[FFmpeg-devel] [PATCH 02/25] lavfi/af_channelsplit: support arbitrary channel layouts

Anton Khirnov anton at khirnov.net
Thu Sep 5 13:07:06 EEST 2024


Not just those containing channel values under 64. Also, remove an
arbitrary limitation on channel count.
---
 libavfilter/af_channelsplit.c | 43 +++++++++++++++++++++++------------
 1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/libavfilter/af_channelsplit.c b/libavfilter/af_channelsplit.c
index 63ffdc3d9b..527c197fa6 100644
--- a/libavfilter/af_channelsplit.c
+++ b/libavfilter/af_channelsplit.c
@@ -34,15 +34,13 @@
 #include "filters.h"
 #include "formats.h"
 
-#define MAX_CH 64
-
 typedef struct ChannelSplitContext {
     const AVClass *class;
 
     AVChannelLayout channel_layout;
     char    *channels_str;
 
-    int      map[64];
+    int     *map;
 } ChannelSplitContext;
 
 #define OFFSET(x) offsetof(ChannelSplitContext, x)
@@ -71,10 +69,9 @@ static av_cold int init(AVFilterContext *ctx)
             goto fail;
     }
 
-    if (channel_layout.nb_channels > MAX_CH) {
-        av_log(ctx, AV_LOG_ERROR, "Too many channels\n");
-        goto fail;
-    }
+    s->map = av_calloc(channel_layout.nb_channels, sizeof(*s->map));
+    if (!s->map)
+        return AVERROR(ENOMEM);
 
     for (i = 0; i < channel_layout.nb_channels; i++) {
         enum AVChannel channel = av_channel_layout_channel_from_index(&channel_layout, i);
@@ -118,6 +115,7 @@ static av_cold void uninit(AVFilterContext *ctx)
     ChannelSplitContext *s = ctx->priv;
 
     av_channel_layout_uninit(&s->channel_layout);
+    av_freep(&s->map);
 }
 
 static int query_formats(AVFilterContext *ctx)
@@ -139,9 +137,27 @@ static int query_formats(AVFilterContext *ctx)
         AVFilterChannelLayouts *out_layouts = NULL;
         enum AVChannel channel = av_channel_layout_channel_from_index(&s->channel_layout, s->map[i]);
 
-        if ((ret = av_channel_layout_from_mask(&channel_layout, 1ULL << channel)) < 0 ||
-            (ret = ff_add_channel_layout(&out_layouts, &channel_layout)) < 0 ||
-            (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts)) < 0)
+        channel_layout.u.map = av_mallocz(sizeof(*channel_layout.u.map));
+        if (!channel_layout.u.map)
+            return AVERROR(ENOMEM);
+
+        channel_layout.u.map[0].id = channel;
+        channel_layout.nb_channels = 1;
+        channel_layout.order       = AV_CHANNEL_ORDER_CUSTOM;
+
+        ret = av_channel_layout_retype(&channel_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
+        if (ret < 0) {
+            av_channel_layout_uninit(&channel_layout);
+            return ret;
+        }
+
+        ret = ff_add_channel_layout(&out_layouts, &channel_layout);
+        av_channel_layout_uninit(&channel_layout);
+        if (ret < 0)
+            return ret;
+
+        ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts);
+        if (ret < 0)
             return ret;
     }
 
@@ -154,17 +170,16 @@ static int filter_frame(AVFilterLink *outlink, AVFrame *buf)
     AVFilterContext *ctx = outlink->src;
     ChannelSplitContext *s = ctx->priv;
     const int i = FF_OUTLINK_IDX(outlink);
-    enum AVChannel channel = av_channel_layout_channel_from_index(&buf->ch_layout, s->map[i]);
     int ret;
 
-    av_assert1(channel >= 0);
-
     buf_out = av_frame_clone(buf);
     if (!buf_out)
         return AVERROR(ENOMEM);
 
     buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[s->map[i]];
-    ret = av_channel_layout_from_mask(&buf_out->ch_layout, 1ULL << channel);
+
+    av_channel_layout_uninit(&buf_out->ch_layout);
+    ret = av_channel_layout_copy(&buf_out->ch_layout, &outlink->ch_layout);
     if (ret < 0) {
         av_frame_free(&buf_out);
         return ret;
-- 
2.43.0



More information about the ffmpeg-devel mailing list