[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