Browse Source

lavfi: fix merging of formats and clarify exception.

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
Nicolas George 12 years ago
parent
commit
2d98dd3d14
3 changed files with 16 additions and 6 deletions
  1. +4
    -4
      libavfilter/avfiltergraph.c
  2. +10
    -1
      libavfilter/formats.c
  3. +2
    -1
      libavfilter/formats.h

+ 4
- 4
libavfilter/avfiltergraph.c View File

@@ -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,


+ 10
- 1
libavfilter/formats.c View File

@@ -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]);


+ 2
- 1
libavfilter/formats.h View File

@@ -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.


Loading…
Cancel
Save