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
35
37 "ch", ///< the value of the current channel
38 "n", ///< number of frame
39 "nb_in_channels",
40 "nb_out_channels",
41 "t", ///< timestamp expressed in seconds
42 "s", ///< sample rate
43 NULL
44 };
45
54 };
55
68 int nb_samples;
///< number of samples per requested frame
75
76 static double val(
void *priv,
double ch)
77 {
80 }
81
84
85 #define OFFSET(x) offsetof(EvalContext, x)
86 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
87
90 {
"nb_samples",
"set the number of samples per requested frame",
OFFSET(nb_samples),
AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX,
FLAGS },
91 {
"n",
"set the number of samples per requested frame",
OFFSET(nb_samples),
AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX,
FLAGS },
98 { NULL }
99 };
100
102
104 int expected_nb_channels)
105 {
108 char *expr, *last_expr = NULL, *
buf;
109 double (*
const *
func1)(
void *, double) = NULL;
112
113 if (!args1)
115
119 }
120
124 }
125
126 #define ADD_EXPRESSION(expr_) do { \
127 if (!av_dynarray2_add((void **)&eval->expr, &eval->nb_channels, \
128 sizeof(*eval->expr), NULL)) { \
129 ret = AVERROR(ENOMEM); \
130 goto end; \
131 } \
132 eval->expr[eval->nb_channels-1] = NULL; \
133 ret = av_expr_parse(&eval->expr[eval->nb_channels - 1], expr_, \
134 var_names, func1_names, func1, \
135 NULL, NULL, 0, ctx); \
136 if (ret < 0) \
137 goto end; \
138 } while (0)
139
140 /* reset expressions */
143 eval->
expr[i] = NULL;
144 }
147
148 buf = args1;
149 while (expr =
av_strtok(buf,
"|", &buf)) {
151 last_expr = expr;
152 }
153
155 for (i = eval->
nb_channels; i < expected_nb_channels; i++)
157
158 if (expected_nb_channels > 0 && eval->
nb_channels != expected_nb_channels) {
160 "Mismatch between the specified number of channel expressions '%d' "
161 "and the number of expected output channels '%d' for the specified channel layout\n",
165 }
166
170 }
171
173 {
176
180 } else {
182 if (ret < 0)
184
186 if (ret < 0)
188 }
189 } else {
190 /* guess channel layout from nb expressions/channels */
193
199 }
200 }
201
206
208 }
209
211 {
213 int i;
214
217 eval->
expr[i] = NULL;
218 }
220 }
221
223 {
226
229
233
235
237 "sample_rate:%d chlayout:%s duration:%"PRId64"\n",
239
240 return 0;
241 }
242
244 {
249
253
254 return 0;
255 }
256
258 {
261 int i, j;
263
266
268 if (!samplesref)
270
271 /* evaluate expression for each single sample and for each channel */
272 for (i = 0; i < eval->
nb_samples; i++, eval->
n++) {
275
279 }
280 }
281
282 samplesref->
pts = eval->
pts;
285
287 }
288
289 #if CONFIG_AEVALSRC_FILTER
291 {
296 },
297 { NULL }
298 };
299
309 .priv_class = &aevalsrc_class,
310 };
311
312 #endif /* CONFIG_AEVALSRC_FILTER */
313
314 #define OFFSET(x) offsetof(EvalContext, x)
315 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
316
321 { NULL }
322 };
323
325
327 {
335 };
336
337 // inlink supports any channel layout
340
343 if (!layouts)
346 } else {
347 // outlink supports only requested output channel layout
348 layouts = NULL;
353 }
354
356 if (!formats)
359
361 if (!formats)
364
365 return 0;
366 }
367
369 {
374
377
380 }
381
387
392
393 return 0;
394 }
395
396 #define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
397
399 {
405 int i, j;
406
407 /* do volume scaling in-place if input buffer is writable */
409 if (!out)
412
414
415 /* evaluate expression for each single sample and for each channel */
416 for (i = 0; i < nb_samples; i++, eval->
n++) {
419
422
423 for (j = 0; j < outlink->
channels; j++) {
427 }
428 }
429
432 }
433
434 #if CONFIG_AEVAL_FILTER
435
437 {
441 },
442 { NULL }
443 };
444
446 {
450 },
451 { NULL }
452 };
453
456 .description =
NULL_IF_CONFIG_SMALL(
"Filter audio signal according to a specified expression."),
463 .priv_class = &aeval_class,
464 };
465
466 #endif /* CONFIG_AEVAL_FILTER */