From 2b5ca38500880fddd74d717b63761379262dc5ae Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 20 Nov 2017 09:32:07 +0100 Subject: rtsp-media: Handle multiple dynamic elements 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 | 17 +++++++++++++++-- tests/check/gst/media.c | 10 +++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 996f453133..fb2211fac7 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -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 @@ -1740,6 +1744,8 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media) priv->dynamic = g_list_prepend (priv->dynamic, elem); g_mutex_unlock (&priv->lock); + priv->nb_dynamic_elements++; + have_elem = TRUE; more_elem_remaining = TRUE; mode |= GST_RTSP_TRANSPORT_MODE_PLAY; @@ -2648,9 +2654,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; @@ -2955,6 +2967,7 @@ gst_rtsp_media_prepare (GstRTSPMedia * media, GstRTSPThread * thread) priv->is_live = FALSE; priv->seekable = FALSE; 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); diff --git a/tests/check/gst/media.c b/tests/check/gst/media.c index b0ddb19967..37d8d464e9 100644 --- a/tests/check/gst/media.c +++ b/tests/check/gst/media.c @@ -419,21 +419,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); -- cgit v1.2.1