summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Schmidt <jan@centricular.com>2015-01-31 02:30:40 +1100
committerJan Schmidt <jan@centricular.com>2015-01-31 06:15:44 +1100
commit4a77c8a84fe921d754124c87e7a8f16e4f49523c (patch)
tree8ece20bb16435721da42227973f940a1d60675f2
parent075eb10e65a84b524f8f8b72d3bdfefb0bf27588 (diff)
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
-rw-r--r--gst/matroska/matroska-demux.c54
-rw-r--r--gst/matroska/matroska-parse.c8
-rw-r--r--gst/matroska/matroska-read-common.c18
-rw-r--r--gst/matroska/matroska-read-common.h2
4 files changed, 51 insertions, 31 deletions
diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c
index 33568792e..9eb7aedbd 100644
--- a/gst/matroska/matroska-demux.c
+++ b/gst/matroska/matroska-demux.c
@@ -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");
diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c
index 1eeef5cf6..9abd67fa1 100644
--- a/gst/matroska/matroska-parse.c
+++ b/gst/matroska/matroska-parse.c
@@ -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);
diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c
index 51494a123..f2f1ee1ed 100644
--- a/gst/matroska/matroska-read-common.c
+++ b/gst/matroska/matroska-read-common.c
@@ -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);
}
}
diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h
index 6495e831a..de2102689 100644
--- a/gst/matroska/matroska-read-common.h
+++ b/gst/matroska/matroska-read-common.h
@@ -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);