decodebin3: Handle race switching on pending streams

find_slot_for_stream_id() will return a slot which has the request stream-id as
active_stream *or* pending_stream (i.e. the slot on which that stream is
currently being outputted or will be outputted).

When figuring out which slot to use (if any) we want to consider stream-id
which *will* appear on a given slot which isn't outputting anything yet the same
way as if we didn't find a slot yet.

Fixes races when doing intensive state changes

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6270>
This commit is contained in:
Edward Hervey 2024-03-06 09:48:43 +01:00 committed by GStreamer Marge Bot
parent e03e2308d7
commit 5f7062136d

View file

@ -3303,19 +3303,25 @@ handle_stream_switch (GstDecodebin3 * dbin, GList * select_streams,
for (tmp = select_streams; tmp; tmp = tmp->next) { for (tmp = select_streams; tmp; tmp = tmp->next) {
const gchar *sid = (const gchar *) tmp->data; const gchar *sid = (const gchar *) tmp->data;
MultiQueueSlot *slot; MultiQueueSlot *slot;
GST_DEBUG_OBJECT (dbin, "Checking stream '%s'", sid); GST_DEBUG_OBJECT (dbin, "Checking for requested stream '%s'", sid);
slot = find_slot_for_stream_id (dbin, sid); slot = find_slot_for_stream_id (dbin, sid);
/* Find the corresponding slot */
if (slot == NULL) { /* Find the multiqueue slot which is outputting, or will output, this stream
* id */
if (slot == NULL || slot->active_stream == NULL) {
/* There is no slot on which this stream is active */
if (stream_in_collection (dbin, (gchar *) sid)) { if (stream_in_collection (dbin, (gchar *) sid)) {
GST_DEBUG_OBJECT (dbin, "Adding to pending streams '%s'", sid);
pending_streams = g_list_append (pending_streams, (gchar *) sid); pending_streams = g_list_append (pending_streams, (gchar *) sid);
} else { } else {
GST_DEBUG_OBJECT (dbin, "We don't have a slot for stream '%s'", sid); GST_DEBUG_OBJECT (dbin, "We don't have a slot for stream '%s'", sid);
unknown = g_list_append (unknown, (gchar *) sid); unknown = g_list_append (unknown, (gchar *) sid);
} }
} else if (slot->output == NULL) { } else if (slot->output == NULL) {
GST_DEBUG_OBJECT (dbin, "We need to activate slot %p for stream '%s')", /* There is a slot on which this stream is active or pending */
slot, sid); GST_DEBUG_OBJECT (dbin,
"We need to activate slot %p %s:%s for stream '%s')", slot,
GST_DEBUG_PAD_NAME (slot->src_pad), sid);
to_activate = g_list_append (to_activate, slot); to_activate = g_list_append (to_activate, slot);
} else { } else {
GST_DEBUG_OBJECT (dbin, GST_DEBUG_OBJECT (dbin,