oggdemux: fix seeking with negative rate with skeleton
authorGuillaume Emont <gemont@igalia.com>
Thu, 7 Oct 2010 17:32:56 +0000 (19:32 +0200)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Sun, 10 Oct 2010 16:26:13 +0000 (18:26 +0200)
Files with a skeleton, or other files with a stream that ends before the end of
the chain would start playing from the end of the chain when trying to seek with
a negative rate at a position between the end of any stream and the end of the
chain.

This is due to the loop in _do_seek() assuming that pages will be encountered
for all streams shortly after the place where we want to seek, as found by
do_binary_search().

In the first iteration of the loop, stream ends are now checked against the
time of the current page.

ext/ogg/gstoggdemux.c

index cb1f2dd..d7774dc 100644 (file)
@@ -2050,6 +2050,7 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
   gint64 result = 0;
   GstFlowReturn ret;
   gint i, pending, len;
+  gboolean first_parsed_page = TRUE;
 
   position = segment->last_stop;
 
@@ -2114,6 +2115,32 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
       continue;
     }
 
+    /* we only do this the first time we pass here */
+    if (first_parsed_page) {
+      /* Now that we have a time reference from the page, we can check
+       * whether all streams still have pages from here on.
+       *
+       * This would be more elegant before the loop, but getting the page from
+       * there without breaking anything would be more costly */
+      granule_time = gst_ogg_stream_get_end_time_for_granulepos (&pad->map,
+          granulepos);
+      for (i = 0; i < len; i++) {
+        GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, i);
+
+        if (stream == pad)
+          /* we already know we have at least one page (the current one)
+           * for this stream */
+          continue;
+
+        if (granule_time > stream->map.total_time)
+          /* we won't encounter any more pages of this stream, so we don't
+           * try finding a key frame for it */
+          pending--;
+      }
+      first_parsed_page = FALSE;
+    }
+
+
     /* in reverse we want to go past the page with the lower timestamp */
     if (segment->rate < 0.0) {
       /* get time for this pad */