Rewrite colorspace negotiation.
authorVitor Sessak <vitor1001@gmail.com>
Fri, 4 Apr 2008 20:07:41 +0000 (20:07 +0000)
committerVitor Sessak <vitor1001@gmail.com>
Fri, 4 Apr 2008 20:07:41 +0000 (20:07 +0000)
Commited in SoC by Bobby Bingham on 2007-12-20 19:36:26

Originally committed as revision 12711 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavfilter/avfiltergraph.c
libavfilter/avfiltergraph.h

index fc79848..665f80e 100644 (file)
@@ -58,21 +58,6 @@ static inline AVFilterLink *get_extern_input_link(AVFilterLink *link)
     return lctx->graph->inputs[link->srcpad];
 }
 
-/** query the formats supported by a filter providing input to the graph */
-static int *link_in_query_formats(AVFilterLink *link)
-{
-    AVFilterLink *link2 = get_extern_input_link(link);
-    int *(*query_formats)(AVFilterLink *);
-
-    if(!link2)
-        return avfilter_make_format_list(0);
-
-    if(!(query_formats = link2->src->output_pads[link2->srcpad].query_formats))
-        query_formats = avfilter_default_query_output_formats;
-
-    return query_formats(link2);
-}
-
 /** request a frame from a filter providing input to the graph */
 static int link_in_request_frame(AVFilterLink *link)
 {
@@ -112,17 +97,6 @@ static inline AVFilterLink *get_extern_output_link(AVFilterLink *link)
     return lctx->graph->outputs[link->dstpad];
 }
 
-/** query the formats supported by a filter taking output from the graph */
-static int *link_out_query_formats(AVFilterLink *link)
-{
-    AVFilterLink *link2 = get_extern_output_link(link);
-
-    if(!link2)
-        return avfilter_make_format_list(0);
-
-    return link2->dst->input_pads[link2->dstpad].query_formats(link2);
-}
-
 static int link_out_config_props(AVFilterLink *link)
 {
     AVFilterLink *link2 = get_extern_output_link(link);
@@ -224,15 +198,6 @@ static void graph_in_draw_slice(AVFilterLink *link, int y, int height)
         avfilter_draw_slice(link2, y, height);
 }
 
-static int *graph_in_query_formats(AVFilterLink *link)
-{
-    AVFilterLink *link2 = get_intern_input_link(link);
-
-    if(!link2 || !link2->dst->input_pads[link2->dstpad].query_formats)
-        return avfilter_make_format_list(0);
-    return link2->dst->input_pads[link2->dstpad].query_formats(link2);
-}
-
 static int graph_in_config_props(AVFilterLink *link)
 {
     AVFilterLink *link2 = get_intern_input_link(link);
@@ -258,17 +223,6 @@ static AVFilterLink *get_intern_output_link(AVFilterLink *link)
     return graph->link_filter->inputs[link->srcpad];
 }
 
-static int *graph_out_query_formats(AVFilterLink *link)
-{
-    AVFilterLink *link2 = get_intern_output_link(link);
-
-    if(!link2)
-        return avfilter_make_format_list(0);
-    if(!link2->src->output_pads[link2->srcpad].query_formats)
-        return avfilter_default_query_output_formats(link2);
-    return link2->src->output_pads[link2->srcpad].query_formats(link2);
-}
-
 static int graph_out_request_frame(AVFilterLink *link)
 {
     AVFilterLink *link2 = get_intern_output_link(link);
@@ -315,7 +269,6 @@ static int add_graph_input(AVFilterContext *gctx, AVFilterContext *filt, unsigne
         .end_frame        = graph_in_end_frame,
         .get_video_buffer = graph_in_get_video_buffer,
         .draw_slice       = graph_in_draw_slice,
-        .query_formats    = graph_in_query_formats,
         .config_props     = graph_in_config_props,
         /* XXX */
     };
@@ -323,7 +276,6 @@ static int add_graph_input(AVFilterContext *gctx, AVFilterContext *filt, unsigne
     {
         .name          = NULL,          /* FIXME? */
         .type          = AV_PAD_VIDEO,
-        .query_formats = link_in_query_formats,
         .request_frame = link_in_request_frame,
         .config_props  = link_in_config_props,
     };
@@ -345,7 +297,6 @@ static int add_graph_output(AVFilterContext *gctx, AVFilterContext *filt, unsign
         .name             = name,
         .type             = AV_PAD_VIDEO,
         .request_frame    = graph_out_request_frame,
-        .query_formats    = graph_out_query_formats,
         .config_props     = graph_out_config_props,
     };
     AVFilterPad dummy_inpad =
@@ -356,7 +307,6 @@ static int add_graph_output(AVFilterContext *gctx, AVFilterContext *filt, unsign
         .end_frame        = link_out_end_frame,
         .draw_slice       = link_out_draw_slice,
         .get_video_buffer = link_out_get_video_buffer,
-        .query_formats    = link_out_query_formats,
         .config_props     = link_out_config_props,
     };
 
@@ -406,6 +356,121 @@ AVFilterContext *avfilter_graph_get_filter(AVFilterContext *ctx, char *name)
     return NULL;
 }
 
+static int query_formats(AVFilterContext *graphctx)
+{
+    GraphContext *graph = graphctx->priv;
+    AVFilterContext *linkfilt = graph->link_filter;
+    int i, j;
+
+    /* ask all the sub-filters for their supported colorspaces */
+    for(i = 0; i < graph->filter_count; i ++) {
+        if(graph->filters[i]->filter->query_formats)
+            graph->filters[i]->filter->query_formats(graph->filters[i]);
+        else
+            avfilter_default_query_formats(graph->filters[i]);
+    }
+
+    /* use these formats on our exported links */
+    for(i = 0; i < linkfilt->input_count; i ++) {
+        avfilter_formats_ref( linkfilt->inputs[i]->in_formats,
+                             &linkfilt->inputs[i]->out_formats);
+
+        if(graphctx->outputs[i])
+            avfilter_formats_ref( linkfilt-> inputs[i]->in_formats,
+                                 &graphctx->outputs[i]->in_formats);
+    }
+    for(i = 0; i < linkfilt->output_count; i ++) {
+        avfilter_formats_ref( linkfilt->outputs[i]->out_formats,
+                             &linkfilt->outputs[i]->in_formats);
+
+        if(graphctx->inputs[i])
+            avfilter_formats_ref( linkfilt->outputs[i]->out_formats,
+                                 &graphctx-> inputs[i]->out_formats);
+    }
+
+    /* go through and merge as many format lists as possible */
+    for(i = 0; i < graph->filter_count; i ++) {
+        AVFilterContext *filter = graph->filters[i];
+
+        for(j = 0; j < filter->input_count; j ++) {
+            AVFilterLink *link;
+            if(!(link = filter->inputs[j]))
+                continue;
+            if(link->in_formats != link->out_formats) {
+                if(!avfilter_merge_formats(link->in_formats,
+                                           link->out_formats)) {
+                    /* couldn't merge format lists. auto-insert scale filter */
+                    AVFilterContext *scale;
+
+                    if(!(scale = avfilter_open(&avfilter_vf_scale, NULL)))
+                        return -1;
+                    if(scale->filter->init(scale, NULL, NULL) ||
+                       avfilter_insert_filter(link, scale, 0, 0)) {
+                        avfilter_destroy(scale);
+                        return -1;
+                    }
+
+                    avfilter_graph_add_filter(graphctx, scale);
+                    scale->filter->query_formats(scale);
+                    if(avfilter_merge_formats(scale-> inputs[0]->in_formats,
+                                              scale-> inputs[0]->out_formats) ||
+                       avfilter_merge_formats(scale->outputs[0]->in_formats,
+                                              scale->outputs[0]->out_formats))
+                        return -1;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static void pick_format(AVFilterLink *link)
+{
+    if(!link || !link->in_formats)
+        return;
+
+    link->in_formats->format_count = 1;
+    link->format = link->in_formats->formats[0];
+
+    avfilter_formats_unref(&link->in_formats);
+    avfilter_formats_unref(&link->out_formats);
+}
+
+static void pick_formats(GraphContext *graph)
+{
+    int i, j;
+
+    for(i = 0; i < graph->filter_count; i ++) {
+        AVFilterContext *filter = graph->filters[i];
+
+        if(filter->filter == &avfilter_vf_graph     ||
+           filter->filter == &avfilter_vf_graphfile ||
+           filter->filter == &avfilter_vf_graphdesc)
+            pick_formats(filter->priv);
+
+        for(j = 0; j < filter->input_count; j ++)
+            pick_format(filter->inputs[j]);
+        for(j = 0; j < filter->output_count; j ++)
+            pick_format(filter->outputs[j]);
+    }
+}
+
+int avfilter_graph_config_formats(AVFilterContext *graphctx)
+{
+    GraphContext *graph = graphctx->priv;
+
+    /* Find supported formats from sub-filters, and merge along links */
+    if(query_formats(graphctx))
+        return -1;
+
+    /* Once everything is merged, it's possible that we'll still have
+     * multiple valid choices of colorspace. We pick the first one. */
+    pick_formats(graph);
+
+    return 0;
+}
+
 int avfilter_graph_config_links(AVFilterContext *graphctx)
 {
     GraphContext *graph = graphctx->priv;
@@ -570,6 +635,8 @@ AVFilter avfilter_vf_graph =
     .init      = init,
     .uninit    = uninit,
 
+    .query_formats = query_formats,
+
     .inputs    = (AVFilterPad[]) {{ .name = NULL, }},
     .outputs   = (AVFilterPad[]) {{ .name = NULL, }},
 };
@@ -667,6 +734,8 @@ AVFilter avfilter_vf_graphdesc =
     .init      = init_desc,
     .uninit    = uninit,
 
+    .query_formats = query_formats,
+
     .inputs    = (AVFilterPad[]) {{ .name = NULL, }},
     .outputs   = (AVFilterPad[]) {{ .name = NULL, }},
 };
@@ -696,6 +765,8 @@ AVFilter avfilter_vf_graphfile =
     .init      = init_file,
     .uninit    = uninit,
 
+    .query_formats = query_formats,
+
     .inputs    = (AVFilterPad[]) {{ .name = NULL, }},
     .outputs   = (AVFilterPad[]) {{ .name = NULL, }},
 };
index 9a70868..d701a3d 100644 (file)
@@ -87,7 +87,12 @@ void avfilter_graph_free_desc(AVFilterGraphDesc *desc);
 void avfilter_graph_add_filter(AVFilterContext *graphctx, AVFilterContext *filter);
 
 /**
- * Configure the colorspace, resolution, etc of all links in the graph
+ * Configure the formats of all the links in the graph
+ */
+int avfilter_graph_config_formats(AVFilterContext *graphctx);
+
+/**
+ * Configure the resolution, etc of all links in the graph
  */
 int avfilter_graph_config_links(AVFilterContext *graphctx);