]> git.sesse.net Git - ffmpeg/commitdiff
avfilter/af_amix: make weights option runtime configured
authorPaul B Mahol <onemda@gmail.com>
Tue, 28 Apr 2020 10:01:04 +0000 (12:01 +0200)
committerPaul B Mahol <onemda@gmail.com>
Wed, 29 Apr 2020 17:18:25 +0000 (19:18 +0200)
doc/filters.texi
libavfilter/af_amix.c

index ce200aa314bc88f46c3f86fb3c576e91cad7f383..3be83533bb5bfea758f221df217fe7ad7bb2eae7 100644 (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.
 @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
 
 Multiply first audio stream with second audio stream and store result
index c09f8b034b16bd7026d62751de4666e9e9836c87..0826fc118ca7659ff64f3e2e0130969949c1db1a 100644 (file)
@@ -181,6 +181,7 @@ typedef struct MixContext {
 #define OFFSET(x) offsetof(MixContext, x)
 #define A AV_OPT_FLAG_AUDIO_PARAM
 #define F AV_OPT_FLAG_FILTERING_PARAM
+#define T AV_OPT_FLAG_RUNTIME_PARAM
 static const AVOption amix_options[] = {
     { "inputs", "Number of inputs.",
             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.",
             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 },
+            OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, A|F|T },
     { NULL }
 };
 
@@ -504,12 +505,37 @@ static int activate(AVFilterContext *ctx)
     return 0;
 }
 
-static av_cold int init(AVFilterContext *ctx)
+static void parse_weights(AVFilterContext *ctx)
 {
     MixContext *s = ctx->priv;
     float last_weight = 1.f;
-    int i, ret;
     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++) {
         AVFilterPad pad = { 0 };
@@ -533,23 +559,7 @@ static av_cold int init(AVFilterContext *ctx)
     if (!s->weights)
         return AVERROR(ENOMEM);
 
-    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);
-    }
+    parse_weights(ctx);
 
     return 0;
 }
@@ -604,6 +614,24 @@ fail:
     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[] = {
     {
         .name          = "default",
@@ -624,5 +652,6 @@ AVFilter ff_af_amix = {
     .query_formats  = query_formats,
     .inputs         = NULL,
     .outputs        = avfilter_af_amix_outputs,
+    .process_command = process_command,
     .flags          = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };