videorate: Fill the segment on EOS or at least produce enough frames to use the compl...
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 1 Sep 2010 09:33:12 +0000 (11:33 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 1 Sep 2010 09:33:12 +0000 (11:33 +0200)
Fixes bug #628400.

gst/videorate/gstvideorate.c

index 7f3c898..4ef4e90 100644 (file)
@@ -577,11 +577,55 @@ gst_video_rate_event (GstPad * pad, GstEvent * event)
           &videorate->segment);
       break;
     }
-    case GST_EVENT_EOS:
-      /* flush last queued frame */
+    case GST_EVENT_EOS:{
+      gint count = 0;
+      GstFlowReturn res = GST_FLOW_OK;
+
       GST_DEBUG_OBJECT (videorate, "Got EOS");
-      gst_video_rate_flush_prev (videorate, FALSE);
+
+      /* If the segment has a stop position, fill the segment */
+      if (GST_CLOCK_TIME_IS_VALID (videorate->segment.stop)) {
+        /* fill up to the end of current segment,
+         * or only send out the stored buffer if there is no specific stop.
+         * regardless, prevent going loopy in strange cases */
+        while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
+            ((videorate->next_ts - videorate->segment.accum <
+                    videorate->segment.stop)
+                || count < 1)) {
+          res = gst_video_rate_flush_prev (videorate, count > 0);
+          count++;
+        }
+      } else if (videorate->prevbuf) {
+        /* Output at least one frame but if the buffer duration is valid, output
+         * enough frames to use the complete buffer duration */
+        if (GST_BUFFER_DURATION_IS_VALID (videorate->prevbuf)) {
+          GstClockTime end_ts =
+              videorate->next_ts + GST_BUFFER_DURATION (videorate->prevbuf);
+
+          while (res == GST_FLOW_OK && count <= MAGIC_LIMIT &&
+              ((videorate->next_ts - videorate->segment.accum < end_ts)
+                  || count < 1)) {
+            res = gst_video_rate_flush_prev (videorate, count > 0);
+            count++;
+          }
+        } else {
+          res = gst_video_rate_flush_prev (videorate, FALSE);
+          count = 1;
+        }
+      }
+
+      if (count > 1) {
+        videorate->dup += count - 1;
+        if (!videorate->silent)
+          g_object_notify (G_OBJECT (videorate), "duplicate");
+      } else if (count == 0) {
+        videorate->drop++;
+        if (!videorate->silent)
+          g_object_notify (G_OBJECT (videorate), "drop");
+      }
+
       break;
+    }
     case GST_EVENT_FLUSH_STOP:
       /* also resets the segment */
       GST_DEBUG_OBJECT (videorate, "Got FLUSH_STOP");