mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
lavfi/aevalsrc: switch to an AVOptions-based system.
This commit is contained in:
parent
94d13df34c
commit
64ce15b9f4
@ -1496,18 +1496,13 @@ This source accepts in input one or more expressions (one for each
|
|||||||
channel), which are evaluated and used to generate a corresponding
|
channel), which are evaluated and used to generate a corresponding
|
||||||
audio signal.
|
audio signal.
|
||||||
|
|
||||||
It accepts the syntax: @var{exprs}[::@var{options}].
|
This source accepts the following options:
|
||||||
@var{exprs} is a list of expressions separated by ":", one for each
|
|
||||||
separate channel. In case the @var{channel_layout} is not
|
|
||||||
specified, the selected channel layout depends on the number of
|
|
||||||
provided expressions.
|
|
||||||
|
|
||||||
@var{options} is an optional sequence of @var{key}=@var{value} pairs,
|
|
||||||
separated by ":".
|
|
||||||
|
|
||||||
The description of the accepted options follows.
|
|
||||||
|
|
||||||
@table @option
|
@table @option
|
||||||
|
@item exprs
|
||||||
|
Set the '|'-separated expressions list for each separate channel. In case the
|
||||||
|
@option{channel_layout} option is not specified, the selected channel layout
|
||||||
|
depends on the number of provided expressions.
|
||||||
|
|
||||||
@item channel_layout, c
|
@item channel_layout, c
|
||||||
Set the channel layout. The number of channels in the specified layout
|
Set the channel layout. The number of channels in the specified layout
|
||||||
@ -1558,14 +1553,14 @@ aevalsrc=0
|
|||||||
Generate a sin signal with frequency of 440 Hz, set sample rate to
|
Generate a sin signal with frequency of 440 Hz, set sample rate to
|
||||||
8000 Hz:
|
8000 Hz:
|
||||||
@example
|
@example
|
||||||
aevalsrc="sin(440*2*PI*t)::s=8000"
|
aevalsrc="sin(440*2*PI*t):s=8000"
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Generate a two channels signal, specify the channel layout (Front
|
Generate a two channels signal, specify the channel layout (Front
|
||||||
Center + Back Center) explicitly:
|
Center + Back Center) explicitly:
|
||||||
@example
|
@example
|
||||||
aevalsrc="sin(420*2*PI*t):cos(430*2*PI*t)::c=FC|BC"
|
aevalsrc="sin(420*2*PI*t)|cos(430*2*PI*t):c=FC|BC"
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@item
|
@item
|
||||||
@ -1583,7 +1578,7 @@ aevalsrc="sin(10*2*PI*t)*sin(880*2*PI*t)"
|
|||||||
@item
|
@item
|
||||||
Generate 2.5 Hz binaural beats on a 360 Hz carrier:
|
Generate 2.5 Hz binaural beats on a 360 Hz carrier:
|
||||||
@example
|
@example
|
||||||
aevalsrc="0.1*sin(2*PI*(360-2.5/2)*t) : 0.1*sin(2*PI*(360+2.5/2)*t)"
|
aevalsrc="0.1*sin(2*PI*(360-2.5/2)*t) | 0.1*sin(2*PI*(360+2.5/2)*t)"
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@end itemize
|
@end itemize
|
||||||
|
@ -56,7 +56,7 @@ typedef struct {
|
|||||||
int nb_channels;
|
int nb_channels;
|
||||||
int64_t pts;
|
int64_t pts;
|
||||||
AVExpr *expr[8];
|
AVExpr *expr[8];
|
||||||
char *expr_str[8];
|
char *exprs;
|
||||||
int nb_samples; ///< number of samples per requested frame
|
int nb_samples; ///< number of samples per requested frame
|
||||||
char *duration_str; ///< total duration of the generated audio
|
char *duration_str; ///< total duration of the generated audio
|
||||||
double duration;
|
double duration;
|
||||||
@ -68,6 +68,7 @@ typedef struct {
|
|||||||
#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
|
#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
|
||||||
|
|
||||||
static const AVOption aevalsrc_options[]= {
|
static const AVOption aevalsrc_options[]= {
|
||||||
|
{ "exprs", "set the '|'-separated list of channels expressions", OFFSET(exprs), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS },
|
||||||
{ "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS },
|
{ "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS },
|
||||||
{ "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS },
|
{ "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS },
|
||||||
{ "sample_rate", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS },
|
{ "sample_rate", "set the sample rate", OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS },
|
||||||
@ -84,15 +85,12 @@ AVFILTER_DEFINE_CLASS(aevalsrc);
|
|||||||
static int init(AVFilterContext *ctx, const char *args)
|
static int init(AVFilterContext *ctx, const char *args)
|
||||||
{
|
{
|
||||||
EvalContext *eval = ctx->priv;
|
EvalContext *eval = ctx->priv;
|
||||||
char *args1 = av_strdup(args);
|
char *args1 = av_strdup(eval->exprs);
|
||||||
char *expr, *buf, *bufptr;
|
char *expr, *buf;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
eval->class = &aevalsrc_class;
|
|
||||||
av_opt_set_defaults(eval);
|
|
||||||
|
|
||||||
if (!args1) {
|
if (!args1) {
|
||||||
av_log(ctx, AV_LOG_ERROR, "Argument is empty\n");
|
av_log(ctx, AV_LOG_ERROR, "Channels expressions list is empty\n");
|
||||||
ret = args ? AVERROR(ENOMEM) : AVERROR(EINVAL);
|
ret = args ? AVERROR(ENOMEM) : AVERROR(EINVAL);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -100,23 +98,15 @@ static int init(AVFilterContext *ctx, const char *args)
|
|||||||
/* parse expressions */
|
/* parse expressions */
|
||||||
buf = args1;
|
buf = args1;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (expr = av_strtok(buf, ":", &bufptr)) {
|
while (i < FF_ARRAY_ELEMS(eval->expr) && (expr = av_strtok(buf, "|", &buf))) {
|
||||||
ret = av_expr_parse(&eval->expr[i], expr, var_names,
|
ret = av_expr_parse(&eval->expr[i], expr, var_names,
|
||||||
NULL, NULL, NULL, NULL, 0, ctx);
|
NULL, NULL, NULL, NULL, 0, ctx);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto end;
|
goto end;
|
||||||
i++;
|
i++;
|
||||||
if (bufptr && *bufptr == ':') { /* found last expression */
|
|
||||||
bufptr++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf = NULL;
|
|
||||||
}
|
}
|
||||||
eval->nb_channels = i;
|
eval->nb_channels = i;
|
||||||
|
|
||||||
if (bufptr && (ret = av_set_options_string(eval, bufptr, "=", ":")) < 0)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (eval->chlayout_str) {
|
if (eval->chlayout_str) {
|
||||||
int n;
|
int n;
|
||||||
ret = ff_parse_channel_layout(&eval->chlayout, eval->chlayout_str, ctx);
|
ret = ff_parse_channel_layout(&eval->chlayout, eval->chlayout_str, ctx);
|
||||||
|
@ -674,7 +674,6 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options,
|
|||||||
static const char *const filters_left_to_update[] = {
|
static const char *const filters_left_to_update[] = {
|
||||||
"abuffer",
|
"abuffer",
|
||||||
"aconvert",
|
"aconvert",
|
||||||
"aevalsrc",
|
|
||||||
"amerge",
|
"amerge",
|
||||||
"aresample",
|
"aresample",
|
||||||
"atempo",
|
"atempo",
|
||||||
@ -757,7 +756,8 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
|
|||||||
!strcmp(filter->filter->name, "frei0r") ||
|
!strcmp(filter->filter->name, "frei0r") ||
|
||||||
!strcmp(filter->filter->name, "frei0r_src") ||
|
!strcmp(filter->filter->name, "frei0r_src") ||
|
||||||
!strcmp(filter->filter->name, "ocv") ||
|
!strcmp(filter->filter->name, "ocv") ||
|
||||||
!strcmp(filter->filter->name, "pp")) {
|
!strcmp(filter->filter->name, "pp") ||
|
||||||
|
!strcmp(filter->filter->name, "aevalsrc")) {
|
||||||
/* a hack for compatibility with the old syntax
|
/* a hack for compatibility with the old syntax
|
||||||
* replace colons with |s */
|
* replace colons with |s */
|
||||||
char *copy = av_strdup(args);
|
char *copy = av_strdup(args);
|
||||||
@ -789,9 +789,24 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
|
|||||||
"'|' to separate the list items.\n");
|
"'|' to separate the list items.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(filter->filter->name, "aevalsrc")) {
|
||||||
|
while ((p = strchr(p, ':')) && p[1] != ':') {
|
||||||
|
const char *epos = strchr(p + 1, '=');
|
||||||
|
const char *spos = strchr(p + 1, ':');
|
||||||
|
const int next_token_is_opt = epos && (!spos || epos < spos);
|
||||||
|
if (next_token_is_opt) {
|
||||||
|
p++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*p++ = '|';
|
||||||
|
}
|
||||||
|
if (p && *p == ':')
|
||||||
|
memmove(p, p + 1, strlen(p));
|
||||||
|
} else
|
||||||
while ((p = strchr(p, ':')))
|
while ((p = strchr(p, ':')))
|
||||||
*p++ = '|';
|
*p++ = '|';
|
||||||
|
|
||||||
|
av_log(filter, AV_LOG_DEBUG, "compat: called with args=[%s]\n", copy);
|
||||||
ret = process_options(filter, &options, copy);
|
ret = process_options(filter, &options, copy);
|
||||||
av_freep(©);
|
av_freep(©);
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ tests/data/vsynth2.yuv: tests/rotozoom$(HOSTEXESUF) | tests/data
|
|||||||
|
|
||||||
tests/data/ffprobe-test.nut: ffmpeg$(EXESUF) | tests/data
|
tests/data/ffprobe-test.nut: ffmpeg$(EXESUF) | tests/data
|
||||||
$(M)$(TARGET_EXEC) ./$< \
|
$(M)$(TARGET_EXEC) ./$< \
|
||||||
-f lavfi -i "aevalsrc=sin(400*PI*2*t)::d=0.125[out0]; testsrc=d=0.125[out1]; testsrc=s=100x100:d=0.125[out2]" \
|
-f lavfi -i "aevalsrc=sin(400*PI*2*t):d=0.125[out0]; testsrc=d=0.125[out1]; testsrc=s=100x100:d=0.125[out2]" \
|
||||||
-f ffmetadata -i $(SRC_PATH)/tests/test.ffmeta \
|
-f ffmetadata -i $(SRC_PATH)/tests/test.ffmeta \
|
||||||
-flags +bitexact -map 0:0 -map 0:1 -map 0:2 -map_metadata 1 \
|
-flags +bitexact -map 0:0 -map 0:1 -map 0:2 -map_metadata 1 \
|
||||||
-map_metadata:s:0 1:s:0 -map_metadata:s:1 1:s:1 \
|
-map_metadata:s:0 1:s:0 -map_metadata:s:1 1:s:1 \
|
||||||
|
Loading…
Reference in New Issue
Block a user