From 3159b374b9d4b73d20667667f8fd843fa319e9e9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 25 Jun 2014 18:23:10 +0200 Subject: [PATCH] rtsp-stream: Listen on the multicast group for RTP/RTCP packets When a UDP multicast transport is used it is expected that the server listens for RTP and RTCP packets on the multicast group with the corresponding port. Without this we will never get RTCP packets from clients in multicast mode. https://bugzilla.gnome.org/show_bug.cgi?id=732238 --- gst/rtsp-server/rtsp-stream.c | 90 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c index 942b837..9ed194f 100644 --- a/gst/rtsp-server/rtsp-stream.c +++ b/gst/rtsp-server/rtsp-stream.c @@ -58,6 +58,15 @@ #define GST_RTSP_STREAM_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_STREAM, GstRTSPStreamPrivate)) +typedef struct +{ + GstRTSPStreamTransport *transport; + + /* RTP and RTCP source */ + GstElement *udpsrc[2]; + GstPad *selpad[2]; +} GstRTSPMulticastTransportSource; + struct _GstRTSPStreamPrivate { GMutex lock; @@ -128,6 +137,9 @@ struct _GstRTSPStreamPrivate GList *tr_cache; guint tr_cache_cookie; + /* UDP sources for UDP multicast transports */ + GList *transport_sources; + gint dscp_qos; /* stream blocking */ @@ -1137,6 +1149,7 @@ again: udpsrc_out[1] = udpsrc1; udpsink_out[0] = udpsink0; udpsink_out[1] = udpsink1; + server_port_out->min = rtpport; server_port_out->max = rtcpport; @@ -2236,9 +2249,84 @@ update_transport (GstRTSPStream * stream, GstRTSPStreamTransport * trans, tr = gst_rtsp_stream_transport_get_transport (trans); switch (tr->lower_transport) { - case GST_RTSP_LOWER_TRANS_UDP: case GST_RTSP_LOWER_TRANS_UDP_MCAST: { + GstRTSPMulticastTransportSource *source; + GstBin *bin; + + bin = GST_BIN (gst_object_get_parent (GST_OBJECT (priv->funnel[0]))); + + if (add) { + gchar *host; + gint i; + GstPad *selpad, *pad; + + source = g_slice_new0 (GstRTSPMulticastTransportSource); + source->transport = trans; + + for (i = 0; i < 2; i++) { + host = + g_strdup_printf ("udp://%s:%d", tr->destination, + (i == 0) ? tr->port.min : tr->port.max); + source->udpsrc[i] = + gst_element_make_from_uri (GST_URI_SRC, host, NULL, NULL); + g_free (host); + + /* we set and keep these to playing so that they don't cause NO_PREROLL return + * values */ + gst_element_set_state (source->udpsrc[i], GST_STATE_PLAYING); + gst_element_set_locked_state (source->udpsrc[i], TRUE); + /* add udpsrc */ + gst_bin_add (bin, source->udpsrc[i]); + + /* and link to the funnel v4 */ + source->selpad[i] = selpad = + gst_element_get_request_pad (priv->funnel[i], "sink_%u"); + pad = gst_element_get_static_pad (source->udpsrc[i], "src"); + gst_pad_link (pad, selpad); + gst_object_unref (pad); + gst_object_unref (selpad); + } + gst_object_unref (bin); + + priv->transport_sources = + g_list_prepend (priv->transport_sources, source); + } else { + GList *l; + + for (l = priv->transport_sources; l; l = l->next) { + source = l->data; + + if (source->transport == trans) { + priv->transport_sources = + g_list_delete_link (priv->transport_sources, l); + break; + } + } + + if (l != NULL) { + gint i; + + for (i = 0; i < 2; i++) { + /* Will automatically unlink everything */ + gst_bin_remove (bin, + GST_ELEMENT (gst_object_ref (source->udpsrc[i]))); + + gst_element_set_state (source->udpsrc[i], GST_STATE_NULL); + gst_object_unref (source->udpsrc[i]); + + gst_element_release_request_pad (priv->funnel[i], + source->selpad[i]); + } + + g_slice_free (GstRTSPMulticastTransportSource, source); + } + } + + /* fall through for the generic case */ + } + case GST_RTSP_LOWER_TRANS_UDP: + { gchar *dest; gint min, max; guint ttl = 0; -- 2.7.4