diff options
author | Anton Khirnov <anton@khirnov.net> | 2012-03-23 15:14:40 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2012-04-01 09:04:09 +0200 |
commit | 63736fe48c30c5db313c3a25d1462ad31b2a1671 (patch) | |
tree | dcb0310f1b136bf58b58607b6cfceda52a85c568 /libavfilter/avfiltergraph.c | |
parent | 996f9f0c3280552d293c3dbe4266938927fd5908 (diff) | |
download | ffmpeg-63736fe48c30c5db313c3a25d1462ad31b2a1671.tar.gz |
avfiltergraph: try to reduce format conversions in filters.
Current code, with a filterchain such as
(input - yuv411) -> (scale - any) -> (sink - any)
will result in yuv420 being chosen for the second link, which is clearly
not right.
This commit attempts to improve in the following way:
repeat until convergence:
loop over all filters
find input link with exactly one format
force this format on all output links of the same type (if possible)
Diffstat (limited to 'libavfilter/avfiltergraph.c')
-rw-r--r-- | libavfilter/avfiltergraph.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 9b73cc95ab..04d9027527 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -214,6 +214,49 @@ static void pick_format(AVFilterLink *link) avfilter_formats_unref(&link->out_formats); } +static int reduce_formats_on_filter(AVFilterContext *filter) +{ + int i, j, k, ret = 0; + + for (i = 0; i < filter->input_count; i++) { + AVFilterLink *link = filter->inputs[i]; + int format = link->out_formats->formats[0]; + + if (link->out_formats->format_count != 1) + continue; + + for (j = 0; j < filter->output_count; j++) { + AVFilterLink *out_link = filter->outputs[j]; + AVFilterFormats *fmts = out_link->in_formats; + + if (link->type != out_link->type || + out_link->in_formats->format_count == 1) + continue; + + for (k = 0; k < out_link->in_formats->format_count; k++) + if (fmts->formats[k] == format) { + fmts->formats[0] = format; + fmts->format_count = 1; + ret = 1; + break; + } + } + } + return ret; +} + +static void reduce_formats(AVFilterGraph *graph) +{ + int i, reduced; + + do { + reduced = 0; + + for (i = 0; i < graph->filter_count; i++) + reduced |= reduce_formats_on_filter(graph->filters[i]); + } while (reduced); +} + static void pick_formats(AVFilterGraph *graph) { int i, j; @@ -237,7 +280,10 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) return ret; /* Once everything is merged, it's possible that we'll still have - * multiple valid media format choices. We pick the first one. */ + * multiple valid media format choices. We try to minimize the amount + * of format conversion inside filters */ + reduce_formats(graph); + pick_formats(graph); return 0; |