decodebin3: fix random hang when remove failing stream
authorHaihua Hu <jared.hu@nxp.com>
Wed, 10 May 2023 08:34:16 +0000 (16:34 +0800)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 17 May 2023 11:02:22 +0000 (11:02 +0000)
When reconfigure_output_stream entry missing decoder path,
requested_selection should been update with what is really
active/selected immdiately with SELECTION_LOCK hold. So
use an optional message return from reconfigure_output_stream
and post it after release SELECTION_LOCK. This can make sure
other thread call to check_slot_reconfiguration will got
a correct requested_selection.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4656>

subprojects/gst-plugins-base/gst/playback/gstdecodebin3.c

index 0da1f68..916916e 100644 (file)
@@ -497,7 +497,7 @@ static DecodebinInput *create_new_input (GstDecodebin3 * dbin, gboolean main);
 static gboolean set_input_group_id (DecodebinInput * input, guint32 * group_id);
 
 static gboolean reconfigure_output_stream (DecodebinOutputStream * output,
-    MultiQueueSlot * slot);
+    MultiQueueSlot * slot, GstMessage ** msg);
 static void free_output_stream (GstDecodebin3 * dbin,
     DecodebinOutputStream * output);
 static DecodebinOutputStream *create_output_stream (GstDecodebin3 * dbin,
@@ -2328,6 +2328,7 @@ static void
 check_slot_reconfiguration (GstDecodebin3 * dbin, MultiQueueSlot * slot)
 {
   DecodebinOutputStream *output;
+  GstMessage *msg = NULL;
 
   SELECTION_LOCK (dbin);
   output = get_output_for_slot (slot);
@@ -2336,7 +2337,7 @@ check_slot_reconfiguration (GstDecodebin3 * dbin, MultiQueueSlot * slot)
     return;
   }
 
-  if (!reconfigure_output_stream (output, slot)) {
+  if (!reconfigure_output_stream (output, slot, &msg)) {
     GST_DEBUG_OBJECT (dbin, "Removing failing stream from selection: %s ",
         gst_stream_get_stream_id (slot->active_stream));
     slot->dbin->requested_selection =
@@ -2344,12 +2345,14 @@ check_slot_reconfiguration (GstDecodebin3 * dbin, MultiQueueSlot * slot)
         gst_stream_get_stream_id (slot->active_stream));
     dbin->selection_updated = TRUE;
     SELECTION_UNLOCK (dbin);
+    if (msg)
+      gst_element_post_message ((GstElement *) slot->dbin, msg);
     reassign_slot (dbin, slot);
   } else {
-    GstMessage *msg = is_selection_done (dbin);
+    GstMessage *selection_msg = is_selection_done (dbin);
     SELECTION_UNLOCK (dbin);
-    if (msg)
-      gst_element_post_message ((GstElement *) slot->dbin, msg);
+    if (selection_msg)
+      gst_element_post_message ((GstElement *) slot->dbin, selection_msg);
   }
 }
 
@@ -2743,7 +2746,7 @@ keyframe_waiter_probe (GstPad * pad, GstPadProbeInfo * info,
  * associated GstStreams should be disabled */
 static gboolean
 reconfigure_output_stream (DecodebinOutputStream * output,
-    MultiQueueSlot * slot)
+    MultiQueueSlot * slot, GstMessage ** msg)
 {
   GstDecodebin3 *dbin = output->dbin;
   GstCaps *new_caps = (GstCaps *) gst_stream_get_caps (slot->active_stream);
@@ -2851,14 +2854,11 @@ reconfigure_output_stream (DecodebinOutputStream * output,
       if (output->decoder == NULL) {
         GstCaps *caps;
 
-        SELECTION_UNLOCK (dbin);
         /* FIXME : Should we be smarter if there's a missing decoder ?
          * Should we deactivate that stream ? */
         caps = gst_stream_get_caps (slot->active_stream);
-        gst_element_post_message (GST_ELEMENT_CAST (dbin),
-            gst_missing_decoder_message_new (GST_ELEMENT_CAST (dbin), caps));
+        *msg = gst_missing_decoder_message_new (GST_ELEMENT_CAST (dbin), caps);
         gst_caps_unref (caps);
-        SELECTION_LOCK (dbin);
         ret = FALSE;
         goto cleanup;
       }