[FFmpeg-devel] [PATCH] libavfilter/af_amix: fixed amix format when graph load

Shiqi Zhu hiccupzhu at gmail.com
Mon Dec 9 03:28:36 EET 2024


Signed-off-by: Shiqi Zhu <hiccupzhu at gmail.com>
---
 libavfilter/af_amix.c | 64 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 57 insertions(+), 7 deletions(-)

diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c
index bc97200926..3a74ff4772 100644
--- a/libavfilter/af_amix.c
+++ b/libavfilter/af_amix.c
@@ -44,6 +44,7 @@
 #include "audio.h"
 #include "avfilter.h"
 #include "filters.h"
+#include "formats.h"
 
 #define INPUT_ON       1    /**< input is active */
 #define INPUT_EOF      2    /**< input has reached EOF (may still be active) */
@@ -165,7 +166,8 @@ typedef struct MixContext {
     char *weights_str;          /**< string for custom weights for every input */
     int normalize;              /**< if inputs are scaled */
 
-    int nb_channels;            /**< number of channels */
+    enum AVSampleFormat sample_fmt;  /**< sample format */
+    AVChannelLayout ch_layout;  /**< channel layout */
     int sample_rate;            /**< sample rate */
     int planar;
     AVAudioFifo **fifos;        /**< audio fifo for each input */
@@ -197,6 +199,12 @@ static const AVOption amix_options[] = {
             OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, A|F|T },
     { "normalize", "Scale inputs",
             OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, A|F|T },
+    { "sample_rate", "sample_rate",
+            OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=0}, -1, INT32_MAX, A|F },
+    { "ch_layout", "ch_layout",
+            OFFSET(ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, 0, 0, A|F },
+    { "sample_fmt", "sample_fmt",
+            OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64=AV_SAMPLE_FMT_NONE}, -1, INT_MAX, A|F },
     { NULL }
 };
 
@@ -260,9 +268,15 @@ static int config_output(AVFilterLink *outlink)
     if (!s->fifos)
         return AVERROR(ENOMEM);
 
-    s->nb_channels = outlink->ch_layout.nb_channels;
+    if (s->ch_layout.nb_channels == 0)
+        av_channel_layout_copy(&s->ch_layout, &outlink->ch_layout);
+    if (av_channel_layout_compare(&s->ch_layout, &outlink->ch_layout)) {
+        av_log(ctx, AV_LOG_ERROR, "Output channel layouts do not match\n");
+        return AVERROR(EINVAL);
+    }
+
     for (i = 0; i < s->nb_inputs; i++) {
-        s->fifos[i] = av_audio_fifo_alloc(outlink->format, s->nb_channels, 1024);
+        s->fifos[i] = av_audio_fifo_alloc(outlink->format, s->ch_layout.nb_channels, 1024);
         if (!s->fifos[i])
             return AVERROR(ENOMEM);
     }
@@ -356,8 +370,8 @@ static int output_frame(AVFilterLink *outlink)
             av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data,
                                nb_samples);
 
-            planes     = s->planar ? s->nb_channels : 1;
-            plane_size = nb_samples * (s->planar ? 1 : s->nb_channels);
+            planes     = s->planar ? s->ch_layout.nb_channels : 1;
+            plane_size = nb_samples * (s->planar ? 1 : s->ch_layout.nb_channels);
             plane_size = FFALIGN(plane_size, 16);
 
             if (out_buf->format == AV_SAMPLE_FMT_FLT ||
@@ -608,6 +622,43 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
     return 0;
 }
 
+static int query_formats(const AVFilterContext *ctx,
+                         AVFilterFormatsConfig **cfg_in,
+                         AVFilterFormatsConfig **cfg_out)
+{
+    const enum AVSampleFormat sample_fmts[] = {
+        AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
+        AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP,
+        AV_SAMPLE_FMT_NONE
+    };
+    MixContext *s = ctx->priv;
+    int ret;
+
+    if (s->sample_fmt != AV_SAMPLE_FMT_NONE) {
+        if ((ret = ff_set_common_formats2(ctx, cfg_in, cfg_out, ff_make_formats_list_singleton(s->sample_fmt))) < 0)
+            return ret;
+    } else {
+        if ((ret = ff_set_common_formats2(ctx, cfg_in, cfg_out, ff_make_format_list(sample_fmts))) < 0)
+            return ret;
+    }
+
+    if (s->sample_rate) {
+        int sample_rates[] = { s->sample_rate, -1 };
+        if ((ret = ff_set_common_samplerates2(ctx, cfg_in, cfg_out, ff_make_format_list(sample_rates))) < 0)
+            return ret;
+    } else {
+        if ((ret = ff_set_common_samplerates2(ctx, cfg_in, cfg_out, ff_all_samplerates())) < 0)
+            return ret;
+    }
+
+    if (s->ch_layout.nb_channels) {
+        const AVChannelLayout layout_list[] = { s->ch_layout, { 0 } };
+        return ff_set_common_channel_layouts2(ctx, cfg_in, cfg_out, ff_make_channel_layout_list(layout_list));
+    } else {
+        return ff_set_common_channel_layouts2(ctx, cfg_in, cfg_out, ff_all_channel_counts());
+    }
+}
+
 static const AVFilterPad avfilter_af_amix_outputs[] = {
     {
         .name          = "default",
@@ -626,8 +677,7 @@ const AVFilter ff_af_amix = {
     .activate       = activate,
     .inputs         = NULL,
     FILTER_OUTPUTS(avfilter_af_amix_outputs),
-    FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
-                      AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP),
+    FILTER_QUERY_FUNC2(query_formats),
     .process_command = process_command,
     .flags          = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
-- 
2.34.1



More information about the ffmpeg-devel mailing list