|
@@ -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, }},
|
|
|
};
|