diff --git a/doc/filters.texi b/doc/filters.texi index 2669804efb..de0e0716eb 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1208,7 +1208,7 @@ This filter accepts the following named parameters: Channel layout of the output stream. @item map -Map channels from input to output. The argument is a comma-separated list of +Map channels from input to output. The argument is a '|'-separated list of mappings, each in the @code{@var{in_channel}-@var{out_channel}} or @var{in_channel} form. @var{in_channel} can be either the name of the input channel (e.g. FL for front left) or its index in the input channel layout. @@ -1222,14 +1222,14 @@ output channels preserving index. For example, assuming a 5.1+downmix input MOV file @example -ffmpeg -i in.mov -filter 'channelmap=map=DL-FL\,DR-FR' out.wav +ffmpeg -i in.mov -filter 'channelmap=map=DL-FL|DR-FR' out.wav @end example will create an output WAV file tagged as stereo from the downmix channels of the input. To fix a 5.1 WAV improperly encoded in AAC's native channel order @example -ffmpeg -i in.wav -filter 'channelmap=1\,2\,0\,5\,3\,4:channel_layout=5.1' out.wav +ffmpeg -i in.wav -filter 'channelmap=1|2|0|5|3|4:channel_layout=5.1' out.wav @end example @section join diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c index e73c4bc904..4cc92c93ac 100644 --- a/libavfilter/af_channelmap.c +++ b/libavfilter/af_channelmap.c @@ -123,25 +123,14 @@ static int get_channel(char **map, uint64_t *ch, char delim) static av_cold int channelmap_init(AVFilterContext *ctx, const char *args) { ChannelMapContext *s = ctx->priv; - int ret; - char *mapping; + int ret = 0; + char *mapping, separator = '|'; int map_entries = 0; char buf[256]; enum MappingMode mode; uint64_t out_ch_mask = 0; int i; - if (!args) { - av_log(ctx, AV_LOG_ERROR, "No parameters supplied.\n"); - return AVERROR(EINVAL); - } - - s->class = &channelmap_class; - av_opt_set_defaults(s); - - if ((ret = av_set_options_string(s, args, "=", ":")) < 0) - return ret; - mapping = s->mapping_str; if (!mapping) { @@ -164,13 +153,20 @@ static av_cold int channelmap_init(AVFilterContext *ctx, const char *args) else mode = MAP_PAIR_STR_STR; } +#if FF_API_OLD_FILTER_OPTS + if (strchr(mapping, ',')) { + av_log(ctx, AV_LOG_WARNING, "This syntax is deprecated, use " + "'|' to separate the mappings.\n"); + separator = ','; + } +#endif } if (mode != MAP_NONE) { - char *comma = mapping; + char *sep = mapping; map_entries = 1; - while ((comma = strchr(comma, ','))) { - if (*++comma) // Allow trailing comma + while ((sep = strchr(sep, separator))) { + if (*++sep) // Allow trailing comma map_entries++; } } @@ -187,7 +183,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx, const char *args) static const char err[] = "Failed to parse channel map\n"; switch (mode) { case MAP_ONE_INT: - if (get_channel_idx(&mapping, &in_ch_idx, ',', MAX_CH) < 0) { + if (get_channel_idx(&mapping, &in_ch_idx, separator, MAX_CH) < 0) { ret = AVERROR(EINVAL); av_log(ctx, AV_LOG_ERROR, err); goto fail; @@ -196,7 +192,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx, const char *args) s->map[i].out_channel_idx = i; break; case MAP_ONE_STR: - if (!get_channel(&mapping, &in_ch, ',')) { + if (!get_channel(&mapping, &in_ch, separator)) { av_log(ctx, AV_LOG_ERROR, err); ret = AVERROR(EINVAL); goto fail; @@ -206,7 +202,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx, const char *args) break; case MAP_PAIR_INT_INT: if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 || - get_channel_idx(&mapping, &out_ch_idx, ',', MAX_CH) < 0) { + get_channel_idx(&mapping, &out_ch_idx, separator, MAX_CH) < 0) { av_log(ctx, AV_LOG_ERROR, err); ret = AVERROR(EINVAL); goto fail; @@ -216,7 +212,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx, const char *args) break; case MAP_PAIR_INT_STR: if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 || - get_channel(&mapping, &out_ch, ',') < 0 || + get_channel(&mapping, &out_ch, separator) < 0 || out_ch & out_ch_mask) { av_log(ctx, AV_LOG_ERROR, err); ret = AVERROR(EINVAL); @@ -228,7 +224,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx, const char *args) break; case MAP_PAIR_STR_INT: if (get_channel(&mapping, &in_ch, '-') < 0 || - get_channel_idx(&mapping, &out_ch_idx, ',', MAX_CH) < 0) { + get_channel_idx(&mapping, &out_ch_idx, separator, MAX_CH) < 0) { av_log(ctx, AV_LOG_ERROR, err); ret = AVERROR(EINVAL); goto fail; @@ -238,7 +234,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx, const char *args) break; case MAP_PAIR_STR_STR: if (get_channel(&mapping, &in_ch, '-') < 0 || - get_channel(&mapping, &out_ch, ',') < 0 || + get_channel(&mapping, &out_ch, separator) < 0 || out_ch & out_ch_mask) { av_log(ctx, AV_LOG_ERROR, err); ret = AVERROR(EINVAL); @@ -409,8 +405,8 @@ AVFilter avfilter_af_channelmap = { .init = channelmap_init, .query_formats = channelmap_query_formats, .priv_size = sizeof(ChannelMapContext), + .priv_class = &channelmap_class, .inputs = avfilter_af_channelmap_inputs, .outputs = avfilter_af_channelmap_outputs, - .priv_class = &channelmap_class, }; diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 4696eaeb5e..632ab4953d 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -667,6 +667,7 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque !strcmp(filter->filter->name, "blend" ) || !strcmp(filter->filter->name, "boxblur" ) || !strcmp(filter->filter->name, "cellauto") || + !strcmp(filter->filter->name, "channelmap") || !strcmp(filter->filter->name, "colormatrix") || !strcmp(filter->filter->name, "crop" ) || !strcmp(filter->filter->name, "cropdetect") || diff --git a/tests/filtergraphs/channelmap b/tests/filtergraphs/channelmap index 7f9f24d178..e2b61435df 100644 --- a/tests/filtergraphs/channelmap +++ b/tests/filtergraphs/channelmap @@ -1 +1 @@ -channelmap=map=1\,2\,0\,5\,3\,4:channel_layout=5.1 +channelmap=map=1|2|0|5|3|4:channel_layout=5.1