rtsp-media: Handle multiple dynamic elements
authorEdward Hervey <edward@centricular.com>
Mon, 20 Nov 2017 08:32:07 +0000 (09:32 +0100)
committerEdward Hervey <bilboed@bilboed.com>
Mon, 20 Nov 2017 08:38:49 +0000 (09:38 +0100)
If we have more than one dynamic payloader in the pipeline, we need
to wait until the *last* one emits 'no-more-pads' before switching
to PREPARED.

Failure to do so would result in a race where some of the streams
wouldn't properly be prepared

https://bugzilla.gnome.org/show_bug.cgi?id=769521

gst/rtsp-server/rtsp-media.c
tests/check/gst/media.c

index 0f8a194..0a9898b 100644 (file)
@@ -142,6 +142,10 @@ struct _GstRTSPMediaPrivate
   guint latency;                /* protected by lock */
   GstClock *clock;              /* protected by lock */
   GstRTSPPublishClockMode publish_clock_mode;
+
+  /* Dynamic element handling */
+  guint nb_dynamic_elements;
+  guint no_more_pads_pending;
 };
 
 #define DEFAULT_SHARED          FALSE
@@ -1821,6 +1825,8 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media)
       gst_object_unref (pad);
       gst_object_unref (elem);
 
+      priv->nb_dynamic_elements++;
+
       have_elem = TRUE;
       more_elem_remaining = TRUE;
       mode |= GST_RTSP_TRANSPORT_MODE_RECORD;
@@ -2743,9 +2749,15 @@ static void
 no_more_pads_cb (GstElement * element, GstRTSPMedia * media)
 {
   GstRTSPMediaPrivate *priv = media->priv;
+  gboolean remaining_dynamic;
 
-  GST_INFO ("no more pads");
-  remove_fakesink (priv);
+  GST_INFO_OBJECT (element, "no more pads");
+  g_mutex_lock (&priv->lock);
+  priv->no_more_pads_pending--;
+  remaining_dynamic = priv->no_more_pads_pending;
+  g_mutex_unlock (&priv->lock);
+  if (remaining_dynamic == 0)
+    remove_fakesink (priv);
 }
 
 typedef struct _DynPaySignalHandlers DynPaySignalHandlers;
@@ -3047,6 +3059,7 @@ gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
   priv->is_live = FALSE;
   priv->seekable = -1;
   priv->buffering = FALSE;
+  priv->no_more_pads_pending = priv->nb_dynamic_elements;
 
   /* we're preparing now */
   gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
index cf09814..b734673 100644 (file)
@@ -486,21 +486,21 @@ GST_START_TEST (test_media_multidyn_prepare)
 
   pool = gst_rtsp_thread_pool_new ();
 
-  fail_unless (gst_rtsp_media_n_streams (media) == 0);
+  fail_unless_equals_int (gst_rtsp_media_n_streams (media), 0);
 
   thread = gst_rtsp_thread_pool_get_thread (pool,
       GST_RTSP_THREAD_TYPE_MEDIA, NULL);
   fail_unless (gst_rtsp_media_prepare (media, thread));
-  fail_unless (gst_rtsp_media_n_streams (media) == 2);
+  fail_unless_equals_int (gst_rtsp_media_n_streams (media), 2);
   fail_unless (gst_rtsp_media_unprepare (media));
-  fail_unless (gst_rtsp_media_n_streams (media) == 0);
+  fail_unless_equals_int (gst_rtsp_media_n_streams (media), 0);
 
   thread = gst_rtsp_thread_pool_get_thread (pool,
       GST_RTSP_THREAD_TYPE_MEDIA, NULL);
   fail_unless (gst_rtsp_media_prepare (media, thread));
-  fail_unless (gst_rtsp_media_n_streams (media) == 2);
+  fail_unless_equals_int (gst_rtsp_media_n_streams (media), 2);
   fail_unless (gst_rtsp_media_unprepare (media));
-  fail_unless (gst_rtsp_media_n_streams (media) == 0);
+  fail_unless_equals_int (gst_rtsp_media_n_streams (media), 0);
 
   gst_object_unref (srcpad0);
   gst_object_unref (srcpad1);