[FFmpeg-soc] [soc]: r4261 - libavfilter/vf_overlay.c

vitor subversion at mplayerhq.hu
Tue May 12 18:43:04 CEST 2009


Author: vitor
Date: Tue May 12 18:43:03 2009
New Revision: 4261

Log:
Change vf_overlay frame requesting logic so it do not call 
avfilter_request_frame() twice for the same input (what is not 
guaranteed to work). Also handle properly EOF.

Patch by Martin Storsjö - $firstname@$firstname.st

Modified:
   libavfilter/vf_overlay.c

Modified: libavfilter/vf_overlay.c
==============================================================================
--- libavfilter/vf_overlay.c	Fri May  8 15:00:28 2009	(r4260)
+++ libavfilter/vf_overlay.c	Tue May 12 18:43:03 2009	(r4261)
@@ -27,7 +27,9 @@ typedef struct {
     int x, y;                   //< position of subpicture
 
     /** pics[0][0..1] are pictures for the main image.
-     *  pics[1][0..1] are pictures for the sub image */
+     *  pics[1][0..1] are pictures for the sub image.
+     *  pics[x][0]    are previously outputted images.
+     *  pics[x][1]    are queued, yet unused frames for each input. */
     AVFilterPicRef *pics[2][2];
 
     int bpp;                    //< bytes per pixel
@@ -87,13 +89,27 @@ static int config_input_main(AVFilterLin
     return 0;
 }
 
+static void shift_input(OverlayContext *over, int idx)
+{
+    assert(over->pics[idx][0]);
+    assert(over->pics[idx][1]);
+    avfilter_unref_pic(over->pics[idx][0]);
+    over->pics[idx][0] = over->pics[idx][1];
+    over->pics[idx][1] = NULL;
+}
+
 static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
 {
     OverlayContext *over = link->dst->priv;
-    if(over->pics[link->dstpad][0])
-        avfilter_unref_pic(over->pics[link->dstpad][0]);
-    over->pics[link->dstpad][0] = over->pics[link->dstpad][1];
-    over->pics[link->dstpad][1] = picref;
+    /* There shouldn't be any previous queued frame in this queue */
+    assert(!over->pics[link->dstpad][1]);
+    if (over->pics[link->dstpad][0]) {
+        /* Queue the new frame */
+        over->pics[link->dstpad][1] = picref;
+    } else {
+        /* No previous unused frame, take this one into use directly */
+        over->pics[link->dstpad][0] = picref;
+    }
 }
 
 static void end_frame(AVFilterLink *link)
@@ -138,20 +154,43 @@ static int request_frame(AVFilterLink *l
     int idx;
     int x, y, w, h;
 
-    /* the first time through, we need to pull a couple frames */
-    if(!over->pics[0][1] && !over->pics[1][1] &&
-       (avfilter_request_frame(link->src->inputs[0]) ||
-        avfilter_request_frame(link->src->inputs[1])))
-        return -1;
+    if (!over->pics[0][0] || !over->pics[1][0]) {
+        /* No frame output yet, we need one frame from each input */
+        if (!over->pics[0][0] && avfilter_request_frame(link->src->inputs[0]))
+            return AVERROR_EOF;
+        if (!over->pics[1][0] && avfilter_request_frame(link->src->inputs[1]))
+            return AVERROR_EOF;
+    } else {
+        int eof = 0;
 
-    /* then we pull a frame from the stream which currently has a lower pts */
-    if((idx = lower_timestamp(over)) == 2) {
-        if(avfilter_request_frame(link->src->inputs[0]) ||
-           avfilter_request_frame(link->src->inputs[1]))
-            return -1;
-    } else
-        if(avfilter_request_frame(link->src->inputs[idx]))
-            return -1;
+        /* Try pulling a new candidate from each input unless we already
+           have one */
+        for (idx = 0; idx < 2; idx++) {
+            if (!over->pics[idx][1] &&
+                 avfilter_request_frame(link->src->inputs[idx]))
+                eof++;
+        }
+        if (eof == 2)
+            return AVERROR_EOF; /* No new candidates in any input; EOF */
+
+        /* At least one new frame */
+        assert(over->pics[0][1] || over->pics[1][1]);
+
+        if (over->pics[0][1] && over->pics[1][1]) {
+            /* Neither one of the inputs has finished */
+            if ((idx = lower_timestamp(over)) == 2) {
+                shift_input(over, 0);
+                shift_input(over, 1);
+            } else
+                shift_input(over, idx);
+        } else if (over->pics[0][1]) {
+            /* Use the single new input frame */
+            shift_input(over, 0);
+        } else {
+            assert(over->pics[1][1]);
+            shift_input(over, 1);
+        }
+    }
 
     /* we draw the output frame */
     pic = avfilter_get_video_buffer(link, AV_PERM_WRITE);


More information about the FFmpeg-soc mailing list