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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4922>
This commit is contained in:
Edward Hervey 2023-02-08 17:24:18 +01:00 committed by Edward Hervey
parent 12b689f6b5
commit f1e2202b23
3 changed files with 86 additions and 59 deletions

View 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);

View 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

View 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.
*/
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,