mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-08 21:28:45 +00:00
qtdemux: Fix seeking on streams with frame reordering
The samples table is sorted by DTS, not PTS. As such we can only get the correct result when using a binary search on it, if we search for the DTS. Also if we only ever search for the frame, where the following frame is the first one with a PTS after the search position, we will generally stop searching too early if frames are reordered. In forwards playback this is not really a problem (after the decoder reordered the frames, clipping is happening), in reverse playback it means that we can output one or more frames too few as we stop too early and the decoder would never receive it. https://bugzilla.gnome.org/show_bug.cgi?id=782118
This commit is contained in:
parent
ed2ccb1a60
commit
850e678813
1 changed files with 25 additions and 14 deletions
|
@ -1055,9 +1055,9 @@ typedef struct
|
||||||
static gint
|
static gint
|
||||||
find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
|
find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
|
||||||
{
|
{
|
||||||
if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
|
if ((gint64) s1->timestamp > *media_time)
|
||||||
return 1;
|
return 1;
|
||||||
if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
|
if ((gint64) s1->timestamp == *media_time)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1066,7 +1066,7 @@ find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
|
||||||
/* find the index of the sample that includes the data for @media_time using a
|
/* find the index of the sample that includes the data for @media_time using a
|
||||||
* binary search. Only to be called in optimized cases of linear search below.
|
* binary search. Only to be called in optimized cases of linear search below.
|
||||||
*
|
*
|
||||||
* Returns the index of the sample.
|
* Returns the index of the sample with the corresponding *DTS*.
|
||||||
*/
|
*/
|
||||||
static guint32
|
static guint32
|
||||||
gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
|
gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
|
||||||
|
@ -1156,20 +1156,31 @@ gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
|
||||||
|
|
||||||
/* use faster search if requested time in already parsed range */
|
/* use faster search if requested time in already parsed range */
|
||||||
sample = str->samples + str->stbl_index;
|
sample = str->samples + str->stbl_index;
|
||||||
if (str->stbl_index >= 0 &&
|
if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
|
||||||
mov_time <= (sample->timestamp + sample->pts_offset))
|
index = gst_qtdemux_find_index (qtdemux, str, media_time);
|
||||||
return gst_qtdemux_find_index (qtdemux, str, media_time);
|
sample = str->samples + index;
|
||||||
|
} else {
|
||||||
while (index < str->n_samples - 1) {
|
while (index < str->n_samples - 1) {
|
||||||
if (!qtdemux_parse_samples (qtdemux, str, index + 1))
|
if (!qtdemux_parse_samples (qtdemux, str, index + 1))
|
||||||
goto parse_failed;
|
goto parse_failed;
|
||||||
|
|
||||||
sample = str->samples + index + 1;
|
sample = str->samples + index + 1;
|
||||||
if (mov_time < (sample->timestamp + sample->pts_offset))
|
if (mov_time < sample->timestamp) {
|
||||||
|
sample = str->samples + index;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sample->timestamp is now <= media_time, need to find the corresponding
|
||||||
|
* PTS now by looking backwards */
|
||||||
|
while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
|
||||||
|
index--;
|
||||||
|
sample = str->samples + index;
|
||||||
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
|
Loading…
Reference in a new issue