hlsdemux: fix reverse playback seek with snap flags
authorThiago Santos <thiagoss@osg.samsung.com>
Tue, 5 Jan 2016 12:16:45 +0000 (09:16 -0300)
committerThiago Santos <thiagoss@osg.samsung.com>
Wed, 6 Jan 2016 13:23:13 +0000 (10:23 -0300)
Properly handle snap flags during reverse seeking. In this case
the before/after are also reversed, so handle those as such.

For example: with a sequence of 1s fragments:

|-- 0 --|-- 1 --|-- 2 --|-- 3 --|

If you seek to 1.5s it is inside fragment 1. With reverse and

snap-before: should play from the end of fragment 1
snap-after: should play from the end of fragment 0

ext/hls/gsthlsdemux.c

index 713ab8e..5da4fc6 100644 (file)
@@ -248,6 +248,7 @@ gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
   GstM3U8MediaFile *file;
   guint64 bitrate;
   gboolean snap_before, snap_after, snap_nearest, keyunit;
+  gboolean reverse;
 
   gst_event_parse_seek (seek, &rate, &format, &flags, &start_type, &start,
       &stop_type, &stop);
@@ -304,7 +305,8 @@ gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
   file = GST_M3U8_MEDIA_FILE (hlsdemux->client->current->files->data);
   current_sequence = file->sequence;
   current_pos = 0;
-  target_pos = rate > 0 ? start : stop;
+  reverse = rate < 0;
+  target_pos = reverse ? stop : start;
 
   /* Snap to segment boundary. Improves seek performance on slow machines. */
   snap_before = snap_after = snap_nearest = FALSE;
@@ -320,11 +322,19 @@ gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
 
     current_sequence = file->sequence;
     current_file = walk;
-    if (snap_after || snap_nearest) {
+    if ((!reverse && snap_after) || snap_nearest) {
       if (current_pos >= target_pos)
         break;
       if (snap_nearest && target_pos - current_pos < file->duration / 2)
         break;
+    } else if (reverse && snap_after) {
+      /* check if the next fragment is our target, in this case we want to
+       * start from the previous fragment */
+      GstClockTime next_pos = current_pos + file->duration;
+
+      if (next_pos <= target_pos && target_pos < next_pos + file->duration) {
+        break;
+      }
     } else if (current_pos <= target_pos
         && target_pos < current_pos + file->duration) {
       break;
@@ -345,9 +355,18 @@ gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
   hlsdemux->client->sequence_position = current_pos;
   GST_M3U8_CLIENT_UNLOCK (hlsdemux->client);
 
-  if (keyunit || snap_before || snap_after || snap_nearest)
-    gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
-        current_pos, stop_type, stop, NULL);
+  /* Play from the end of the current selected segment */
+  if (reverse && (snap_before || snap_after || snap_nearest))
+    current_pos += file->duration;
+
+  if (keyunit || snap_before || snap_after || snap_nearest) {
+    if (!reverse)
+      gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
+          current_pos, stop_type, stop, NULL);
+    else
+      gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
+          start, stop_type, current_pos, NULL);
+  }
 
   return TRUE;
 }