[FFmpeg-devel] [PATCH 2/3] avfiltergraph: don't query formats if filter has uninitialized inputs
Matthieu Bouron
matthieu.bouron at gmail.com
Thu May 3 15:39:11 CEST 2012
On Thu, May 03, 2012 at 03:16:40PM +0200, Nicolas George wrote:
> Le quintidi 15 floréal, an CCXX, Matthieu Bouron a écrit :
> > ---
> > libavfilter/avfiltergraph.c | 46 ++++++++++++++++++++++++++++++++++++-------
> > 1 file changed, 39 insertions(+), 7 deletions(-)
>
> Can you explain why this is necessary? I have some ideas, but I would like
> to compare ideas.
>
The complex filter system add vsrc_buffer and asrc_buffer (in next patch) at
the end of the avfilter context array and query_formats is currently called
sequentially it. It can lead to a filter initialization failure for filters
with input dependencies (like amerge)
The following example will fail on the amerge filter since the two abbufer
are not initialized:
[ amerge ] [ abuffer ] [ abuffer ] [ abuffersink ]
> > diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
> > index 9d7b956..064e678 100644
> > --- a/libavfilter/avfiltergraph.c
> > +++ b/libavfilter/avfiltergraph.c
> > @@ -202,17 +202,49 @@ static int insert_conv_filter(AVFilterGraph *graph, AVFilterLink *link,
> >
> > static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
> > {
> > - int i, j, ret;
> > + int i, j, k, ret;
> > char filt_args[128];
> > AVFilterFormats *formats, *chlayouts, *packing;
> > + int filters_init;
> > + int *filters_state = av_calloc(graph->filter_count, sizeof(int));
> >
> > /* ask all the sub-filters for their supported media formats */
> > - 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]);
> > - }
> > + do {
> > + filters_init = 1;
> > + for (i = 0; i < graph->filter_count; i++) {
> > + int do_query = 1;
> > + AVFilterContext *cur = graph->filters[i];
> > +
> > + if (filters_state[i])
> > + continue;
> > +
> > + /* Check state of input links */
> > + for (j = 0; j < cur->input_count; j++) {
> > + AVFilterContext *ifilter = cur->inputs[j]->src;
> > +
> > + for(k = 0; k < graph->filter_count; k++) {
> > + if (ifilter == graph->filters[k]) {
> > + break;
> > + }
> > + }
>
> This looks quadratic in the number of filters in the graph.
>
> > +
> > + if (!filters_state[k]) {
> > + do_query = 0;
> > + filters_init = 0;
> > + }
> > + }
> > +
> > + if (do_query) {
> > + filters_state[i] = 1;
> > + if (graph->filters[i]->filter->query_formats)
> > + graph->filters[i]->filter->query_formats(graph->filters[i]);
> > + else
> > + avfilter_default_query_formats(graph->filters[i]);
> > + }
> > + }
> > + } while (!filters_init);
> > +
> > + av_freep(&filters_state);
>
> On the whole, it looks like you want to do the queries in dependency order.
> There may be more efficient solutions.
I agree, this implementation is naive.
Another solution whould be to order the avfilter context array when avfilter_link
is called.
[...]
More information about the ffmpeg-devel
mailing list