Signed-off-by: Michael Niedermayer <mich...@niedermayer.cc> --- libavfilter/avfilter.c | 53 +++++++++++++++++++++++++++++++++++++------ libavfilter/avfilter.h | 8 +++++++ libavfilter/avfiltergraph.c | 31 ++++++++++++------------- 3 files changed, 68 insertions(+), 24 deletions(-)
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 21f8d9e..e270628 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -180,6 +180,44 @@ int avfilter_link_get_channels(AVFilterLink *link) return link->channels; } +#define MAKE_SET_CLEAR_FRAME_WANTED_FUNC(DIR) \ +static void set_frame_wanted_ ## DIR(AVFilterLink *link)\ +{\ + if (!link->frame_wanted_ ## DIR) {\ + AVFilterGraph *graph = link->graph;\ + AVFilterLink *next, *prev;\ + next = graph->next_link_wanting_frame_ ## DIR;\ + if (!next) {\ + prev = next = link;\ + } else\ + prev = next->prev_link_wanting_frame_ ## DIR;\ + link->next_link_wanting_frame_ ## DIR = next;\ + link->prev_link_wanting_frame_ ## DIR = prev;\ + prev->prev_link_wanting_frame_ ## DIR = \ + next->prev_link_wanting_frame_ ## DIR = link;\ + graph->next_link_wanting_frame_ ## DIR = link;\ + link->frame_wanted_ ## DIR = 1;\ + }\ +}\ +\ +static void clear_frame_wanted_ ## DIR(AVFilterLink *link)\ +{\ + if (link->frame_wanted_ ## DIR) {\ + AVFilterGraph *graph = link->graph;\ + AVFilterLink *prev = link->prev_link_wanting_frame_ ## DIR;\ + AVFilterLink *next = link->next_link_wanting_frame_ ## DIR;\ + next->prev_link_wanting_frame_ ## DIR = prev;\ + prev->next_link_wanting_frame_ ## DIR = next;\ + link->next_link_wanting_frame_ ## DIR = NULL;\ + graph->next_link_wanting_frame_ ## DIR = prev->next_link_wanting_frame_ ## DIR;\ + link->prev_link_wanting_frame_ ## DIR = NULL;\ + link->frame_wanted_ ## DIR = 0;\ + }\ +} + +MAKE_SET_CLEAR_FRAME_WANTED_FUNC(in) // create set_frame_wanted_in() clear_frame_wanted_in() +MAKE_SET_CLEAR_FRAME_WANTED_FUNC(out)// create set_frame_wanted_out() clear_frame_wanted_out() + void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts) { ff_avfilter_link_set_out_status(link, status, pts); @@ -188,7 +226,8 @@ void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts) void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts) { link->status = status; - link->frame_wanted_in = link->frame_wanted_out = 0; + clear_frame_wanted_in(link); + clear_frame_wanted_out(link); ff_update_link_current_pts(link, pts); } @@ -372,8 +411,8 @@ int ff_request_frame(AVFilterLink *link) if (link->status) return link->status; - link->frame_wanted_in = 1; - link->frame_wanted_out = 1; + set_frame_wanted_in(link); + set_frame_wanted_out(link); return 0; } @@ -382,7 +421,7 @@ int ff_request_frame_to_filter(AVFilterLink *link) int ret = -1; FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1); - link->frame_wanted_in = 0; + clear_frame_wanted_in(link); if (link->srcpad->request_frame) ret = link->srcpad->request_frame(link); else if (link->src->inputs[0]) @@ -392,7 +431,7 @@ int ff_request_frame_to_filter(AVFilterLink *link) link->partial_buf = NULL; ret = ff_filter_frame_framed(link, pbuf); ff_avfilter_link_set_in_status(link, AVERROR_EOF, AV_NOPTS_VALUE); - link->frame_wanted_out = 0; + clear_frame_wanted_out(link); return ret; } if (ret < 0) { @@ -1169,7 +1208,7 @@ static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame) pbuf = NULL; } else { if (link->frame_wanted_out) - link->frame_wanted_in = 1; + set_frame_wanted_in(link); } } av_frame_free(&frame); @@ -1211,7 +1250,7 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) } } - link->frame_wanted_out = 0; + clear_frame_wanted_out(link); /* Go directly to actual filtering if possible */ if (link->type == AVMEDIA_TYPE_AUDIO && link->min_samples && diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 79227a7..7d05f4c 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -550,6 +550,11 @@ struct AVFilterLink { * cleared when a frame is filtered. */ int frame_wanted_out; + + AVFilterLink *next_link_wanting_frame_in; + AVFilterLink *prev_link_wanting_frame_in; + AVFilterLink *next_link_wanting_frame_out; + AVFilterLink *prev_link_wanting_frame_out; }; /** @@ -842,6 +847,9 @@ typedef struct AVFilterGraph { int sink_links_count; unsigned disable_auto_convert; + + AVFilterLink *next_link_wanting_frame_in; + AVFilterLink *next_link_wanting_frame_out; } AVFilterGraph; /** diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index 4275113..af6a554 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -104,6 +104,9 @@ void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter if (filter->outputs[j]) filter->outputs[j]->graph = NULL; + // Note if we add a feature that allows rmoving filters and then + // continuing then the filter must be removed from next_link_wanting_frame_* + return; } } @@ -1402,23 +1405,17 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph) static AVFilterLink *graph_run_once_find_filter(AVFilterGraph *graph) { - unsigned i, j; - AVFilterContext *f; - - /* TODO: replace scanning the graph with a priority list */ - for (i = 0; i < graph->nb_filters; i++) { - f = graph->filters[i]; - for (j = 0; j < f->nb_outputs; j++) - if (f->outputs[j]->frame_wanted_in) - return f->outputs[j]; - } - for (i = 0; i < graph->nb_filters; i++) { - f = graph->filters[i]; - for (j = 0; j < f->nb_outputs; j++) - if (f->outputs[j]->frame_wanted_out) - return f->outputs[j]; - } - return NULL; + AVFilterLink *link = graph->next_link_wanting_frame_in; + if (link) + av_assert0(link->frame_wanted_in); + if (!link) + link = graph->next_link_wanting_frame_out; + if (link) + av_assert0(link->graph == graph); + if (link) + av_assert0(link->frame_wanted_in || link->frame_wanted_out); + + return link; } int ff_filter_graph_run_once(AVFilterGraph *graph) -- 1.7.9.5 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel