summaryrefslogtreecommitdiff
path: root/libavfilter/avfiltergraph.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2012-03-23 15:14:40 +0100
committerAnton Khirnov <anton@khirnov.net>2012-04-01 09:04:09 +0200
commit63736fe48c30c5db313c3a25d1462ad31b2a1671 (patch)
treedcb0310f1b136bf58b58607b6cfceda52a85c568 /libavfilter/avfiltergraph.c
parent996f9f0c3280552d293c3dbe4266938927fd5908 (diff)
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.c48
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;