From 93e432bccb09e480059039df62695adeb71e3787 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 25 Nov 2024 10:50:34 +0100 Subject: [PATCH] urisourcebin: Fix issue re-using outputs When checking whether a no-longer used output could be re-used for another slot, we only want to do that for streams which are not still used. Otherwise we end up potentially re-assigning a demuxer stream to a completely different one Furthermore, if we *are* re-using an output slot, indicate what the replacement GstStream will be so slot matching can work properly (which can happen in the case of demuxers which add/remove all pads even if only a single one changed) Part-of: --- .../gst/playback/gsturisourcebin.c | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c b/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c index 7e1b9910a0..b1978c4068 100644 --- a/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c +++ b/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c @@ -2892,6 +2892,7 @@ handle_parsebin_collection (ChildSrcPadInfo * info, { GList *unused_slots = NULL, *iter; GList *streams = NULL; + GList *unused_streams = NULL; guint i, nb_streams; nb_streams = gst_stream_collection_get_size (collection); @@ -2900,33 +2901,54 @@ handle_parsebin_collection (ChildSrcPadInfo * info, g_list_append (streams, gst_stream_collection_get_stream (collection, i)); + unused_streams = g_list_copy (streams); + /* Get list of output info slots not present in the collection */ for (iter = info->outputs; iter; iter = iter->next) { OutputSlotInfo *output = iter->data; - if (output->stream - && !gst_playback_utils_stream_in_list (streams, output->stream)) { + if (!output->stream) + continue; + + if (!gst_playback_utils_stream_in_list (streams, output->stream)) { GST_DEBUG_OBJECT (output->originating_pad, "No longer used in new collection"); unused_slots = g_list_append (unused_slots, output); + } else { + GList *iter2 = unused_streams; + /* Stream is re-used, remove it from unused streams we will try to + * re-assign further down */ + for (iter2 = unused_streams; iter2; iter2 = iter2->next) { + GstStream *stream = iter2->data; + if (!g_strcmp0 (output->stream->stream_id, stream->stream_id)) { + /* Replace the pending stream by the incoming stream */ + gst_object_replace ((GstObject **) & output->pending_stream, + (GstObject *) stream); + unused_streams = g_list_remove (unused_streams, stream); + break; + } + } } } - /* For each of those slots, check if there is a compatible stream from the - * collection that could be assigned to it */ + /* For each of those slots, check if there is a unused compatible stream from + * the collection that could be assigned to it */ for (iter = unused_slots; iter; iter = iter->next) { OutputSlotInfo *output = iter->data; - GstStream *replacement = find_compatible_stream (streams, output->stream); + GstStream *replacement = + find_compatible_stream (unused_streams, output->stream); if (replacement) { GST_DEBUG_OBJECT (output->originating_pad, "Assigning stream %s", gst_stream_get_stream_id (replacement)); - output->pending_stream = gst_object_ref (replacement); - streams = g_list_remove (streams, replacement); + gst_object_replace ((GstObject **) & output->pending_stream, + (GstObject *) replacement); + unused_streams = g_list_remove (unused_streams, replacement); } } g_list_free (unused_slots); g_list_free (streams); + g_list_free (unused_streams); /* Store the collection */ gst_object_replace ((GstObject **) & info->collection,