decodebin3: Handle changes in stream type

While decodebin3 could handle changes in inputs (ex: changing codecs), there was
still one limitation which was when changing between sources which had
non-intersecting stream types (ex: switching from a video-only source to a
audio-only source). While the decoder *could* change to the proper codec ... it
would carry on using a `DecodebinOutputStream` associated to that stream
type (and therefore with pads with the wrong name).

In order to handle this:

* We notify the `MultiQueueSlot` of the change in `GstStreamType` if it already
  had an associated inputstream (ex: the one associated with the static sink
  pad)

* We detect such changes on the output of multiqueue as soon as
  possible (i.e. when we get the GST_EVENT_STREAM_START for the new stream type)
  by discarding the associated output.

Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1669

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4703>
This commit is contained in:
Edward Hervey 2023-05-24 16:39:54 +02:00 committed by GStreamer Marge Bot
parent f51283b57b
commit d6f1c517f3

View file

@ -2376,11 +2376,31 @@ multiqueue_src_probe (GstPad * pad, GstPadProbeInfo * info,
if (slot->active_stream == NULL) { if (slot->active_stream == NULL) {
slot->active_stream = stream; slot->active_stream = stream;
} else if (slot->active_stream != stream) { } else if (slot->active_stream != stream) {
GST_FIXME_OBJECT (pad, "Handle stream changes (%s => %s) !", gboolean stream_type_changed =
gst_stream_get_stream_type (stream) !=
gst_stream_get_stream_type (slot->active_stream);
GST_DEBUG_OBJECT (pad, "Stream change (%s => %s) !",
gst_stream_get_stream_id (slot->active_stream), gst_stream_get_stream_id (slot->active_stream),
gst_stream_get_stream_id (stream)); gst_stream_get_stream_id (stream));
gst_object_unref (slot->active_stream); gst_object_unref (slot->active_stream);
slot->active_stream = stream; slot->active_stream = stream;
if (stream_type_changed) {
/* The stream type has changed, we get rid of the current output. A
* new one (targetting the new stream type) will be created once the
* caps are received. */
GST_DEBUG_OBJECT (pad,
"Stream type change, discarding current output stream");
if (slot->output) {
DecodebinOutputStream *output = slot->output;
SELECTION_LOCK (dbin);
dbin->output_streams =
g_list_remove (dbin->output_streams, output);
free_output_stream (dbin, output);
SELECTION_UNLOCK (dbin);
}
}
} else } else
gst_object_unref (stream); gst_object_unref (stream);
#if 0 /* Disabled because stream-start is pushed for every buffer on every unlinked pad */ #if 0 /* Disabled because stream-start is pushed for every buffer on every unlinked pad */
@ -2615,6 +2635,20 @@ get_slot_for_input (GstDecodebin3 * dbin, DecodebinInputStream * input)
/* Already used input, return that one */ /* Already used input, return that one */
if (slot->input == input) { if (slot->input == input) {
GST_DEBUG_OBJECT (dbin, "Returning already specified slot %d", slot->id); GST_DEBUG_OBJECT (dbin, "Returning already specified slot %d", slot->id);
if (input_type && slot->type != input_type) {
/* The input stream type has changed. It is the responsibility of the
* user of decodebin3 to ensure that the inputs are coherent.
*
* The only case where the stream type will change is when switching
* between sources which have non-intersecting stream types (ex:
* switching from audio-only file to video-only file)
*
* NOTE : We need to change the slot type here, since it is notified as
* soon as the *input* of the slot changes.
*/
GST_DEBUG_OBJECT (dbin, "Changing multiqueue slot stream type");
slot->type = input_type;
}
return slot; return slot;
} }
} }