matroska: implement forward snapping keyframe seeking
authorVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Thu, 26 Apr 2012 11:47:27 +0000 (12:47 +0100)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Mon, 30 Apr 2012 09:37:57 +0000 (10:37 +0100)
Requires an index.

gst/matroska/matroska-demux.c
gst/matroska/matroska-parse.c
gst/matroska/matroska-read-common.c
gst/matroska/matroska-read-common.h

index 6d9f7e6..34c3699 100644 (file)
@@ -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;
index 5efbf89..c7acb89 100644 (file)
@@ -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);
index a95a95e..146255c 100644 (file)
@@ -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;
index 7488bc0..0a18eaa 100644 (file)
@@ -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);