diff options
author | Edward Hervey <edward@centricular.com> | 2017-11-20 09:32:07 +0100 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2017-11-20 10:00:52 +0100 |
commit | 2b5ca38500880fddd74d717b63761379262dc5ae (patch) | |
tree | 534a15aefe31e63ba7d22e2d7c377548d542b031 | |
parent | 838d9c69077e3e9ad628f966af8b0fed13a3e1b2 (diff) |
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
-rw-r--r-- | gst/rtsp-server/rtsp-media.c | 17 | ||||
-rw-r--r-- | 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 996f453..fb2211f 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 b0ddb19..37d8d46 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); |