diff options
author | Nicolas George <nicolas.george@normalesup.org> | 2013-02-21 14:02:13 +0100 |
---|---|---|
committer | Nicolas George <nicolas.george@normalesup.org> | 2013-02-24 11:58:52 +0100 |
commit | 2d98dd3d142b5905852571a9c4c5d873945b2a37 (patch) | |
tree | b951babb00a74f326f3b3be525dfc93a5fd8cb2f | |
parent | 3d7f4f87267cf260795f28de1f669c3f45e05a28 (diff) | |
download | ffmpeg-2d98dd3d142b5905852571a9c4c5d873945b2a37.tar.gz |
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.
-rw-r--r-- | libavfilter/avfiltergraph.c | 8 | ||||
-rw-r--r-- | libavfilter/formats.c | 11 | ||||
-rw-r--r-- | libavfilter/formats.h | 3 |
3 files changed, 16 insertions, 6 deletions
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 0bc8464e1d..d0b6b1687f 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -272,8 +272,8 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) continue; 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; if (link->type == AVMEDIA_TYPE_AUDIO) { 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); inlink = convert->inputs[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); if (inlink->type == AVMEDIA_TYPE_AUDIO && (!ff_merge_samplerates(inlink->in_samplerates, diff --git a/libavfilter/formats.c b/libavfilter/formats.c index eb9d94022c..58762806bf 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -89,7 +89,8 @@ do { MERGE_REF(ret, b, fmts, type, fail); \ } while (0) -AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b) +AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, + enum AVMediaType type) { AVFilterFormats *ret = NULL; int i, j; @@ -99,6 +100,14 @@ AVFilterFormats *ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b) if (a == b) 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 (j = 0; j < b->format_count; j++) { const AVPixFmtDescriptor *adesc = av_pix_fmt_desc_get(a->formats[i]); diff --git a/libavfilter/formats.h b/libavfilter/formats.h index a476e70c2e..c06f6dfa3c 100644 --- a/libavfilter/formats.h +++ b/libavfilter/formats.h @@ -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 * 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. |