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