mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-27 08:48:19 +00:00
matroska: Fix seeking past the end of the file in reverse mode.
Snap to the end of the file when seeking past the end in reverse mode, and also fix GST_SEEK_TYPE_END and GST_SEEK_TYPE_NONE handling for the stop position by always seeking on a segment in stream time
This commit is contained in:
parent
075eb10e65
commit
4a77c8a84f
|
@ -1873,10 +1873,15 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
|||
gboolean update = TRUE;
|
||||
gboolean pad_locked = FALSE;
|
||||
guint32 seqnum;
|
||||
GstSearchMode snap_dir;
|
||||
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
if (pad)
|
||||
track = gst_pad_get_element_private (pad);
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "Have seek %" GST_PTR_FORMAT, event);
|
||||
|
||||
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
|
||||
&stop_type, &stop);
|
||||
seqnum = gst_event_get_seqnum (event);
|
||||
|
@ -1899,25 +1904,29 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
|||
seeksegment.duration = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
if (event) {
|
||||
GST_DEBUG_OBJECT (demux, "configuring seek");
|
||||
gst_segment_do_seek (&seeksegment, rate, format, flags,
|
||||
cur_type, cur, stop_type, stop, &update);
|
||||
/* compensate for clip start time, but only for SET seeks,
|
||||
* otherwise it is already part of the segments */
|
||||
if (GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) {
|
||||
if (cur_type == GST_SEEK_TYPE_SET) {
|
||||
if (rate > 0.0)
|
||||
seeksegment.position += demux->stream_start_time;
|
||||
seeksegment.start += demux->stream_start_time;
|
||||
}
|
||||
if (stop_type == GST_SEEK_TYPE_SET
|
||||
&& GST_CLOCK_TIME_IS_VALID (seeksegment.stop)) {
|
||||
if (rate < 0.0)
|
||||
seeksegment.position += demux->stream_start_time;
|
||||
seeksegment.stop += demux->stream_start_time;
|
||||
}
|
||||
}
|
||||
GST_DEBUG_OBJECT (demux, "configuring seek");
|
||||
/* Subtract stream_start_time so we always seek on a segment
|
||||
* in stream time */
|
||||
if (GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) {
|
||||
seeksegment.start -= demux->stream_start_time;
|
||||
seeksegment.position -= demux->stream_start_time;
|
||||
if (GST_CLOCK_TIME_IS_VALID (seeksegment.stop))
|
||||
seeksegment.stop -= demux->stream_start_time;
|
||||
else
|
||||
seeksegment.stop = seeksegment.duration;
|
||||
}
|
||||
|
||||
gst_segment_do_seek (&seeksegment, rate, format, flags,
|
||||
cur_type, cur, stop_type, stop, &update);
|
||||
|
||||
/* Restore the clip timestamp offset */
|
||||
if (GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) {
|
||||
seeksegment.position += demux->stream_start_time;
|
||||
seeksegment.start += demux->stream_start_time;
|
||||
if (!GST_CLOCK_TIME_IS_VALID (seeksegment.stop))
|
||||
seeksegment.stop = seeksegment.duration;
|
||||
if (GST_CLOCK_TIME_IS_VALID (seeksegment.stop))
|
||||
seeksegment.stop += demux->stream_start_time;
|
||||
}
|
||||
|
||||
/* restore segment duration (if any effect),
|
||||
|
@ -1938,12 +1947,15 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
|
|||
/* check sanity before we start flushing and all that */
|
||||
snap_next = after && !before;
|
||||
if (seeksegment.rate < 0)
|
||||
snap_next = !snap_next;
|
||||
snap_dir = snap_next ? GST_SEARCH_MODE_BEFORE : GST_SEARCH_MODE_AFTER;
|
||||
else
|
||||
snap_dir = snap_next ? GST_SEARCH_MODE_AFTER : GST_SEARCH_MODE_BEFORE;
|
||||
|
||||
GST_OBJECT_LOCK (demux);
|
||||
track = gst_matroska_read_common_get_seek_track (&demux->common, track);
|
||||
if ((entry = gst_matroska_read_common_do_index_seek (&demux->common, track,
|
||||
seeksegment.position, &demux->seek_index, &demux->seek_entry,
|
||||
snap_next)) == NULL) {
|
||||
snap_dir)) == NULL) {
|
||||
/* pull mode without index can scan later on */
|
||||
if (demux->streaming) {
|
||||
GST_DEBUG_OBJECT (demux, "No matching seek entry in index");
|
||||
|
|
|
@ -1221,6 +1221,7 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
|
|||
GstMatroskaTrackContext *track = NULL;
|
||||
GstSegment seeksegment = { 0, };
|
||||
gboolean update;
|
||||
GstSearchMode snap_dir;
|
||||
|
||||
if (pad)
|
||||
track = gst_pad_get_element_private (pad);
|
||||
|
@ -1248,11 +1249,16 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
|
|||
|
||||
GST_DEBUG_OBJECT (parse, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
|
||||
|
||||
if (seeksegment.rate < 0)
|
||||
snap_dir = GST_SEARCH_MODE_AFTER;
|
||||
else
|
||||
snap_dir = GST_SEARCH_MODE_BEFORE;
|
||||
|
||||
/* check sanity before we start flushing and all that */
|
||||
GST_OBJECT_LOCK (parse);
|
||||
if ((entry = gst_matroska_read_common_do_index_seek (&parse->common, track,
|
||||
seeksegment.position, &parse->seek_index, &parse->seek_entry,
|
||||
FALSE)) == NULL) {
|
||||
snap_dir)) == NULL) {
|
||||
/* pull mode without index can scan later on */
|
||||
GST_DEBUG_OBJECT (parse, "No matching seek entry in index");
|
||||
GST_OBJECT_UNLOCK (parse);
|
||||
|
|
|
@ -375,30 +375,32 @@ gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
|
|||
GstMatroskaIndex *
|
||||
gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common,
|
||||
GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
|
||||
gint * _entry_index, gboolean next)
|
||||
gint * _entry_index, GstSearchMode snap_dir)
|
||||
{
|
||||
GstMatroskaIndex *entry = NULL;
|
||||
GArray *index;
|
||||
|
||||
if (!common->index || !common->index->len)
|
||||
return NULL;
|
||||
|
||||
/* find entry just before or at the requested position */
|
||||
if (track && track->index_table)
|
||||
index = track->index_table;
|
||||
else
|
||||
index = common->index;
|
||||
|
||||
if (!index || !index->len)
|
||||
return NULL;
|
||||
|
||||
entry =
|
||||
gst_util_array_binary_search (index->data, index->len,
|
||||
sizeof (GstMatroskaIndex),
|
||||
(GCompareDataFunc) gst_matroska_index_seek_find,
|
||||
next ? GST_SEARCH_MODE_AFTER : GST_SEARCH_MODE_BEFORE, &seek_pos, NULL);
|
||||
(GCompareDataFunc) gst_matroska_index_seek_find, snap_dir, &seek_pos,
|
||||
NULL);
|
||||
|
||||
if (entry == NULL) {
|
||||
if (next) {
|
||||
return NULL;
|
||||
if (snap_dir == GST_SEARCH_MODE_AFTER) {
|
||||
/* Can only happen with a reverse seek past the end */
|
||||
entry = &g_array_index (index, GstMatroskaIndex, index->len - 1);
|
||||
} else {
|
||||
/* Can only happen with a forward seek before the start */
|
||||
entry = &g_array_index (index, GstMatroskaIndex, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ gint gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
|
|||
gpointer user_data);
|
||||
GstMatroskaIndex * gst_matroska_read_common_do_index_seek (
|
||||
GstMatroskaReadCommon * common, GstMatroskaTrackContext * track, gint64
|
||||
seek_pos, GArray ** _index, gint * _entry_index, gboolean next);
|
||||
seek_pos, GArray ** _index, gint * _entry_index, GstSearchMode snap_dir);
|
||||
void gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
|
||||
GstElement * el, GstTagList * taglist);
|
||||
gint64 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common);
|
||||
|
|
Loading…
Reference in a new issue