From 446315b36c5c4c813abc9f22f6624ca1a58e13e2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 22 Jul 2019 19:32:43 +0300 Subject: [PATCH] rtsp-media: Try to get dynamic payloaders by name from their bin first First try "pay", then "pay_%s" (where %s == pad name). And only then fall back to the code that simply takes the first payloader that is found. The current code usually works (but is racy) because it will always take the payloader that was last added (due to g_list_prepend() when adding elements) in pad-added and that's usually the correct one. But if a new payloader is added between pad-added and us trying to get it, we would get the wrong payloader. --- gst/rtsp-server/rtsp-media-factory-uri.c | 6 ++-- gst/rtsp-server/rtsp-media.c | 59 ++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/gst/rtsp-server/rtsp-media-factory-uri.c b/gst/rtsp-server/rtsp-media-factory-uri.c index 93ed9d7..67cdc3e 100644 --- a/gst/rtsp-server/rtsp-media-factory-uri.c +++ b/gst/rtsp-server/rtsp-media-factory-uri.c @@ -465,7 +465,7 @@ pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element) GstCaps *caps; GstPad *sinkpad, *srcpad, *ghostpad; GstElement *convert; - gchar *padname; + gchar *padname, *payloader_name; GST_DEBUG ("added pad %s:%s", GST_DEBUG_PAD_NAME (pad)); @@ -521,7 +521,9 @@ pad_added_cb (GstElement * uribin, GstPad * pad, GstElement * element) GST_DEBUG ("found payloader factory %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); - payloader = gst_element_factory_create (factory, NULL); + payloader_name = g_strdup_printf ("pay_%s", padname); + payloader = gst_element_factory_create (factory, payloader_name); + g_free (payloader_name); if (payloader == NULL) goto no_payloader; diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index bd3fcaa..a412481 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -235,7 +235,7 @@ static gboolean default_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp); static gboolean wait_preroll (GstRTSPMedia * media); -static GstElement *find_payload_element (GstElement * payloader); +static GstElement *find_payload_element (GstElement * payloader, GstPad * pad); static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 }; @@ -2046,7 +2046,7 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media) pad = gst_element_get_static_pad (elem, "src"); /* find the real payload element in case elem is a GstBin */ - pay = find_payload_element (elem); + pay = find_payload_element (elem, pad); /* create the stream */ if (pay == NULL) { @@ -2213,7 +2213,8 @@ gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader, g_mutex_lock (&priv->lock); idx = priv->streams->len; - GST_DEBUG ("media %p: creating stream with index %d", media, idx); + GST_DEBUG ("media %p: creating stream with index %d and payloader %" + GST_PTR_FORMAT, media, idx, payloader); if (GST_PAD_IS_SRC (pad)) name = g_strdup_printf ("src_%u", idx); @@ -3148,27 +3149,57 @@ watch_destroyed (GstRTSPMedia * media) g_object_unref (media); } +static gboolean +is_payloader (GstElement * element) +{ + GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element); + const gchar *klass; + + klass = gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS); + if (klass == NULL) + return FALSE; + + if (strstr (klass, "Payloader") && strstr (klass, "RTP")) { + return TRUE; + } + + return FALSE; +} + static GstElement * -find_payload_element (GstElement * payloader) +find_payload_element (GstElement * payloader, GstPad * pad) { GstElement *pay = NULL; if (GST_IS_BIN (payloader)) { GstIterator *iter; GValue item = { 0 }; + gchar *pad_name, *payloader_name; + GstElement *element; + + if ((element = gst_bin_get_by_name (GST_BIN (payloader), "pay"))) { + if (is_payloader (element)) + return element; + gst_object_unref (element); + } + + pad_name = gst_object_get_name (GST_OBJECT (pad)); + payloader_name = g_strdup_printf ("pay_%s", pad_name); + g_free (pad_name); + if ((element = gst_bin_get_by_name (GST_BIN (payloader), payloader_name))) { + g_free (payloader_name); + if (is_payloader (element)) + return element; + gst_object_unref (element); + } else { + g_free (payloader_name); + } iter = gst_bin_iterate_recurse (GST_BIN (payloader)); while (gst_iterator_next (iter, &item) == GST_ITERATOR_OK) { - GstElement *element = (GstElement *) g_value_get_object (&item); - GstElementClass *eclass = GST_ELEMENT_GET_CLASS (element); - const gchar *klass; - - klass = - gst_element_class_get_metadata (eclass, GST_ELEMENT_METADATA_KLASS); - if (klass == NULL) - continue; + element = (GstElement *) g_value_get_object (&item); - if (strstr (klass, "Payloader") && strstr (klass, "RTP")) { + if (is_payloader (element)) { pay = gst_object_ref (element); g_value_unset (&item); break; @@ -3192,7 +3223,7 @@ pad_added_cb (GstElement * element, GstPad * pad, GstRTSPMedia * media) GstElement *pay; /* find the real payload element */ - pay = find_payload_element (element); + pay = find_payload_element (element, pad); stream = gst_rtsp_media_create_stream (media, pay, pad); gst_object_unref (pay); -- 2.7.4