1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

avfilter/af_amix: make weights option runtime configured

This commit is contained in:
Paul B Mahol 2020-04-28 12:01:04 +02:00
parent a124f4ebff
commit d8147c4e2d
2 changed files with 57 additions and 20 deletions

View File

@ -1703,6 +1703,14 @@ Specify weight of each input audio stream as sequence.
Each weight is separated by space. By default all inputs have same weight. Each weight is separated by space. By default all inputs have same weight.
@end table @end table
@subsection Commands
This filter supports the following commands:
@table @option
@item weights
Syntax is same as option with same name.
@end table
@section amultiply @section amultiply
Multiply first audio stream with second audio stream and store result Multiply first audio stream with second audio stream and store result

View File

@ -181,6 +181,7 @@ typedef struct MixContext {
#define OFFSET(x) offsetof(MixContext, x) #define OFFSET(x) offsetof(MixContext, x)
#define A AV_OPT_FLAG_AUDIO_PARAM #define A AV_OPT_FLAG_AUDIO_PARAM
#define F AV_OPT_FLAG_FILTERING_PARAM #define F AV_OPT_FLAG_FILTERING_PARAM
#define T AV_OPT_FLAG_RUNTIME_PARAM
static const AVOption amix_options[] = { static const AVOption amix_options[] = {
{ "inputs", "Number of inputs.", { "inputs", "Number of inputs.",
OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT16_MAX, A|F }, OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT16_MAX, A|F },
@ -193,7 +194,7 @@ static const AVOption amix_options[] = {
"renormalization when an input stream ends.", "renormalization when an input stream ends.",
OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { .dbl = 2.0 }, 0, INT_MAX, A|F }, OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { .dbl = 2.0 }, 0, INT_MAX, A|F },
{ "weights", "Set weight for each input.", { "weights", "Set weight for each input.",
OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, A|F }, OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, A|F|T },
{ NULL } { NULL }
}; };
@ -504,12 +505,37 @@ static int activate(AVFilterContext *ctx)
return 0; return 0;
} }
static av_cold int init(AVFilterContext *ctx) static void parse_weights(AVFilterContext *ctx)
{ {
MixContext *s = ctx->priv; MixContext *s = ctx->priv;
float last_weight = 1.f; float last_weight = 1.f;
int i, ret;
char *p; char *p;
int i;
s->weight_sum = 0.f;
p = s->weights_str;
for (i = 0; i < s->nb_inputs; i++) {
last_weight = av_strtod(p, &p);
s->weights[i] = last_weight;
s->weight_sum += FFABS(last_weight);
if (p && *p) {
p++;
} else {
i++;
break;
}
}
for (; i < s->nb_inputs; i++) {
s->weights[i] = last_weight;
s->weight_sum += FFABS(last_weight);
}
}
static av_cold int init(AVFilterContext *ctx)
{
MixContext *s = ctx->priv;
int i, ret;
for (i = 0; i < s->nb_inputs; i++) { for (i = 0; i < s->nb_inputs; i++) {
AVFilterPad pad = { 0 }; AVFilterPad pad = { 0 };
@ -533,23 +559,7 @@ static av_cold int init(AVFilterContext *ctx)
if (!s->weights) if (!s->weights)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
p = s->weights_str; parse_weights(ctx);
for (i = 0; i < s->nb_inputs; i++) {
last_weight = av_strtod(p, &p);
s->weights[i] = last_weight;
s->weight_sum += FFABS(last_weight);
if (p && *p) {
p++;
} else {
i++;
break;
}
}
for (; i < s->nb_inputs; i++) {
s->weights[i] = last_weight;
s->weight_sum += FFABS(last_weight);
}
return 0; return 0;
} }
@ -604,6 +614,24 @@ fail:
return ret; return ret;
} }
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
char *res, int res_len, int flags)
{
MixContext *s = ctx->priv;
int ret;
ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
if (ret < 0)
return ret;
parse_weights(ctx);
for (int i = 0; i < s->nb_inputs; i++)
s->scale_norm[i] = s->weight_sum / FFABS(s->weights[i]);
calculate_scales(s, 0);
return 0;
}
static const AVFilterPad avfilter_af_amix_outputs[] = { static const AVFilterPad avfilter_af_amix_outputs[] = {
{ {
.name = "default", .name = "default",
@ -624,5 +652,6 @@ AVFilter ff_af_amix = {
.query_formats = query_formats, .query_formats = query_formats,
.inputs = NULL, .inputs = NULL,
.outputs = avfilter_af_amix_outputs, .outputs = avfilter_af_amix_outputs,
.process_command = process_command,
.flags = AVFILTER_FLAG_DYNAMIC_INPUTS, .flags = AVFILTER_FLAG_DYNAMIC_INPUTS,
}; };