adaptivedemux2: Handle early key-unit seek
authorEdward Hervey <edward@centricular.com>
Wed, 8 Feb 2023 16:24:18 +0000 (17:24 +0100)
committerEdward Hervey <bilboed@bilboed.com>
Fri, 23 Jun 2023 06:51:05 +0000 (08:51 +0200)
Is a seek is done on stream-collection post, there are no selected streams
yet. Therefore none would be chosen to adjust the key-unit seek.

If no streams are selected, fallback to a default stream (i.e. one which has
track(s) with GST_STREAM_FLAG_SELECT).

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4922>

subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-private.h
subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c
subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c

index a72cefe..ee50f77 100644 (file)
@@ -191,6 +191,7 @@ gboolean gst_adaptive_demux_get_live_seek_range (GstAdaptiveDemux * demux,
 gboolean gst_adaptive_demux2_stream_in_live_seek_range (GstAdaptiveDemux * demux,
     GstAdaptiveDemux2Stream * stream);
 gboolean gst_adaptive_demux2_stream_is_selected_locked (GstAdaptiveDemux2Stream *stream);
+gboolean gst_adaptive_demux2_stream_is_default_locked (GstAdaptiveDemux2Stream *stream);
 
 gboolean gst_adaptive_demux_has_next_period (GstAdaptiveDemux * demux);
 void gst_adaptive_demux_advance_period (GstAdaptiveDemux * demux);
index 8981ac1..217d78e 100644 (file)
@@ -2097,6 +2097,20 @@ gst_adaptive_demux2_stream_is_selected_locked (GstAdaptiveDemux2Stream * stream)
   return FALSE;
 }
 
+gboolean
+gst_adaptive_demux2_stream_is_default_locked (GstAdaptiveDemux2Stream * stream)
+{
+  GList *tmp;
+
+  for (tmp = stream->tracks; tmp; tmp = tmp->next) {
+    GstAdaptiveDemuxTrack *track = tmp->data;
+    if (track->flags & GST_STREAM_FLAG_SELECT)
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
 /**
  * gst_adaptive_demux2_stream_is_selected:
  * @stream: A #GstAdaptiveDemux2Stream
index afba0ec..00c9c9c 100644 (file)
@@ -2212,72 +2212,84 @@ gst_adaptive_demux_handle_seek_event (GstAdaptiveDemux * demux,
 
   GST_ADAPTIVE_DEMUX_SEGMENT_LOCK (demux);
 
-  /*
-   * Handle snap seeks as follows:
-   * 1) do the snap seeking a (random) active stream
-   * 2) use the final position on this stream to seek
-   *    on the other streams to the same position
-   *
-   * We can't snap at all streams at the same time as they might end in
-   * different positions, so just pick one and align all others to that
-   * position.
-   */
-
-  GstAdaptiveDemux2Stream *stream = NULL;
-  GList *iter;
-  /* Pick a random active stream on which to do the stream seek */
-  for (iter = demux->output_period->streams; iter; iter = iter->next) {
-    GstAdaptiveDemux2Stream *cand = iter->data;
-    if (gst_adaptive_demux2_stream_is_selected_locked (cand)) {
-      stream = cand;
-      break;
-    }
-  }
-
-  if (stream && IS_SNAP_SEEK (flags)) {
-    GstClockTimeDiff ts;
-    GstSeekFlags stream_seek_flags = flags;
+  if (IS_SNAP_SEEK (flags)) {
+    GstAdaptiveDemux2Stream *default_stream = NULL;
+    GstAdaptiveDemux2Stream *stream = NULL;
+    GList *iter;
+    /*
+     * Handle snap seeks as follows:
+     * 1) do the snap seeking a (random) active stream
+     * 1.1) If none are active yet (early-seek), pick a random default one
+     * 2) use the final position on this stream to seek
+     *    on the other streams to the same position
+     *
+     * We can't snap at all streams at the same time as they might end in
+     * different positions, so just pick one and align all others to that
+     * position.
+     */
 
-    /* snap-seek on the chosen stream and then
-     * use the resulting position to seek on all streams */
-    if (rate >= 0) {
-      if (start_type != GST_SEEK_TYPE_NONE)
-        ts = start;
-      else {
-        ts = gst_segment_position_from_running_time (&demux->segment,
-            GST_FORMAT_TIME, demux->priv->global_output_position);
-        start_type = GST_SEEK_TYPE_SET;
+    /* Pick a random active stream on which to do the stream seek */
+    for (iter = demux->output_period->streams; iter; iter = iter->next) {
+      GstAdaptiveDemux2Stream *cand = iter->data;
+      if (gst_adaptive_demux2_stream_is_selected_locked (cand)) {
+        stream = cand;
+        break;
       }
-    } else {
-      if (stop_type != GST_SEEK_TYPE_NONE)
-        ts = stop;
-      else {
-        stop_type = GST_SEEK_TYPE_SET;
-        ts = gst_segment_position_from_running_time (&demux->segment,
-            GST_FORMAT_TIME, demux->priv->global_output_position);
+      if (default_stream == NULL
+          && gst_adaptive_demux2_stream_is_default_locked (cand))
+        default_stream = cand;
+    }
+
+    if (stream == NULL)
+      stream = default_stream;
+
+    if (stream) {
+      GstClockTimeDiff ts;
+      GstSeekFlags stream_seek_flags = flags;
+
+      /* snap-seek on the chosen stream and then
+       * use the resulting position to seek on all streams */
+      if (rate >= 0) {
+        if (start_type != GST_SEEK_TYPE_NONE)
+          ts = start;
+        else {
+          ts = gst_segment_position_from_running_time (&demux->segment,
+              GST_FORMAT_TIME, demux->priv->global_output_position);
+          start_type = GST_SEEK_TYPE_SET;
+        }
+      } else {
+        if (stop_type != GST_SEEK_TYPE_NONE)
+          ts = stop;
+        else {
+          stop_type = GST_SEEK_TYPE_SET;
+          ts = gst_segment_position_from_running_time (&demux->segment,
+              GST_FORMAT_TIME, demux->priv->global_output_position);
+        }
       }
-    }
 
-    if (gst_adaptive_demux2_stream_seek (stream, rate >= 0, stream_seek_flags,
-            ts, &ts) != GST_FLOW_OK) {
-      GST_ADAPTIVE_SCHEDULER_UNLOCK (demux);
+      if (gst_adaptive_demux2_stream_seek (stream, rate >= 0, stream_seek_flags,
+              ts, &ts) != GST_FLOW_OK) {
+        GST_ADAPTIVE_SCHEDULER_UNLOCK (demux);
+        GST_ADAPTIVE_DEMUX_SEGMENT_UNLOCK (demux);
 
-      GST_API_UNLOCK (demux);
-      gst_event_unref (event);
-      return FALSE;
-    }
+        GST_API_UNLOCK (demux);
 
-    /* replace event with a new one without snapping to seek on all streams */
-    gst_event_unref (event);
-    if (rate >= 0) {
-      start = ts;
-    } else {
-      stop = ts;
+        gst_event_unref (event);
+
+        return FALSE;
+      }
+      /* replace event with a new one without snapping to seek on all streams */
+      gst_event_unref (event);
+      if (rate >= 0) {
+        start = ts;
+      } else {
+        stop = ts;
+      }
+      event =
+          gst_event_new_seek (rate, format, REMOVE_SNAP_FLAGS (flags),
+          start_type, start, stop_type, stop);
+      GST_DEBUG_OBJECT (demux, "Adapted snap seek to %" GST_PTR_FORMAT, event);
     }
-    event =
-        gst_event_new_seek (rate, format, REMOVE_SNAP_FLAGS (flags),
-        start_type, start, stop_type, stop);
-    GST_DEBUG_OBJECT (demux, "Adapted snap seek to %" GST_PTR_FORMAT, event);
   }
 
   ret = gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,