[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