From 93ce50f9b924a061ee65693f0d87960d50beedc4 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 26 Apr 2012 12:47:27 +0100 Subject: [PATCH] matroska: implement forward snapping keyframe seeking Requires an index. --- gst/matroska/matroska-demux.c | 20 +++++++++++++------- gst/matroska/matroska-parse.c | 4 ++-- gst/matroska/matroska-read-common.c | 15 ++++++++++----- gst/matroska/matroska-read-common.h | 2 +- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 6d9f7e60a7..34c3699a2a 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -1925,7 +1925,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, GstSeekFlags flags; GstSeekType cur_type, stop_type; GstFormat format; - gboolean flush, keyunit; + gboolean flush, keyunit, before, after, snap_next; gdouble rate; gint64 cur, stop; GstMatroskaTrackContext *track = NULL; @@ -1975,8 +1975,10 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, * would be determined again when parsing, but anyway ... */ seeksegment.duration = demux->common.segment.duration; - flush = ! !(flags & GST_SEEK_FLAG_FLUSH); - keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT); + flush = !!(flags & GST_SEEK_FLAG_FLUSH); + keyunit = !!(flags & GST_SEEK_FLAG_KEY_UNIT); + after = !!(flags & GST_SEEK_FLAG_SNAP_AFTER); + before = !!(flags & GST_SEEK_FLAG_SNAP_BEFORE); GST_DEBUG_OBJECT (demux, "New segment %" GST_SEGMENT_FORMAT, &seeksegment); @@ -1989,11 +1991,14 @@ 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; 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)) == - NULL) { + seeksegment.position, &demux->seek_index, &demux->seek_entry, + snap_next)) == NULL) { /* pull mode without index can scan later on */ if (demux->streaming) { GST_DEBUG_OBJECT (demux, "No matching seek entry in index"); @@ -2053,8 +2058,9 @@ next: } if (keyunit) { - GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start to %" - GST_TIME_FORMAT, GST_TIME_ARGS (entry->time)); + GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start from %" + GST_TIME_FORMAT " to %" GST_TIME_FORMAT, + GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (entry->time)); seeksegment.start = MAX (entry->time, demux->stream_start_time); seeksegment.position = seeksegment.start; seeksegment.time = seeksegment.start - demux->stream_start_time; diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index 5efbf8969b..c7acb89982 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -1364,8 +1364,8 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse, /* 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)) == - NULL) { + seeksegment.position, &parse->seek_index, &parse->seek_entry, + FALSE)) == 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 a95a95ee55..146255c5e2 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -365,7 +365,7 @@ 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) + gint * _entry_index, gboolean next) { GstMatroskaIndex *entry = NULL; GArray *index; @@ -382,11 +382,16 @@ gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common, entry = gst_util_array_binary_search (index->data, index->len, sizeof (GstMatroskaIndex), - (GCompareDataFunc) gst_matroska_index_seek_find, GST_SEARCH_MODE_BEFORE, - &seek_pos, NULL); + (GCompareDataFunc) gst_matroska_index_seek_find, + next ? GST_SEARCH_MODE_AFTER : GST_SEARCH_MODE_BEFORE, &seek_pos, NULL); - if (entry == NULL) - entry = &g_array_index (index, GstMatroskaIndex, 0); + if (entry == NULL) { + if (next) { + return NULL; + } else { + entry = &g_array_index (index, GstMatroskaIndex, 0); + } + } if (_index) *_index = index; diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index 7488bc0ded..0a18eaa81a 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -106,7 +106,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); + seek_pos, GArray ** _index, gint * _entry_index, gboolean next); void gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common, GstElement * el, GstTagList * taglist); gint64 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common);