diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index 95cb605712..0eded68b55 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -154,6 +154,7 @@ int attribute_align_arg av_buffersink_get_samples(AVFilterContext *ctx, static av_cold int common_init(AVFilterContext *ctx) { BufferSinkContext *buf = ctx->priv; + int ret = 0; #if FF_API_BUFFERSINK_OPTS @@ -184,6 +185,44 @@ static av_cold int common_init(AVFilterContext *ctx) CHECK_LIST_SIZE(sample_fmts) CHECK_LIST_SIZE(sample_rates) + + if (buf->channel_layouts_str) { + const char *cur = buf->channel_layouts_str; + + if (buf->all_channel_counts) + av_log(ctx, AV_LOG_WARNING, + "Conflicting all_channel_counts and list in options\n"); + + while (cur) { + void *tmp; + char *next = strchr(cur, '|'); + if (next) + *next++ = 0; + + // +2 for the new element and terminator + tmp = av_realloc_array(buf->channel_layouts, buf->nb_channel_layouts + 2, + sizeof(*buf->channel_layouts)); + if (!tmp) + return AVERROR(ENOMEM); + + memset(&buf->channel_layouts[buf->nb_channel_layouts], 0, + sizeof(*buf->channel_layouts)); + buf->nb_channel_layouts++; + + ret = av_channel_layout_from_string(&buf->channel_layouts[buf->nb_channel_layouts - 1], cur); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: %s.\n", cur); + return ret; + } + if (ret < 0) + return ret; + + cur = next; + } + + if (buf->nb_channel_layouts) + buf->channel_layouts[buf->nb_channel_layouts] = (AVChannelLayout){ 0 }; + } } #undef CHECK_LIST_SIZE @@ -412,8 +451,6 @@ static int asink_query_formats(AVFilterContext *ctx) #if FF_API_BUFFERSINK_OPTS } else { AVFilterFormats *formats = NULL; - AVChannelLayout layout = { 0 }; - AVFilterChannelLayouts *layouts = NULL; unsigned i; if (buf->sample_fmts_size) { @@ -424,37 +461,9 @@ static int asink_query_formats(AVFilterContext *ctx) return ret; } - if (buf->channel_layouts_str || buf->all_channel_counts) { - if (buf->channel_layouts_str) { - const char *cur = buf->channel_layouts_str; - - while (cur) { - char *next = strchr(cur, '|'); - if (next) - *next++ = 0; - - ret = av_channel_layout_from_string(&layout, cur); - if (ret < 0) { - av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: %s.\n", cur); - return ret; - } - ret = ff_add_channel_layout(&layouts, &layout); - av_channel_layout_uninit(&layout); - if (ret < 0) - return ret; - - cur = next; - } - } - - if (buf->all_channel_counts) { - if (layouts) - av_log(ctx, AV_LOG_WARNING, - "Conflicting all_channel_counts and list in options\n"); - else if (!(layouts = ff_all_channel_counts())) - return AVERROR(ENOMEM); - } - if ((ret = ff_set_common_channel_layouts(ctx, layouts)) < 0) + if (buf->nb_channel_layouts) { + ret = ff_set_common_channel_layouts_from_list(ctx, buf->channel_layouts); + if (ret < 0) return ret; }