History

lavfi/af_channelmap: remove an arbitrary limit on channel count

Anton Khirnov committed 2 years ago

Commit 7dc81d31 parent a3f79fd1 file · +53 −32Browse files

Unified · Split

libavfilter/af_channelmap.c+53−32
@@ -55,14 +55,15 @@ enum MappingMode { · 54 unmodified lines
5555 MAP_PAIR_STR_STR
5656 };
5757
58−#define MAX_CH 64
5958 typedef struct ChannelMapContext {
6059 const AVClass *class;
6160 char *mapping_str;
6261 AVChannelLayout output_layout;
63− struct ChannelMap map[MAX_CH];
62+ struct ChannelMap *map;
6463 int nch;
6564 enum MappingMode mode;
65+
66+ uint8_t **source_planes;
6667 } ChannelMapContext;
6768
6869 #define OFFSET(x) offsetof(ChannelMapContext, x)
@@ -78,6 +79,13 @@ static const AVOption channelmap_options[] = { · 9 unmodified lines
7879
7980 AVFILTER_DEFINE_CLASS(channelmap);
8081
82+static void channelmap_uninit(AVFilterContext *ctx)
83+{
84+ ChannelMapContext *s = ctx->priv;
85+ av_freep(&s->map);
86+ av_freep(&s->source_planes);
87+}
88+
8189 static char* split(char *message, char delim) {
8290 char *next = strchr(message, delim);
8391 if (next)
@@ -85,7 +93,7 @@ static char* split(char *message, char delim) { · 1 unmodified line
8593 return next;
8694 }
8795
88−static int get_channel_idx(char **map, int *ch, char delim, int max_nb_channels)
96+static int get_channel_idx(char **map, int *ch, char delim)
8997 {
9098 char *next;
9199 int len;
@@ -99,7 +107,7 @@ static int get_channel_idx(char **map, int *ch, char delim, int max_nb_channels) · 7 unmodified lines
99107 sscanf(*map, "%d%n", ch, &n);
100108 if (n != len)
101109 return AVERROR(EINVAL);
102− if (*ch < 0 || *ch >= max_nb_channels)
110+ if (*ch < 0)
103111 return AVERROR(EINVAL);
104112 *map = next;
105113 return 0;
@@ -148,7 +156,8 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 42 unmodified lines
148156 int map_entries = 0;
149157 enum MappingMode mode;
150158 int64_t out_ch_mask = 0;
151− uint64_t presence_mask;
159+ uint8_t *presence_map = NULL;
160+ int ret = 0;
152161 int i;
153162
154163 mapping = s->mapping_str;
@@ -182,27 +191,25 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 27 unmodified lines
182191 if (*++sep) // Allow trailing comma
183192 map_entries++;
184193 }
185− }
186194
187− if (map_entries > MAX_CH) {
188− av_log(ctx, AV_LOG_ERROR, "Too many channels mapped: '%d'.\n", map_entries);
189− return AVERROR(EINVAL);
195+ s->map = av_malloc_array(map_entries, sizeof(*s->map));
196+ if (!s->map)
197+ return AVERROR(ENOMEM);
190198 }
191199
192− for (i = 0; i < MAX_CH; i++) {
200+ for (i = 0; i < map_entries; i++) {
201+ int in_ch_idx = -1, out_ch_idx = -1;
202+ int in_ch = -1, out_ch = -1;
203+ static const char err[] = "Failed to parse channel map\n";
204+
193205 s->map[i].in_channel_idx = -1;
194206 s->map[i].out_channel_idx = -1;
195207 s->map[i].in_channel = -1;
196208 s->map[i].out_channel = -1;
197− }
198209
199− for (i = 0; i < map_entries; i++) {
200− int in_ch_idx = -1, out_ch_idx = -1;
201− int in_ch = -1, out_ch = -1;
202− static const char err[] = "Failed to parse channel map\n";
203210 switch (mode) {
204211 case MAP_ONE_INT:
205− if (get_channel_idx(&mapping, &in_ch_idx, separator, MAX_CH) < 0) {
212+ if (get_channel_idx(&mapping, &in_ch_idx, separator) < 0) {
206213 av_log(ctx, AV_LOG_ERROR, err);
207214 return AVERROR(EINVAL);
208215 }
@@ -218,8 +225,8 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 9 unmodified lines
218225 s->map[i].out_channel_idx = i;
219226 break;
220227 case MAP_PAIR_INT_INT:
221− if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 ||
222− get_channel_idx(&mapping, &out_ch_idx, separator, MAX_CH) < 0) {
228+ if (get_channel_idx(&mapping, &in_ch_idx, '-') < 0 ||
229+ get_channel_idx(&mapping, &out_ch_idx, separator) < 0) {
223230 av_log(ctx, AV_LOG_ERROR, err);
224231 return AVERROR(EINVAL);
225232 }
@@ -227,7 +234,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 1 unmodified line
227234 s->map[i].out_channel_idx = out_ch_idx;
228235 break;
229236 case MAP_PAIR_INT_STR:
230− if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 ||
237+ if (get_channel_idx(&mapping, &in_ch_idx, '-') < 0 ||
231238 get_channel(&mapping, &out_ch, separator) < 0) {
232239 av_log(ctx, AV_LOG_ERROR, err);
233240 return AVERROR(EINVAL);
@@ -241,7 +248,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 7 unmodified lines
241248 break;
242249 case MAP_PAIR_STR_INT:
243250 if (get_channel(&mapping, &in_ch, '-') < 0 ||
244− get_channel_idx(&mapping, &out_ch_idx, separator, MAX_CH) < 0) {
251+ get_channel_idx(&mapping, &out_ch_idx, separator) < 0) {
245252 av_log(ctx, AV_LOG_ERROR, err);
246253 return AVERROR(EINVAL);
247254 }
@@ -275,6 +282,11 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 27 unmodified lines
275282 if (mode == MAP_NONE) {
276283 int i;
277284 s->nch = s->output_layout.nb_channels;
285+
286+ s->map = av_malloc_array(s->nch, sizeof(*s->map));
287+ if (!s->map)
288+ return AVERROR(ENOMEM);
289+
278290 for (i = 0; i < s->nch; i++) {
279291 s->map[i].in_channel_idx = i;
280292 s->map[i].out_channel_idx = i;
@@ -301,22 +313,25 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 20 unmodified lines
301313 }
302314 }
303315
304− presence_mask = 0;
316+ presence_map = av_calloc(s->nch, sizeof(*presence_map));
305317 for (i = 0; i < s->nch; i++) {
306− uint64_t idx_mask;
307− int ret = check_idx_and_id(ctx, s->map[i].out_channel_idx, s->map[i].out_channel, &s->output_layout, "out");
318+ const int out_idx = s->map[i].out_channel_idx;
319+ int ret = check_idx_and_id(ctx, out_idx, s->map[i].out_channel, &s->output_layout, "out");
308320 if (ret < 0)
309− return ret;
310− idx_mask = (1ULL << s->map[i].out_channel_idx);
311− if (presence_mask & idx_mask) {
321+ break;
322+ if (presence_map[out_idx]) {
312323 char layout_name[256];
313324 av_channel_layout_describe(&s->output_layout, layout_name, sizeof(layout_name));
314325 av_log(ctx, AV_LOG_ERROR, "Mapping %d assigns channel #%d twice in output layout '%s'.\n",
315326 i + 1, s->map[i].out_channel_idx, layout_name);
316− return AVERROR(EINVAL);
327+ ret = AVERROR(EINVAL);
328+ break;
317329 }
318− presence_mask |= idx_mask;
330+ presence_map[out_idx] = 1;
319331 }
332+ av_freep(&presence_map);
333+ if (ret < 0)
334+ return ret;
320335
321336 return 0;
322337 }
@@ -353,10 +368,9 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf) · 30 unmodified lines
353368 const int nch_in = inlink->ch_layout.nb_channels;
354369 const int nch_out = s->nch;
355370 int ch, ret;
356− uint8_t *source_planes[MAX_CH];
357371
358− memcpy(source_planes, buf->extended_data,
359− nch_in * sizeof(source_planes[0]));
372+ memcpy(s->source_planes, buf->extended_data,
373+ nch_in * sizeof(s->source_planes[0]));
360374
361375 if (nch_out > nch_in) {
362376 if (nch_out > FF_ARRAY_ELEMS(buf->data)) {
@@ -380,7 +394,7 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf) · 17 unmodified lines
380394
381395 for (ch = 0; ch < nch_out; ch++) {
382396 buf->extended_data[s->map[ch].out_channel_idx] =
383− source_planes[s->map[ch].in_channel_idx];
397+ s->source_planes[s->map[ch].in_channel_idx];
384398 }
385399
386400 if (buf->data != buf->extended_data)
@@ -411,6 +425,12 @@ static int channelmap_config_input(AVFilterLink *inlink) · 24 unmodified lines
411425 err = AVERROR(EINVAL);
412426 }
413427
428+ av_freep(&s->source_planes);
429+ s->source_planes = av_calloc(inlink->ch_layout.nb_channels,
430+ sizeof(*s->source_planes));
431+ if (!s->source_planes)
432+ return AVERROR(ENOMEM);
433+
414434 return err;
415435 }
416436
@@ -428,6 +448,7 @@ const AVFilter ff_af_channelmap = { · 11 unmodified lines
428448 .name = "channelmap",
429449 .description = NULL_IF_CONFIG_SMALL("Remap audio channels."),
430450 .init = channelmap_init,
451+ .uninit = channelmap_uninit,
431452 .priv_size = sizeof(ChannelMapContext),
432453 .priv_class = &channelmap_class,
433454 FILTER_INPUTS(avfilter_af_channelmap_inputs),

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