[FFmpeg-devel] [PATCH] avfilter/af_amix: add weights option
Paul B Mahol
onemda at gmail.com
Thu Mar 29 15:05:12 EEST 2018
Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
doc/filters.texi | 3 +++
libavfilter/af_amix.c | 32 +++++++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index 5c119c0151..6cbb7255f4 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1350,6 +1350,9 @@ The duration of the first input.
The transition time, in seconds, for volume renormalization when an input
stream ends. The default value is 2 seconds.
+ at item weights
+Specify weight of each input audio stream as sequence.
+Each weight is separated by space. By default all inputs have same weight.
@end table
@section anequalizer
diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c
index ec764375c0..9fa504765f 100644
--- a/libavfilter/af_amix.c
+++ b/libavfilter/af_amix.c
@@ -162,6 +162,7 @@ typedef struct MixContext {
int active_inputs; /**< number of input currently active */
int duration_mode; /**< mode for determining duration */
float dropout_transition; /**< transition time when an input drops out */
+ char *weights_str; /**< string for custom weights for every input */
int nb_channels; /**< number of channels */
int sample_rate; /**< sample rate */
@@ -169,6 +170,7 @@ typedef struct MixContext {
AVAudioFifo **fifos; /**< audio fifo for each input */
uint8_t *input_state; /**< current state of each input */
float *input_scale; /**< mixing scale factor for each input */
+ float *weights; /**< custom weights for every input */
float scale_norm; /**< normalization factor for all inputs */
int64_t next_pts; /**< calculated pts for next output frame */
FrameList *frame_list; /**< list of frame info for the first input */
@@ -188,6 +190,8 @@ static const AVOption amix_options[] = {
{ "dropout_transition", "Transition time, in seconds, for volume "
"renormalization when an input stream ends.",
OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { .dbl = 2.0 }, 0, INT_MAX, A|F },
+ { "weights", "Set weight for each input.",
+ OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, A|F },
{ NULL }
};
@@ -202,6 +206,7 @@ AVFILTER_DEFINE_CLASS(amix);
*/
static void calculate_scales(MixContext *s, int nb_samples)
{
+ float weight_sum = 0.f;
int i;
if (s->scale_norm > s->active_inputs) {
@@ -209,9 +214,13 @@ static void calculate_scales(MixContext *s, int nb_samples)
s->scale_norm = FFMAX(s->scale_norm, s->active_inputs);
}
+ for (i = 0; i < s->nb_inputs; i++)
+ if (s->input_state[i] & INPUT_ON)
+ weight_sum += s->weights[i];
+
for (i = 0; i < s->nb_inputs; i++) {
if (s->input_state[i] & INPUT_ON)
- s->input_scale[i] = 1.0f / s->scale_norm;
+ s->input_scale[i] = s->weights[i] / weight_sum * s->active_inputs / s->scale_norm;
else
s->input_scale[i] = 0.0f;
}
@@ -487,6 +496,8 @@ static int activate(AVFilterContext *ctx)
static av_cold int init(AVFilterContext *ctx)
{
MixContext *s = ctx->priv;
+ char *p, *arg, *saveptr = NULL;
+ float last_weight = 1.f;
int i, ret;
for (i = 0; i < s->nb_inputs; i++) {
@@ -507,6 +518,24 @@ static av_cold int init(AVFilterContext *ctx)
if (!s->fdsp)
return AVERROR(ENOMEM);
+ s->weights = av_mallocz_array(s->nb_inputs, sizeof(*s->weights));
+ if (!s->weights)
+ return AVERROR(ENOMEM);
+
+ p = s->weights_str;
+ for (i = 0; i < s->nb_inputs; i++) {
+ if (!(arg = av_strtok(p, " ", &saveptr)))
+ break;
+
+ p = NULL;
+ sscanf(arg, "%f", &last_weight);
+ s->weights[i] = last_weight;
+ }
+
+ for (; i < s->nb_inputs; i++) {
+ s->weights[i] = last_weight;
+ }
+
return 0;
}
@@ -524,6 +553,7 @@ static av_cold void uninit(AVFilterContext *ctx)
av_freep(&s->frame_list);
av_freep(&s->input_state);
av_freep(&s->input_scale);
+ av_freep(&s->weights);
av_freep(&s->fdsp);
for (i = 0; i < ctx->nb_inputs; i++)
--
2.11.0
More information about the ffmpeg-devel
mailing list