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

Showing the changes to libavfilter (1 of 1 file). Show all

Unified · Split

libavfilter/af_channelmap.c+53−32
@@ -55,14 +55,15 @@ enum MappingMode { · 54 unmodified lines
55 MAP_PAIR_STR_STR55 MAP_PAIR_STR_STR
56};56};
57 57
58#define MAX_CH 64
59typedef struct ChannelMapContext {58typedef struct ChannelMapContext {
60 const AVClass *class;59 const AVClass *class;
61 char *mapping_str;60 char *mapping_str;
62 AVChannelLayout output_layout;61 AVChannelLayout output_layout;
63 struct ChannelMap map[MAX_CH];62 struct ChannelMap *map;
64 int nch;63 int nch;
65 enum MappingMode mode;64 enum MappingMode mode;
65
66 uint8_t **source_planes;
66} ChannelMapContext;67} ChannelMapContext;
67 68
68#define OFFSET(x) offsetof(ChannelMapContext, x)69#define OFFSET(x) offsetof(ChannelMapContext, x)
@@ -78,6 +79,13 @@ static const AVOption channelmap_options[] = { · 9 unmodified lines
78 79
79AVFILTER_DEFINE_CLASS(channelmap);80AVFILTER_DEFINE_CLASS(channelmap);
80 81
82static void channelmap_uninit(AVFilterContext *ctx)
83{
84 ChannelMapContext *s = ctx->priv;
85 av_freep(&s->map);
86 av_freep(&s->source_planes);
87}
88
81static char* split(char *message, char delim) {89static char* split(char *message, char delim) {
82 char *next = strchr(message, delim);90 char *next = strchr(message, delim);
83 if (next)91 if (next)
@@ -85,7 +93,7 @@ static char* split(char *message, char delim) { · 1 unmodified line
85 return next;93 return next;
86}94}
87 95
88static int get_channel_idx(char **map, int *ch, char delim, int max_nb_channels)96static int get_channel_idx(char **map, int *ch, char delim)
89{97{
90 char *next;98 char *next;
91 int len;99 int len;
@@ -99,7 +107,7 @@ static int get_channel_idx(char **map, int *ch, char delim, int max_nb_channels) · 7 unmodified lines
99 sscanf(*map, "%d%n", ch, &n);107 sscanf(*map, "%d%n", ch, &n);
100 if (n != len)108 if (n != len)
101 return AVERROR(EINVAL);109 return AVERROR(EINVAL);
102 if (*ch < 0 || *ch >= max_nb_channels)110 if (*ch < 0)
103 return AVERROR(EINVAL);111 return AVERROR(EINVAL);
104 *map = next;112 *map = next;
105 return 0;113 return 0;
@@ -148,7 +156,8 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 42 unmodified lines
148 int map_entries = 0;156 int map_entries = 0;
149 enum MappingMode mode;157 enum MappingMode mode;
150 int64_t out_ch_mask = 0;158 int64_t out_ch_mask = 0;
151 uint64_t presence_mask;159 uint8_t *presence_map = NULL;
160 int ret = 0;
152 int i;161 int i;
153 162
154 mapping = s->mapping_str;163 mapping = s->mapping_str;
@@ -182,27 +191,25 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 27 unmodified lines
182 if (*++sep) // Allow trailing comma191 if (*++sep) // Allow trailing comma
183 map_entries++;192 map_entries++;
184 }193 }
185 }
186 194
187 if (map_entries > MAX_CH) {195 s->map = av_malloc_array(map_entries, sizeof(*s->map));
188 av_log(ctx, AV_LOG_ERROR, "Too many channels mapped: '%d'.\n", map_entries);196 if (!s->map)
189 return AVERROR(EINVAL);197 return AVERROR(ENOMEM);
190 }198 }
191 199
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
193 s->map[i].in_channel_idx = -1;205 s->map[i].in_channel_idx = -1;
194 s->map[i].out_channel_idx = -1;206 s->map[i].out_channel_idx = -1;
195 s->map[i].in_channel = -1;207 s->map[i].in_channel = -1;
196 s->map[i].out_channel = -1;208 s->map[i].out_channel = -1;
197 }
198 209
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";
203 switch (mode) {210 switch (mode) {
204 case MAP_ONE_INT:211 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) {
206 av_log(ctx, AV_LOG_ERROR, err);213 av_log(ctx, AV_LOG_ERROR, err);
207 return AVERROR(EINVAL);214 return AVERROR(EINVAL);
208 }215 }
@@ -218,8 +225,8 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 9 unmodified lines
218 s->map[i].out_channel_idx = i;225 s->map[i].out_channel_idx = i;
219 break;226 break;
220 case MAP_PAIR_INT_INT:227 case MAP_PAIR_INT_INT:
221 if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 ||228 if (get_channel_idx(&mapping, &in_ch_idx, '-') < 0 ||
222 get_channel_idx(&mapping, &out_ch_idx, separator, MAX_CH) < 0) {229 get_channel_idx(&mapping, &out_ch_idx, separator) < 0) {
223 av_log(ctx, AV_LOG_ERROR, err);230 av_log(ctx, AV_LOG_ERROR, err);
224 return AVERROR(EINVAL);231 return AVERROR(EINVAL);
225 }232 }
@@ -227,7 +234,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 1 unmodified line
227 s->map[i].out_channel_idx = out_ch_idx;234 s->map[i].out_channel_idx = out_ch_idx;
228 break;235 break;
229 case MAP_PAIR_INT_STR:236 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 ||
231 get_channel(&mapping, &out_ch, separator) < 0) {238 get_channel(&mapping, &out_ch, separator) < 0) {
232 av_log(ctx, AV_LOG_ERROR, err);239 av_log(ctx, AV_LOG_ERROR, err);
233 return AVERROR(EINVAL);240 return AVERROR(EINVAL);
@@ -241,7 +248,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 7 unmodified lines
241 break;248 break;
242 case MAP_PAIR_STR_INT:249 case MAP_PAIR_STR_INT:
243 if (get_channel(&mapping, &in_ch, '-') < 0 ||250 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) {
245 av_log(ctx, AV_LOG_ERROR, err);252 av_log(ctx, AV_LOG_ERROR, err);
246 return AVERROR(EINVAL);253 return AVERROR(EINVAL);
247 }254 }
@@ -275,6 +282,11 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 27 unmodified lines
275 if (mode == MAP_NONE) {282 if (mode == MAP_NONE) {
276 int i;283 int i;
277 s->nch = s->output_layout.nb_channels;284 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
278 for (i = 0; i < s->nch; i++) {290 for (i = 0; i < s->nch; i++) {
279 s->map[i].in_channel_idx = i;291 s->map[i].in_channel_idx = i;
280 s->map[i].out_channel_idx = i;292 s->map[i].out_channel_idx = i;
@@ -301,22 +313,25 @@ static av_cold int channelmap_init(AVFilterContext *ctx) · 20 unmodified lines
301 }313 }
302 }314 }
303 315
304 presence_mask = 0;316 presence_map = av_calloc(s->nch, sizeof(*presence_map));
305 for (i = 0; i < s->nch; i++) {317 for (i = 0; i < s->nch; i++) {
306 uint64_t idx_mask;318 const int out_idx = s->map[i].out_channel_idx;
307 int ret = check_idx_and_id(ctx, s->map[i].out_channel_idx, s->map[i].out_channel, &s->output_layout, "out");319 int ret = check_idx_and_id(ctx, out_idx, s->map[i].out_channel, &s->output_layout, "out");
308 if (ret < 0)320 if (ret < 0)
309 return ret;321 break;
310 idx_mask = (1ULL << s->map[i].out_channel_idx);322 if (presence_map[out_idx]) {
311 if (presence_mask & idx_mask) {
312 char layout_name[256];323 char layout_name[256];
313 av_channel_layout_describe(&s->output_layout, layout_name, sizeof(layout_name));324 av_channel_layout_describe(&s->output_layout, layout_name, sizeof(layout_name));
314 av_log(ctx, AV_LOG_ERROR, "Mapping %d assigns channel #%d twice in output layout '%s'.\n",325 av_log(ctx, AV_LOG_ERROR, "Mapping %d assigns channel #%d twice in output layout '%s'.\n",
315 i + 1, s->map[i].out_channel_idx, layout_name);326 i + 1, s->map[i].out_channel_idx, layout_name);
316 return AVERROR(EINVAL);327 ret = AVERROR(EINVAL);
328 break;
317 }329 }
318 presence_mask |= idx_mask;330 presence_map[out_idx] = 1;
319 }331 }
332 av_freep(&presence_map);
333 if (ret < 0)
334 return ret;
320 335
321 return 0;336 return 0;
322}337}
@@ -353,10 +368,9 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf) · 30 unmodified lines
353 const int nch_in = inlink->ch_layout.nb_channels;368 const int nch_in = inlink->ch_layout.nb_channels;
354 const int nch_out = s->nch;369 const int nch_out = s->nch;
355 int ch, ret;370 int ch, ret;
356 uint8_t *source_planes[MAX_CH];
357 371
358 memcpy(source_planes, buf->extended_data,372 memcpy(s->source_planes, buf->extended_data,
359 nch_in * sizeof(source_planes[0]));373 nch_in * sizeof(s->source_planes[0]));
360 374
361 if (nch_out > nch_in) {375 if (nch_out > nch_in) {
362 if (nch_out > FF_ARRAY_ELEMS(buf->data)) {376 if (nch_out > FF_ARRAY_ELEMS(buf->data)) {
@@ -380,7 +394,7 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf) · 17 unmodified lines
380 394
381 for (ch = 0; ch < nch_out; ch++) {395 for (ch = 0; ch < nch_out; ch++) {
382 buf->extended_data[s->map[ch].out_channel_idx] =396 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];
384 }398 }
385 399
386 if (buf->data != buf->extended_data)400 if (buf->data != buf->extended_data)
@@ -411,6 +425,12 @@ static int channelmap_config_input(AVFilterLink *inlink) · 24 unmodified lines
411 err = AVERROR(EINVAL);425 err = AVERROR(EINVAL);
412 }426 }
413 427
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
414 return err;434 return err;
415}435}
416 436
@@ -428,6 +448,7 @@ const AVFilter ff_af_channelmap = { · 11 unmodified lines
428 .name = "channelmap",448 .name = "channelmap",
429 .description = NULL_IF_CONFIG_SMALL("Remap audio channels."),449 .description = NULL_IF_CONFIG_SMALL("Remap audio channels."),
430 .init = channelmap_init,450 .init = channelmap_init,
451 .uninit = channelmap_uninit,
431 .priv_size = sizeof(ChannelMapContext),452 .priv_size = sizeof(ChannelMapContext),
432 .priv_class = &channelmap_class,453 .priv_class = &channelmap_class,
433 FILTER_INPUTS(avfilter_af_channelmap_inputs),454 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