The following commit:
b97d61f avfilter/ff_merge_formats: only merge if doing so does not loose chroma or alpha
introduced an exception to avoid lossy conversions.
Add a comment to explain the logic.
Fix the call to avoid applying it on audio formats.
tags/n1.2
| @@ -272,8 +272,8 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) | |||||
| continue; | continue; | ||||
| if (link->in_formats != link->out_formats && | if (link->in_formats != link->out_formats && | ||||
| !ff_merge_formats(link->in_formats, | |||||
| link->out_formats)) | |||||
| !ff_merge_formats(link->in_formats, link->out_formats, | |||||
| link->type)) | |||||
| convert_needed = 1; | convert_needed = 1; | ||||
| if (link->type == AVMEDIA_TYPE_AUDIO) { | if (link->type == AVMEDIA_TYPE_AUDIO) { | ||||
| if (link->in_channel_layouts != link->out_channel_layouts && | if (link->in_channel_layouts != link->out_channel_layouts && | ||||
| @@ -337,8 +337,8 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) | |||||
| filter_query_formats(convert); | filter_query_formats(convert); | ||||
| inlink = convert->inputs[0]; | inlink = convert->inputs[0]; | ||||
| outlink = convert->outputs[0]; | outlink = convert->outputs[0]; | ||||
| if (!ff_merge_formats( inlink->in_formats, inlink->out_formats) || | |||||
| !ff_merge_formats(outlink->in_formats, outlink->out_formats)) | |||||
| if (!ff_merge_formats( inlink->in_formats, inlink->out_formats, inlink->type) || | |||||
| !ff_merge_formats(outlink->in_formats, outlink->out_formats, outlink->type)) | |||||
| ret |= AVERROR(ENOSYS); | ret |= AVERROR(ENOSYS); | ||||
| if (inlink->type == AVMEDIA_TYPE_AUDIO && | if (inlink->type == AVMEDIA_TYPE_AUDIO && | ||||
| (!ff_merge_samplerates(inlink->in_samplerates, | (!ff_merge_samplerates(inlink->in_samplerates, | ||||
| @@ -89,7 +89,8 @@ do { | |||||
| MERGE_REF(ret, b, fmts, type, fail); \ | MERGE_REF(ret, b, fmts, type, fail); \ | ||||
| } while (0) | } while (0) | ||||
| AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b) | |||||
| AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, | |||||
| enum AVMediaType type) | |||||
| { | { | ||||
| AVFilterFormats *ret = NULL; | AVFilterFormats *ret = NULL; | ||||
| int i, j; | int i, j; | ||||
| @@ -99,6 +100,14 @@ AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b) | |||||
| if (a == b) | if (a == b) | ||||
| return a; | return a; | ||||
| /* Do not lose chroma or alpha in merging. | |||||
| It happens if both lists have formats with chroma (resp. alpha), but | |||||
| the only formats in common do not have it (e.g. YUV+gray vs. | |||||
| RGB+gray): in that case, the merging would select the gray format, | |||||
| possibly causing a lossy conversion elsewhere in the graph. | |||||
| To avoid that, pretend that there are no common formats to force the | |||||
| insertion of a conversion filter. */ | |||||
| if (type == AVMEDIA_TYPE_VIDEO) | |||||
| for (i = 0; i < a->format_count; i++) | for (i = 0; i < a->format_count; i++) | ||||
| for (j = 0; j < b->format_count; j++) { | for (j = 0; j < b->format_count; j++) { | ||||
| const AVPixFmtDescriptor *adesc = av_pix_fmt_desc_get(a->formats[i]); | const AVPixFmtDescriptor *adesc = av_pix_fmt_desc_get(a->formats[i]); | ||||
| @@ -218,7 +218,8 @@ AVFilterFormats *ff_planar_sample_fmts(void); | |||||
| * If a and b do not share any common formats, neither is modified, and NULL | * If a and b do not share any common formats, neither is modified, and NULL | ||||
| * is returned. | * is returned. | ||||
| */ | */ | ||||
| AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b); | |||||
| AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, | |||||
| enum AVMediaType type); | |||||
| /** | /** | ||||
| * Add *ref as a new reference to formats. | * Add *ref as a new reference to formats. | ||||