asrc_aevalsrc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Stefano Sabatini
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * eval audio source
24  */
25 
26 #include "libavutil/avassert.h"
27 #include "libavutil/avstring.h"
29 #include "libavutil/eval.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/parseutils.h"
32 #include "avfilter.h"
33 #include "audio.h"
34 #include "internal.h"
35 
36 static const char * const var_names[] = {
37  "n", ///< number of frame
38  "t", ///< timestamp expressed in seconds
39  "s", ///< sample rate
40  NULL
41 };
42 
43 enum var_name {
48 };
49 
50 typedef struct {
51  const AVClass *class;
54  int64_t chlayout;
55  char *chlayout_str;
57  int64_t pts;
58  AVExpr *expr[8];
59  char *exprs;
60  int nb_samples; ///< number of samples per requested frame
61  char *duration_str; ///< total duration of the generated audio
62  double duration;
63  uint64_t n;
64  double var_values[VAR_VARS_NB];
65 } EvalContext;
66 
67 #define OFFSET(x) offsetof(EvalContext, x)
68 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
69 
70 static const AVOption aevalsrc_options[]= {
71  { "exprs", "set the '|'-separated list of channels expressions", OFFSET(exprs), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS },
72  { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS },
73  { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS },
74  { "sample_rate", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS },
75  { "s", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS },
76  { "duration", "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
77  { "d", "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
78  { "channel_layout", "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
79  { "c", "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
80 {NULL},
81 };
82 
83 AVFILTER_DEFINE_CLASS(aevalsrc);
84 
85 static int init(AVFilterContext *ctx)
86 {
87  EvalContext *eval = ctx->priv;
88  char *args1 = av_strdup(eval->exprs);
89  char *expr, *buf;
90  int ret, i;
91 
92  if (!args1) {
93  av_log(ctx, AV_LOG_ERROR, "Channels expressions list is empty\n");
94  ret = eval->exprs ? AVERROR(ENOMEM) : AVERROR(EINVAL);
95  goto end;
96  }
97 
98  /* parse expressions */
99  buf = args1;
100  i = 0;
101  while (i < FF_ARRAY_ELEMS(eval->expr) && (expr = av_strtok(buf, "|", &buf))) {
102  ret = av_expr_parse(&eval->expr[i], expr, var_names,
103  NULL, NULL, NULL, NULL, 0, ctx);
104  if (ret < 0)
105  goto end;
106  i++;
107  }
108  eval->nb_channels = i;
109 
110  if (eval->chlayout_str) {
111  int n;
112  ret = ff_parse_channel_layout(&eval->chlayout, eval->chlayout_str, ctx);
113  if (ret < 0)
114  goto end;
115 
117  if (n != eval->nb_channels) {
118  av_log(ctx, AV_LOG_ERROR,
119  "Mismatch between the specified number of channels '%d' "
120  "and the number of channels '%d' in the specified channel layout '%s'\n",
121  eval->nb_channels, n, eval->chlayout_str);
122  ret = AVERROR(EINVAL);
123  goto end;
124  }
125  } else {
126  /* guess channel layout from nb expressions/channels */
128  if (!eval->chlayout) {
129  av_log(ctx, AV_LOG_ERROR, "Invalid number of channels '%d' provided\n",
130  eval->nb_channels);
131  ret = AVERROR(EINVAL);
132  goto end;
133  }
134  }
135 
136  if ((ret = ff_parse_sample_rate(&eval->sample_rate, eval->sample_rate_str, ctx)))
137  goto end;
138 
139  eval->duration = -1;
140  if (eval->duration_str) {
141  int64_t us = -1;
142  if ((ret = av_parse_time(&us, eval->duration_str, 1)) < 0) {
143  av_log(ctx, AV_LOG_ERROR, "Invalid duration: '%s'\n", eval->duration_str);
144  goto end;
145  }
146  eval->duration = (double)us / 1000000;
147  }
148  eval->n = 0;
149 
150 end:
151  av_free(args1);
152  return ret;
153 }
154 
155 static void uninit(AVFilterContext *ctx)
156 {
157  EvalContext *eval = ctx->priv;
158  int i;
159 
160  for (i = 0; i < 8; i++) {
161  av_expr_free(eval->expr[i]);
162  eval->expr[i] = NULL;
163  }
164  av_freep(&eval->chlayout_str);
165  av_freep(&eval->duration_str);
166  av_freep(&eval->sample_rate_str);
167 }
168 
169 static int config_props(AVFilterLink *outlink)
170 {
171  EvalContext *eval = outlink->src->priv;
172  char buf[128];
173 
174  outlink->time_base = (AVRational){1, eval->sample_rate};
175  outlink->sample_rate = eval->sample_rate;
176 
177  eval->var_values[VAR_S] = eval->sample_rate;
178 
179  av_get_channel_layout_string(buf, sizeof(buf), 0, eval->chlayout);
180 
181  av_log(outlink->src, AV_LOG_VERBOSE,
182  "sample_rate:%d chlayout:%s duration:%f\n",
183  eval->sample_rate, buf, eval->duration);
184 
185  return 0;
186 }
187 
189 {
190  EvalContext *eval = ctx->priv;
192  int64_t chlayouts[] = { eval->chlayout, -1 };
193  int sample_rates[] = { eval->sample_rate, -1 };
194 
195  ff_set_common_formats (ctx, ff_make_format_list(sample_fmts));
198 
199  return 0;
200 }
201 
202 static int request_frame(AVFilterLink *outlink)
203 {
204  EvalContext *eval = outlink->src->priv;
205  AVFrame *samplesref;
206  int i, j;
207  double t = eval->n * (double)1/eval->sample_rate;
208 
209  if (eval->duration >= 0 && t >= eval->duration)
210  return AVERROR_EOF;
211 
212  samplesref = ff_get_audio_buffer(outlink, eval->nb_samples);
213  if (!samplesref)
214  return AVERROR(ENOMEM);
215 
216  /* evaluate expression for each single sample and for each channel */
217  for (i = 0; i < eval->nb_samples; i++, eval->n++) {
218  eval->var_values[VAR_N] = eval->n;
219  eval->var_values[VAR_T] = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
220 
221  for (j = 0; j < eval->nb_channels; j++) {
222  *((double *) samplesref->extended_data[j] + i) =
223  av_expr_eval(eval->expr[j], eval->var_values, NULL);
224  }
225  }
226 
227  samplesref->pts = eval->pts;
228  samplesref->sample_rate = eval->sample_rate;
229  eval->pts += eval->nb_samples;
230 
231  return ff_filter_frame(outlink, samplesref);
232 }
233 
234 static const AVFilterPad aevalsrc_outputs[] = {
235  {
236  .name = "default",
237  .type = AVMEDIA_TYPE_AUDIO,
238  .config_props = config_props,
239  .request_frame = request_frame,
240  },
241  { NULL }
242 };
243 
245  .name = "aevalsrc",
246  .description = NULL_IF_CONFIG_SMALL("Generate an audio signal generated by an expression."),
247 
248  .query_formats = query_formats,
249  .init = init,
250  .uninit = uninit,
251  .priv_size = sizeof(EvalContext),
252  .inputs = NULL,
253  .outputs = aevalsrc_outputs,
254  .priv_class = &aevalsrc_class,
255 };
static const AVFilterPad aevalsrc_outputs[]
char * exprs
Definition: asrc_aevalsrc.c:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
AVOption.
Definition: opt.h:251
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:117
external API header
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition: parseutils.c:530
double duration
Definition: asrc_aevalsrc.c:62
#define FF_ARRAY_ELEMS(a)
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:640
char * chlayout_str
Definition: asrc_aevalsrc.c:55
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:308
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
const char * name
Pad name.
it can be given away to ff_start_frame *A reference passed to ff_filter_frame(or the deprecated ff_start_frame) is given away and must no longer be used.*A reference created with avfilter_ref_buffer belongs to the code that created it.*A reference obtained with ff_get_video_buffer or ff_get_audio_buffer belongs to the code that requested it.*A reference given as return value by the get_video_buffer or get_audio_buffer method is given away and must no longer be used.Link reference fields---------------------The AVFilterLink structure has a few AVFilterBufferRef fields.The cur_buf and out_buf were used with the deprecated start_frame/draw_slice/end_frame API and should no longer be used.src_buf
AVOptions.
end end
static void uninit(AVFilterContext *ctx)
int nb_samples
number of samples per requested frame
Definition: asrc_aevalsrc.c:60
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:159
Definition: eval.c:140
int64_t pts
Definition: asrc_aevalsrc.c:57
#define AVERROR_EOF
End of file.
Definition: error.h:55
void ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:545
A filter pad used for either input or output.
#define FLAGS
Definition: asrc_aevalsrc.c:68
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:84
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void * priv
private data for use by the filter
Definition: avfilter.h:545
uint64_t n
Definition: asrc_aevalsrc.c:63
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
simple assert() macros that are a bit more flexible than ISO C assert().
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int64_t chlayout
Definition: asrc_aevalsrc.c:54
#define AV_LOG_VERBOSE
Definition: log.h:157
struct AVRational AVRational
rational number numerator/denominator
AVExpr * expr[8]
Definition: asrc_aevalsrc.c:58
audio channel layout utility functions
var_name
ret
Definition: avfilter.c:821
t
Definition: genspecsines3.m:6
eval(cmd)
static int request_frame(AVFilterLink *outlink)
NULL
Definition: eval.c:55
AVFilterChannelLayouts * avfilter_make_format64_list(const int64_t *fmts)
Definition: formats.c:317
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:302
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:220
static int query_formats(AVFilterContext *ctx)
char * duration_str
total duration of the generated audio
Definition: asrc_aevalsrc.c:61
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
char * sample_rate_str
Definition: asrc_aevalsrc.c:52
void * buf
Definition: avisynth_c.h:594
Describe the class of an AVClass context structure.
Definition: log.h:50
int sample_rate
Sample rate of the audio data.
Definition: frame.h:326
Filter definition.
Definition: avfilter.h:436
synthesis window for stochastic i
const char * name
filter name
Definition: avfilter.h:437
#define OFFSET(x)
Definition: asrc_aevalsrc.c:67
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
misc parsing utilities
static const char *const var_names[]
Definition: asrc_aevalsrc.c:36
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
Definition: avstring.c:183
void ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:533
static int init(AVFilterContext *ctx)
Definition: asrc_aevalsrc.c:85
int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx)
Parse a channel layout or a corresponding integer representation.
Definition: formats.c:632
AVSampleFormat
Audio Sample Formats.
Definition: samplefmt.h:49
static const AVOption aevalsrc_options[]
Definition: asrc_aevalsrc.c:70
static int config_props(AVFilterLink *outlink)
int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx)
Parse a sample rate.
Definition: formats.c:620
AVFILTER_DEFINE_CLASS(aevalsrc)
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:691
AVFilter avfilter_asrc_aevalsrc
An instance of a filter.
Definition: avfilter.h:524
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:700
void ff_set_common_channel_layouts(AVFilterContext *ctx, AVFilterChannelLayouts *layouts)
A helper for query_formats() which sets all links to the same list of channel layouts/sample rates...
Definition: formats.c:526
internal API functions
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:117
double var_values[VAR_VARS_NB]
Definition: asrc_aevalsrc.c:64
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
double, planar
Definition: samplefmt.h:61
for(j=16;j >0;--j)
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout)
Return a description of a channel layout.
simple arithmetic expression evaluator
int64_t av_get_default_channel_layout(int nb_channels)
Return default channel layout for a given number of channels.