From b41cd0428956f3ade9b428149e38be8e788556fe Mon Sep 17 00:00:00 2001 From: Guillaume Emont Date: Thu, 7 Oct 2010 19:32:56 +0200 Subject: [PATCH] oggdemux: fix seeking with negative rate with skeleton 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 | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index cb1f2dd..d7774dc 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -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 */ -- 2.7.4