summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2014-06-25 18:23:10 +0200
committerSebastian Dröge <sebastian@centricular.com>2014-07-22 14:26:49 +0200
commit3159b374b9d4b73d20667667f8fd843fa319e9e9 (patch)
tree6a6c246f80f950d06b31f7a9418724ed81e0a393
parente58eeb408d1b8415860c93ade956a8bf62f7af1b (diff)
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
-rw-r--r--gst/rtsp-server/rtsp-stream.c90
1 files changed, 89 insertions, 1 deletions
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;