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
00099 buf = args1;
00100 i = 0;
00101 while (expr = av_strtok(buf, ":", &bufptr)) {
00102 if (i >= 8) {
00103 av_log(ctx, AV_LOG_ERROR,
00104 "More than 8 expressions provided, unsupported.\n");
00105 ret = AVERROR(EINVAL);
00106 return ret;
00107 }
00108 ret = av_expr_parse(&eval->expr[i], expr, var_names,
00109 NULL, NULL, NULL, NULL, 0, ctx);
00110 if (ret < 0)
00111 goto end;
00112 i++;
00113 if (bufptr && *bufptr == ':') {
00114 bufptr++;
00115 break;
00116 }
00117 buf = NULL;
00118 }
00119
00120
00121 eval->nb_channels = i;
00122 eval->chlayout = av_get_default_channel_layout(eval->nb_channels);
00123 if (!eval->chlayout) {
00124 av_log(ctx, AV_LOG_ERROR, "Invalid number of channels '%d' provided\n",
00125 eval->nb_channels);
00126 ret = AVERROR(EINVAL);
00127 goto end;
00128 }
00129
00130 if (bufptr && (ret = av_set_options_string(eval, bufptr, "=", ":")) < 0)
00131 goto end;
00132
00133 if ((ret = ff_parse_sample_rate(&eval->sample_rate, eval->sample_rate_str, ctx)))
00134 goto end;
00135
00136 eval->duration = -1;
00137 if (eval->duration_str) {
00138 int64_t us = -1;
00139 if ((ret = av_parse_time(&us, eval->duration_str, 1)) < 0) {
00140 av_log(ctx, AV_LOG_ERROR, "Invalid duration: '%s'\n", eval->duration_str);
00141 goto end;
00142 }
00143 eval->duration = (double)us / 1000000;
00144 }
00145 eval->n = 0;
00146
00147 end:
00148 av_free(args1);
00149 return ret;
00150 }
00151
00152 static void uninit(AVFilterContext *ctx)
00153 {
00154 EvalContext *eval = ctx->priv;
00155 int i;
00156
00157 for (i = 0; i < 8; i++) {
00158 av_expr_free(eval->expr[i]);
00159 eval->expr[i] = NULL;
00160 }
00161 av_freep(&eval->duration_str);
00162 av_freep(&eval->sample_rate_str);
00163 }
00164
00165 static int config_props(AVFilterLink *outlink)
00166 {
00167 EvalContext *eval = outlink->src->priv;
00168 char buf[128];
00169
00170 outlink->time_base = (AVRational){1, eval->sample_rate};
00171 outlink->sample_rate = eval->sample_rate;
00172
00173 eval->var_values[VAR_S] = eval->sample_rate;
00174
00175 av_get_channel_layout_string(buf, sizeof(buf), 0, eval->chlayout);
00176
00177 av_log(outlink->src, AV_LOG_INFO,
00178 "sample_rate:%d chlayout:%s duration:%f\n",
00179 eval->sample_rate, buf, eval->duration);
00180
00181 return 0;
00182 }
00183
00184 static int query_formats(AVFilterContext *ctx)
00185 {
00186 EvalContext *eval = ctx->priv;
00187 enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_NONE };
00188 int64_t chlayouts[] = { eval->chlayout, -1 };
00189 int packing_fmts[] = { AVFILTER_PLANAR, -1 };
00190
00191 avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
00192 avfilter_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
00193 avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts));
00194
00195 return 0;
00196 }
00197
00198 static int request_frame(AVFilterLink *outlink)
00199 {
00200 EvalContext *eval = outlink->src->priv;
00201 AVFilterBufferRef *samplesref;
00202 int i, j;
00203 double t = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
00204
00205 if (eval->duration >= 0 && t > eval->duration)
00206 return AVERROR_EOF;
00207
00208 samplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, eval->nb_samples);
00209
00210
00211 for (i = 0; i < eval->nb_samples; i++, eval->n++) {
00212 eval->var_values[VAR_N] = eval->n;
00213 eval->var_values[VAR_T] = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
00214
00215 for (j = 0; j < eval->nb_channels; j++) {
00216 *((double *) samplesref->data[j] + i) =
00217 av_expr_eval(eval->expr[j], eval->var_values, NULL);
00218 }
00219 }
00220
00221 samplesref->pts = eval->pts;
00222 samplesref->pos = -1;
00223 samplesref->audio->sample_rate = eval->sample_rate;
00224 eval->pts += eval->nb_samples;
00225
00226 avfilter_filter_samples(outlink, samplesref);
00227
00228 return 0;
00229 }
00230
00231 AVFilter avfilter_asrc_aevalsrc = {
00232 .name = "aevalsrc",
00233 .description = NULL_IF_CONFIG_SMALL("Generate an audio signal generated by an expression."),
00234
00235 .query_formats = query_formats,
00236 .init = init,
00237 .uninit = uninit,
00238 .priv_size = sizeof(EvalContext),
00239
00240 .inputs = (const AVFilterPad[]) {{ .name = NULL}},
00241
00242 .outputs = (const AVFilterPad[]) {{ .name = "default",
00243 .type = AVMEDIA_TYPE_AUDIO,
00244 .config_props = config_props,
00245 .request_frame = request_frame, },
00246 { .name = NULL}},
00247 };