History

lavfi/af_channelsplit: support arbitrary channel layouts

Not just those containing channel values under 64. Also, remove an arbitrary limitation on channel count.

Anton Khirnov committed 2 years ago

Commit 18d492f1 parent 7dc81d31 file · +29 −14Browse files

Unified · Split

libavfilter/af_channelsplit.c+29−14
@@ -34,15 +34,13 @@ · 33 unmodified lines
3434 #include "filters.h"
3535 #include "formats.h"
3636
37−#define MAX_CH 64
38−
3937 typedef struct ChannelSplitContext {
4038 const AVClass *class;
4139
4240 AVChannelLayout channel_layout;
4341 char *channels_str;
4442
45− int map[64];
43+ int *map;
4644 } ChannelSplitContext;
4745
4846 #define OFFSET(x) offsetof(ChannelSplitContext, x)
@@ -71,10 +69,9 @@ static av_cold int init(AVFilterContext *ctx) · 22 unmodified lines
7169 goto fail;
7270 }
7371
74− if (channel_layout.nb_channels > MAX_CH) {
75− av_log(ctx, AV_LOG_ERROR, "Too many channels\n");
76− goto fail;
77− }
72+ s->map = av_calloc(channel_layout.nb_channels, sizeof(*s->map));
73+ if (!s->map)
74+ return AVERROR(ENOMEM);
7875
7976 for (i = 0; i < channel_layout.nb_channels; i++) {
8077 enum AVChannel channel = av_channel_layout_channel_from_index(&channel_layout, i);
@@ -118,6 +115,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 37 unmodified lines
118115 ChannelSplitContext *s = ctx->priv;
119116
120117 av_channel_layout_uninit(&s->channel_layout);
118+ av_freep(&s->map);
121119 }
122120
123121 static int query_formats(AVFilterContext *ctx)
@@ -139,9 +137,27 @@ static int query_formats(AVFilterContext *ctx) · 15 unmodified lines
139137 AVFilterChannelLayouts *out_layouts = NULL;
140138 enum AVChannel channel = av_channel_layout_channel_from_index(&s->channel_layout, s->map[i]);
141139
142− if ((ret = av_channel_layout_from_mask(&channel_layout, 1ULL << channel)) < 0 ||
143− (ret = ff_add_channel_layout(&out_layouts, &channel_layout)) < 0 ||
144− (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts)) < 0)
140+ channel_layout.u.map = av_mallocz(sizeof(*channel_layout.u.map));
141+ if (!channel_layout.u.map)
142+ return AVERROR(ENOMEM);
143+
144+ channel_layout.u.map[0].id = channel;
145+ channel_layout.nb_channels = 1;
146+ channel_layout.order = AV_CHANNEL_ORDER_CUSTOM;
147+
148+ ret = av_channel_layout_retype(&channel_layout, 0, AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL);
149+ if (ret < 0) {
150+ av_channel_layout_uninit(&channel_layout);
151+ return ret;
152+ }
153+
154+ ret = ff_add_channel_layout(&out_layouts, &channel_layout);
155+ av_channel_layout_uninit(&channel_layout);
156+ if (ret < 0)
157+ return ret;
158+
159+ ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts);
160+ if (ret < 0)
145161 return ret;
146162 }
147163
@@ -154,17 +170,16 @@ static int filter_frame(AVFilterLink *outlink, AVFrame *buf) · 6 unmodified lines
154170 AVFilterContext *ctx = outlink->src;
155171 ChannelSplitContext *s = ctx->priv;
156172 const int i = FF_OUTLINK_IDX(outlink);
157− enum AVChannel channel = av_channel_layout_channel_from_index(&buf->ch_layout, s->map[i]);
158173 int ret;
159174
160− av_assert1(channel >= 0);
161−
162175 buf_out = av_frame_clone(buf);
163176 if (!buf_out)
164177 return AVERROR(ENOMEM);
165178
166179 buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[s->map[i]];
167− ret = av_channel_layout_from_mask(&buf_out->ch_layout, 1ULL << channel);
180+
181+ av_channel_layout_uninit(&buf_out->ch_layout);
182+ ret = av_channel_layout_copy(&buf_out->ch_layout, &outlink->ch_layout);
168183 if (ret < 0) {
169184 av_frame_free(&buf_out);
170185 return ret;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t