diff options
author | Anton Khirnov <anton@khirnov.net> | 2024-09-01 12:23:41 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2024-09-09 17:26:17 +0200 |
commit | 18d492ff41b294b447bb7d890433f4593dac9b66 (patch) | |
tree | db7880463c4aa5dd6eef59d476c92223cb919cca /libavfilter | |
parent | 7dc81d33c241b9e176ea85956e8317f29bc9e3c0 (diff) | |
download | ffmpeg-18d492ff41b294b447bb7d890433f4593dac9b66.tar.gz |
lavfi/af_channelsplit: support arbitrary channel layouts
Not just those containing channel values under 64. Also, remove an
arbitrary limitation on channel count.
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/af_channelsplit.c | 43 |
1 files 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; |