[FFmpeg-devel] [PATCH 1/2] avfilter: Implement graph_run_once_find_filter() in O(1)
Michael Niedermayer
michael at niedermayer.cc
Fri May 27 15:29:16 CEST 2016
Signed-off-by: Michael Niedermayer <michael at 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
More information about the ffmpeg-devel
mailing list