From 7b4708780c6d6e9ec937b3148ce5df42ec55fd08 Mon Sep 17 00:00:00 2001 From: Vitor Sessak Date: Fri, 4 Apr 2008 20:07:41 +0000 Subject: [PATCH] Rewrite colorspace negotiation. 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 | 171 +++++++++++++++++++++++++----------- libavfilter/avfiltergraph.h | 7 +- 2 files changed, 127 insertions(+), 51 deletions(-) diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index fc79848312..665f80e600 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -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, }}, }; diff --git a/libavfilter/avfiltergraph.h b/libavfilter/avfiltergraph.h index 9a70868182..d701a3d584 100644 --- a/libavfilter/avfiltergraph.h +++ b/libavfilter/avfiltergraph.h @@ -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);