[gst-cvs] gst-plugins-bad: sdpdemux: rework RTCP sending and RTP receiving

Wim Taymans wtay at kemper.freedesktop.org
Thu May 21 13:22:21 PDT 2009


Module: gst-plugins-bad
Branch: master
Commit: e9eae335f1164c6d57b18d5038c6df2835bfd563
URL:    http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/?id=e9eae335f1164c6d57b18d5038c6df2835bfd563

Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Mon May 18 23:21:47 2009 +0200

sdpdemux: rework RTCP sending and RTP receiving

When we are dealing with multiast, create the udp src and sink elements pointing
to the multicast addresses. When we are doing unicast, receive data on the local
ports and don't send RTCP because we don't know where we have to send it.

Fixes #583188

---

 gst/sdp/gstsdpdemux.c |   76 ++++++++++++++++++++++++++++++++++++++++++++----
 gst/sdp/gstsdpdemux.h |    1 +
 2 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/gst/sdp/gstsdpdemux.c b/gst/sdp/gstsdpdemux.c
index be34a22..4deac87 100644
--- a/gst/sdp/gstsdpdemux.c
+++ b/gst/sdp/gstsdpdemux.c
@@ -51,6 +51,22 @@
 #include <unistd.h>
 #endif
 
+#ifdef G_OS_WIN32
+#ifdef _MSC_VER
+#include <Winsock2.h>
+#endif
+/* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later.
+ *  * minwg32 headers check WINVER before allowing the use of these */
+#ifndef WINVER
+#define WINVER 0x0501
+#endif
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 #include <locale.h>
@@ -348,6 +364,39 @@ gst_sdp_demux_stream_free (GstSDPDemux * demux, GstSDPStream * stream)
   g_free (stream);
 }
 
+static gboolean
+is_multicast_address (const gchar * host_name)
+{
+  struct addrinfo hints;
+  struct addrinfo *ai;
+  struct addrinfo *res;
+  gboolean ret = FALSE;
+  int err;
+
+  memset (&hints, 0, sizeof (hints));
+  hints.ai_socktype = SOCK_DGRAM;
+
+  g_return_val_if_fail (host_name, FALSE);
+
+  if ((err = getaddrinfo (host_name, NULL, &hints, &res)) < 0)
+    return FALSE;
+
+  for (ai = res; !ret && ai; ai = ai->ai_next) {
+    if (ai->ai_family == AF_INET)
+      ret =
+          IN_MULTICAST (ntohl (((struct sockaddr_in *) ai->ai_addr)->
+              sin_addr.s_addr));
+    else
+      ret =
+          IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) ai->
+              ai_addr)->sin6_addr);
+  }
+
+  freeaddrinfo (res);
+
+  return ret;
+}
+
 static GstSDPStream *
 gst_sdp_demux_create_stream (GstSDPDemux * demux, GstSDPMessage * sdp, gint idx)
 {
@@ -395,6 +444,7 @@ gst_sdp_demux_create_stream (GstSDPDemux * demux, GstSDPMessage * sdp, gint idx)
 
   stream->destination = conn->address;
   stream->ttl = conn->ttl;
+  stream->multicast = is_multicast_address (stream->destination);
 
   stream->rtp_port = gst_sdp_media_get_port (media);
   if ((rtcp = gst_sdp_media_get_attribute_val (media, "rtcp"))) {
@@ -885,18 +935,24 @@ start_session_failure:
 static gboolean
 gst_sdp_demux_stream_configure_udp (GstSDPDemux * demux, GstSDPStream * stream)
 {
-  gchar *uri, *name;
+  gchar *uri, *name, *destination;
   GstPad *pad;
 
   GST_DEBUG_OBJECT (demux, "creating UDP sources for multicast");
 
+  /* if the destination is not a multicast address, we just want to listen on
+   * our local ports */
+  if (!stream->multicast)
+    destination = "0.0.0.0";
+  else
+    destination = stream->destination;
+
   /* creating UDP source */
   if (stream->rtp_port != -1) {
-    GST_DEBUG_OBJECT (demux, "receiving RTP from %s:%d", stream->destination,
+    GST_DEBUG_OBJECT (demux, "receiving RTP from %s:%d", destination,
         stream->rtp_port);
 
-    uri = g_strdup_printf ("udp://%s:%d", stream->destination,
-        stream->rtp_port);
+    uri = g_strdup_printf ("udp://%s:%d", destination, stream->rtp_port);
     stream->udpsrc[0] = gst_element_make_from_uri (GST_URI_SRC, uri, NULL);
     g_free (uri);
     if (stream->udpsrc[0] == NULL)
@@ -933,10 +989,9 @@ gst_sdp_demux_stream_configure_udp (GstSDPDemux * demux, GstSDPStream * stream)
 
   /* creating another UDP source */
   if (stream->rtcp_port != -1) {
-    GST_DEBUG_OBJECT (demux, "receiving RTCP from %s:%d", stream->destination,
+    GST_DEBUG_OBJECT (demux, "receiving RTCP from %s:%d", destination,
         stream->rtcp_port);
-    uri =
-        g_strdup_printf ("udp://%s:%d", stream->destination, stream->rtcp_port);
+    uri = g_strdup_printf ("udp://%s:%d", destination, stream->rtcp_port);
     stream->udpsrc[1] = gst_element_make_from_uri (GST_URI_SRC, uri, NULL);
     g_free (uri);
     if (stream->udpsrc[1] == NULL)
@@ -988,6 +1043,13 @@ gst_sdp_demux_stream_configure_udp_sink (GstSDPDemux * demux,
   if (stream->udpsink == NULL)
     goto no_sink_element;
 
+  /* we clear all destinations because we don't really know where to send the
+   * RTCP to and we want to avoid sending it to our own ports.
+   * FIXME when we get an RTCP packet from the sender, we could look at its
+   * source port and address and try to send RTCP there. */
+  if (!stream->multicast)
+    g_signal_emit_by_name (stream->udpsink, "clear");
+
   /* no sync needed */
   g_object_set (G_OBJECT (stream->udpsink), "sync", FALSE, NULL);
   /* no async state changes needed */
diff --git a/gst/sdp/gstsdpdemux.h b/gst/sdp/gstsdpdemux.h
index 0ae6074..32a5329 100644
--- a/gst/sdp/gstsdpdemux.h
+++ b/gst/sdp/gstsdpdemux.h
@@ -68,6 +68,7 @@ struct _GstSDPStream {
 
   gchar        *destination;
   guint         ttl;
+  gboolean      multicast;
 
   /* our udp sink back to the server */
   GstElement   *udpsink;





More information about the Gstreamer-commits mailing list