00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include "libavutil/audioconvert.h"
00027 #include "libavutil/avassert.h"
00028 #include "libavutil/avstring.h"
00029 #include "libavutil/eval.h"
00030 #include "libavutil/opt.h"
00031 #include "libavutil/parseutils.h"
00032 #include "avfilter.h"
00033 #include "audio.h"
00034 #include "internal.h"
00035
00036 static const char * const var_names[] = {
00037 "n",
00038 "t",
00039 "s",
00040 NULL
00041 };
00042
00043 enum var_name {
00044 VAR_N,
00045 VAR_T,
00046 VAR_S,
00047 VAR_VARS_NB
00048 };
00049
00050 typedef struct {
00051 const AVClass *class;
00052 char *sample_rate_str;
00053 int sample_rate;
00054 int64_t chlayout;
00055 char *chlayout_str;
00056 int nb_channels;
00057 int64_t pts;
00058 AVExpr *expr[8];
00059 char *expr_str[8];
00060 int nb_samples;
00061 char *duration_str;
00062 double duration;
00063 uint64_t n;
00064 double var_values[VAR_VARS_NB];
00065 } EvalContext;
00066
00067 #define OFFSET(x) offsetof(EvalContext, x)
00068
00069 static const AVOption eval_options[]= {
00070 { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.dbl = 1024}, 0, INT_MAX },
00071 { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.dbl = 1024}, 0, INT_MAX },
00072 { "sample_rate", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX },
00073 { "s", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX },
00074 { "duration", "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0 },
00075 { "d", "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0 },
00076 { "channel_layout", "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0 },
00077 { "c", "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0 },
00078 {NULL},
00079 };
00080
00081 static const char *eval_get_name(void *ctx)
00082 {
00083 return "aevalsrc";
00084 }
00085
00086 static const AVClass eval_class = {
00087 "AEvalSrcContext",
00088 eval_get_name,
00089 eval_options
00090 };
00091
00092 static int init(AVFilterContext *ctx, const char *args, void *opaque)
00093 {
00094 EvalContext *eval = ctx->priv;
00095 char *args1 = av_strdup(args);
00096 char *expr, *buf, *bufptr;
00097 int ret, i;
00098
00099 eval->class = &eval_class;
00100 av_opt_set_defaults(eval);
00101
00102
00103 buf = args1;
00104 i = 0;
00105 while (expr = av_strtok(buf, ":", &bufptr)) {
00106 ret = av_expr_parse(&eval->expr[i], expr, var_names,
00107 NULL, NULL, NULL, NULL, 0, ctx);
00108 if (ret < 0)
00109 goto end;
00110 i++;
00111 if (bufptr && *bufptr == ':') {
00112 bufptr++;
00113 break;
00114 }
00115 buf = NULL;
00116 }
00117 eval->nb_channels = i;
00118
00119 if (bufptr && (ret = av_set_options_string(eval, bufptr, "=", ":")) < 0)
00120 goto end;
00121
00122 if (eval->chlayout_str) {
00123 int n;
00124 ret = ff_parse_channel_layout(&eval->chlayout, eval->chlayout_str, ctx);
00125 if (ret < 0)
00126 goto end;
00127
00128 n = av_get_channel_layout_nb_channels(eval->chlayout);
00129 if (n != eval->nb_channels) {
00130 av_log(ctx, AV_LOG_ERROR,
00131 "Mismatch between the specified number of channels '%d' "
00132 "and the number of channels '%d' in the specified channel layout '%s'\n",
00133 eval->nb_channels, n, eval->chlayout_str);
00134 ret = AVERROR(EINVAL);
00135 goto end;
00136 }
00137 } else {
00138
00139 eval->chlayout = av_get_default_channel_layout(eval->nb_channels);
00140 if (!eval->chlayout) {
00141 av_log(ctx, AV_LOG_ERROR, "Invalid number of channels '%d' provided\n",
00142 eval->nb_channels);
00143 ret = AVERROR(EINVAL);
00144 goto end;
00145 }
00146 }
00147
00148 if ((ret = ff_parse_sample_rate(&eval->sample_rate, eval->sample_rate_str, ctx)))
00149 goto end;
00150
00151 eval->duration = -1;
00152 if (eval->duration_str) {
00153 int64_t us = -1;
00154 if ((ret = av_parse_time(&us, eval->duration_str, 1)) < 0) {
00155 av_log(ctx, AV_LOG_ERROR, "Invalid duration: '%s'\n", eval->duration_str);
00156 goto end;
00157 }
00158 eval->duration = (double)us / 1000000;
00159 }
00160 eval->n = 0;
00161
00162 end:
00163 av_free(args1);
00164 return ret;
00165 }
00166
00167 static void uninit(AVFilterContext *ctx)
00168 {
00169 EvalContext *eval = ctx->priv;
00170 int i;
00171
00172 for (i = 0; i < 8; i++) {
00173 av_expr_free(eval->expr[i]);
00174 eval->expr[i] = NULL;
00175 }
00176 av_freep(&eval->chlayout_str);
00177 av_freep(&eval->duration_str);
00178 av_freep(&eval->sample_rate_str);
00179 }
00180
00181 static int config_props(AVFilterLink *outlink)
00182 {
00183 EvalContext *eval = outlink->src->priv;
00184 char buf[128];
00185
00186 outlink->time_base = (AVRational){1, eval->sample_rate};
00187 outlink->sample_rate = eval->sample_rate;
00188
00189 eval->var_values[VAR_S] = eval->sample_rate;
00190
00191 av_get_channel_layout_string(buf, sizeof(buf), 0, eval->chlayout);
00192
00193 av_log(outlink->src, AV_LOG_INFO,
00194 "sample_rate:%d chlayout:%s duration:%f\n",
00195 eval->sample_rate, buf, eval->duration);
00196
00197 return 0;
00198 }
00199
00200 static int query_formats(AVFilterContext *ctx)
00201 {
00202 EvalContext *eval = ctx->priv;
00203 enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE };
00204 int64_t chlayouts[] = { eval->chlayout, -1 };
00205 int sample_rates[] = { eval->sample_rate, -1 };
00206
00207 avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
00208 ff_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
00209 ff_set_common_samplerates(ctx, avfilter_make_format_list(sample_rates));
00210
00211 return 0;
00212 }
00213
00214 static int request_frame(AVFilterLink *outlink)
00215 {
00216 EvalContext *eval = outlink->src->priv;
00217 AVFilterBufferRef *samplesref;
00218 int i, j;
00219 double t = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
00220
00221 if (eval->duration >= 0 && t > eval->duration)
00222 return AVERROR_EOF;
00223
00224 samplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, eval->nb_samples);
00225
00226
00227 for (i = 0; i < eval->nb_samples; i++, eval->n++) {
00228 eval->var_values[VAR_N] = eval->n;
00229 eval->var_values[VAR_T] = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
00230
00231 for (j = 0; j < eval->nb_channels; j++) {
00232 *((double *) samplesref->extended_data[j] + i) =
00233 av_expr_eval(eval->expr[j], eval->var_values, NULL);
00234 }
00235 }
00236
00237 samplesref->pts = eval->pts;
00238 samplesref->pos = -1;
00239 samplesref->audio->sample_rate = eval->sample_rate;
00240 eval->pts += eval->nb_samples;
00241
00242 ff_filter_samples(outlink, samplesref);
00243
00244 return 0;
00245 }
00246
00247 AVFilter avfilter_asrc_aevalsrc = {
00248 .name = "aevalsrc",
00249 .description = NULL_IF_CONFIG_SMALL("Generate an audio signal generated by an expression."),
00250
00251 .query_formats = query_formats,
00252 .init = init,
00253 .uninit = uninit,
00254 .priv_size = sizeof(EvalContext),
00255
00256 .inputs = (const AVFilterPad[]) {{ .name = NULL}},
00257
00258 .outputs = (const AVFilterPad[]) {{ .name = "default",
00259 .type = AVMEDIA_TYPE_AUDIO,
00260 .config_props = config_props,
00261 .request_frame = request_frame, },
00262 { .name = NULL}},
00263 };