From f1e2202b237114fde202e7e03ccd9b8c159bcec9 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 8 Feb 2023 17:24:18 +0100 Subject: [PATCH] adaptivedemux2: Handle early key-unit seek 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: --- .../adaptivedemux2/gstadaptivedemux-private.h | 1 + .../adaptivedemux2/gstadaptivedemux-stream.c | 14 ++ .../ext/adaptivedemux2/gstadaptivedemux.c | 130 ++++++++++-------- 3 files changed, 86 insertions(+), 59 deletions(-) diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-private.h b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-private.h index a72cefe3af..ee50f773c3 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-private.h +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-private.h @@ -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); diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c index 8981ac1176..217d78e79f 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux-stream.c @@ -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 diff --git a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c index afba0ecca6..00c9c9cbcc 100644 --- a/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c +++ b/subprojects/gst-plugins-good/ext/adaptivedemux2/gstadaptivedemux.c @@ -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. - */ + 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. + */ - 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; - - /* 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); + /* 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 (default_stream == NULL + && gst_adaptive_demux2_stream_is_default_locked (cand)) + default_stream = cand; } - if (gst_adaptive_demux2_stream_seek (stream, rate >= 0, stream_seek_flags, - ts, &ts) != GST_FLOW_OK) { - GST_ADAPTIVE_SCHEDULER_UNLOCK (demux); + if (stream == NULL) + stream = default_stream; - GST_API_UNLOCK (demux); + 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); + GST_ADAPTIVE_DEMUX_SEGMENT_UNLOCK (demux); + + GST_API_UNLOCK (demux); + + gst_event_unref (event); + + return FALSE; + } + /* replace event with a new one without snapping to seek on all streams */ gst_event_unref (event); - return FALSE; + 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); } - - /* 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); } ret = gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,