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:
parent
a124f4ebff
commit
d8147c4e2d
@ -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
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user