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.
This commit is contained in:
Guillaume Emont 2010-10-07 19:32:56 +02:00 committed by Sebastian Dröge
parent b3629a7e1f
commit b41cd04289

View file

@ -2050,6 +2050,7 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
gint64 result = 0; gint64 result = 0;
GstFlowReturn ret; GstFlowReturn ret;
gint i, pending, len; gint i, pending, len;
gboolean first_parsed_page = TRUE;
position = segment->last_stop; position = segment->last_stop;
@ -2114,6 +2115,32 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
continue; 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 */ /* in reverse we want to go past the page with the lower timestamp */
if (segment->rate < 0.0) { if (segment->rate < 0.0) {
/* get time for this pad */ /* get time for this pad */