rtsp-stream: postpone UDP socket allocation until SETUP
authorPatricia Muscalu <patricia@axis.com>
Tue, 23 Feb 2016 13:59:32 +0000 (14:59 +0100)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 23 Feb 2016 15:05:15 +0000 (17:05 +0200)
Postpone the allocation of the UDP sockets until we know
what transport has been chosen by the client.
Both unicast and multicast UDP sources are created in one
function.

https://bugzilla.gnome.org/show_bug.cgi?id=757488

gst/rtsp-server/rtsp-client.c
gst/rtsp-server/rtsp-stream.c
gst/rtsp-server/rtsp-stream.h

index c7620a8..b27f52b 100644 (file)
@@ -1403,26 +1403,26 @@ default_configure_client_transport (GstRTSPClient * client,
   /* we have a valid transport now, set the destination of the client. */
   if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
     gboolean use_client_settings;
+    GSocketFamily family;
 
     use_client_settings =
         gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS);
 
     if (ct->destination && use_client_settings) {
-      GstRTSPAddress *addr;
+      family = priv->is_ipv6 ? G_SOCKET_FAMILY_IPV6 : G_SOCKET_FAMILY_IPV4;
 
-      addr = gst_rtsp_stream_reserve_address (ctx->stream, ct->destination,
-          ct->port.min, ct->port.max - ct->port.min + 1, ct->ttl);
+      if (!gst_rtsp_stream_allocate_udp_sockets (ctx->stream, family, ct, TRUE))
+        goto no_udp_protocol;
 
-      if (addr == NULL)
-        goto no_address;
-
-      gst_rtsp_address_free (addr);
     } else {
       GstRTSPAddress *addr;
-      GSocketFamily family;
 
       family = priv->is_ipv6 ? G_SOCKET_FAMILY_IPV6 : G_SOCKET_FAMILY_IPV4;
 
+      if (!gst_rtsp_stream_allocate_udp_sockets (ctx->stream, family, ct, FALSE))
+        goto no_udp_protocol;
+
+      gst_rtsp_stream_get_server_port (ctx->stream, &ct->port, family);
       addr = gst_rtsp_stream_get_multicast_address (ctx->stream, family);
       if (addr == NULL)
         goto no_address;
@@ -1475,6 +1475,11 @@ default_configure_client_transport (GstRTSPClient * client,
         gst_rtsp_session_media_alloc_channels (ctx->sessmedia,
             &ct->interleaved);
       }
+    } else if (ct->lower_transport & GST_RTSP_LOWER_TRANS_UDP) {
+      GSocketFamily family;
+      family = priv->is_ipv6 ? G_SOCKET_FAMILY_IPV6 : G_SOCKET_FAMILY_IPV4;
+      if (!gst_rtsp_stream_allocate_udp_sockets (ctx->stream, family, ct, FALSE))
+        goto no_udp_protocol;
     }
   }
   return TRUE;
@@ -1485,6 +1490,11 @@ no_address:
     GST_ERROR_OBJECT (client, "failed to acquire address for stream");
     return FALSE;
   }
+no_udp_protocol:
+  {
+    GST_ERROR_OBJECT (client, "failed to allocate udp ports");
+    return FALSE;
+  }
 }
 
 static GstRTSPTransport *
index 86e7ef2..cf2c88f 100644 (file)
 #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;
@@ -106,10 +97,14 @@ struct _GstRTSPStreamPrivate
   /* sinks used for sending and receiving RTP and RTCP over ipv4, they share
    * sockets */
   GstElement *udpsrc_v4[2];
+  /* UDP sources for UDP multicast transports */
+  GstElement *udpsrc_mcast_v4[2];
 
   /* sinks used for sending and receiving RTP and RTCP over ipv6, they share
    * sockets */
   GstElement *udpsrc_v6[2];
+  /* UDP sources for UDP multicast transports */
+  GstElement *udpsrc_mcast_v6[2];
 
   GstElement *udpqueue[2];
   GstElement *udpsink[2];
@@ -142,6 +137,8 @@ struct _GstRTSPStreamPrivate
   GstRTSPAddressPool *pool;
   GstRTSPAddress *addr_v4;
   GstRTSPAddress *addr_v6;
+  gboolean have_ipv4_mcast;
+  gboolean have_ipv6_mcast;
 
   /* the caps of the stream */
   gulong caps_sig;
@@ -157,9 +154,6 @@ struct _GstRTSPStreamPrivate
   guint tr_cache_cookie_rtcp;
 
 
-  /* UDP sources for UDP multicast transports */
-  GList *transport_sources;
-
   gint dscp_qos;
 
   /* stream blocking */
@@ -1106,7 +1100,8 @@ no_udp_protocol:
 
 /* must be called with lock */
 static void
-play_udpsources_one_family (GstRTSPStream * stream, GSocketFamily family)
+play_udpsources_one_family (GstRTSPStream * stream, GstElement * udpsrc_out[2],
+    GSocketFamily family)
 {
   GstRTSPStreamPrivate *priv;
   GstPad *pad, *selpad;
@@ -1118,38 +1113,21 @@ play_udpsources_one_family (GstRTSPStream * stream, GSocketFamily family)
 
   for (i = 0; i < 2; i++) {
     if (priv->sinkpad || i == 1) {
-      if (family == G_SOCKET_FAMILY_IPV4 && priv->udpsrc_v4[i]) {
-        if (priv->srcpad) {
-          /* we set and keep these to playing so that they don't cause NO_PREROLL return
-           * values. This is only relevant for PLAY pipelines */
-          gst_element_set_state (priv->udpsrc_v4[i], GST_STATE_PLAYING);
-          gst_element_set_locked_state (priv->udpsrc_v4[i], TRUE);
-        }
-        /* add udpsrc */
-        gst_bin_add (bin, priv->udpsrc_v4[i]);
-
-        /* and link to the funnel v4 */
-        selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
-        pad = gst_element_get_static_pad (priv->udpsrc_v4[i], "src");
-        gst_pad_link (pad, selpad);
-        gst_object_unref (pad);
-        gst_object_unref (selpad);
+      if (priv->srcpad) {
+        /* we set and keep these to playing so that they don't cause NO_PREROLL return
+         * values. This is only relevant for PLAY pipelines */
+        gst_element_set_state (udpsrc_out[i], GST_STATE_PLAYING);
+        gst_element_set_locked_state (udpsrc_out[i], TRUE);
       }
+      /* add udpsrc */
+      gst_bin_add (bin, udpsrc_out[i]);
 
-      if (family == G_SOCKET_FAMILY_IPV6 && priv->udpsrc_v6[i]) {
-        if (priv->srcpad) {
-          gst_element_set_state (priv->udpsrc_v6[i], GST_STATE_PLAYING);
-          gst_element_set_locked_state (priv->udpsrc_v6[i], TRUE);
-        }
-        gst_bin_add (bin, priv->udpsrc_v6[i]);
-
-        /* and link to the funnel v6 */
-        selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
-        pad = gst_element_get_static_pad (priv->udpsrc_v6[i], "src");
-        gst_pad_link (pad, selpad);
-        gst_object_unref (pad);
-        gst_object_unref (selpad);
-      }
+      /* and link to the funnel */
+      selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
+      pad = gst_element_get_static_pad (udpsrc_out[i], "src");
+      gst_pad_link (pad, selpad);
+      gst_object_unref (pad);
+      gst_object_unref (selpad);
     }
   }
 
@@ -1159,18 +1137,27 @@ play_udpsources_one_family (GstRTSPStream * stream, GSocketFamily family)
 /* must be called with lock */
 static gboolean
 create_and_configure_udpsources_one_family (GstElement * udpsrc_out[2],
-    GSocket * rtp_socket, GSocket * rtcp_socket, GSocketFamily family)
+    GSocket * rtp_socket, GSocket * rtcp_socket, GSocketFamily family,
+    const gchar * address, gint rtpport, gint rtcpport,
+    GstRTSPLowerTrans transport)
 {
   GstStateChangeReturn ret;
 
-  /* we keep these elements, we will further configure them when the
-   * client told us to really use the UDP ports. */
   udpsrc_out[0] = gst_element_factory_make ("udpsrc", NULL);
   udpsrc_out[1] = gst_element_factory_make ("udpsrc", NULL);
 
   if (udpsrc_out[0] == NULL || udpsrc_out[1] == NULL)
     goto error;
 
+  if (transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
+    g_object_set (G_OBJECT (udpsrc_out[0]), "address", address, NULL);
+    g_object_set (G_OBJECT (udpsrc_out[1]), "address", address, NULL);
+    g_object_set (G_OBJECT (udpsrc_out[0]), "port", rtpport, NULL);
+    g_object_set (G_OBJECT (udpsrc_out[1]), "port", rtcpport, NULL);
+    g_object_set (G_OBJECT (udpsrc_out[0]), "loop", FALSE, NULL);
+    g_object_set (G_OBJECT (udpsrc_out[1]), "loop", FALSE, NULL);
+  }
+
   g_object_set (G_OBJECT (udpsrc_out[0]), "socket", rtp_socket, NULL);
   g_object_set (G_OBJECT (udpsrc_out[1]), "socket", rtcp_socket, NULL);
 
@@ -1198,7 +1185,8 @@ error:
 static gboolean
 alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
     GstElement * udpsrc_out[2], GstRTSPRange * server_port_out,
-    GstRTSPAddress ** server_addr_out)
+    GstRTSPTransport *ct, GstRTSPAddress ** server_addr_out,
+    gboolean use_client_settings)
 {
   GstRTSPStreamPrivate *priv = stream->priv;
   GSocket *rtp_socket = NULL;
@@ -1209,12 +1197,15 @@ alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
   GList *rejected_addresses = NULL;
   GstRTSPAddress *addr = NULL;
   GInetAddress *inetaddr = NULL;
+  gchar *addr_str;
   GSocketAddress *rtp_sockaddr = NULL;
   GSocketAddress *rtcp_sockaddr = NULL;
   GstRTSPAddressPool * pool;
+  GstRTSPLowerTrans transport;
 
   pool = priv->pool;
   count = 0;
+  transport = ct->lower_transport;
 
   /* Start with random port */
   tmp_rtp = 0;
@@ -1238,19 +1229,30 @@ again:
       goto no_udp_protocol;
   }
 
-  if (pool && gst_rtsp_address_pool_has_unicast_addresses (pool)) {
+  if (pool) {
     GstRTSPAddressFlags flags;
 
+    if (transport == GST_RTSP_LOWER_TRANS_UDP &&
+        gst_rtsp_address_pool_has_unicast_addresses (pool))
+      flags = GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_UNICAST;
+    else if (transport == GST_RTSP_LOWER_TRANS_UDP_MCAST)
+      flags = GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_MULTICAST;
+    else
+      goto no_ports;
+
     if (addr)
       rejected_addresses = g_list_prepend (rejected_addresses, addr);
 
-    flags = GST_RTSP_ADDRESS_FLAG_EVEN_PORT | GST_RTSP_ADDRESS_FLAG_UNICAST;
     if (family == G_SOCKET_FAMILY_IPV6)
       flags |= GST_RTSP_ADDRESS_FLAG_IPV6;
     else
       flags |= GST_RTSP_ADDRESS_FLAG_IPV4;
 
-    addr = gst_rtsp_address_pool_acquire_address (pool, flags, 2);
+    if (ct->destination && transport == GST_RTSP_LOWER_TRANS_UDP_MCAST && use_client_settings)
+      gst_rtsp_address_pool_reserve_address (pool, ct->destination,
+          ct->port.min, 2, ct->ttl, &addr);
+    else
+      addr = gst_rtsp_address_pool_acquire_address (pool, flags, 2);
 
     if (addr == NULL)
       goto no_ports;
@@ -1306,12 +1308,23 @@ again:
   }
   g_object_unref (rtcp_sockaddr);
 
+  if (addr == NULL)
+    addr_str = g_inet_address_to_string (inetaddr);
+  else
+    addr_str = addr->address;
   g_clear_object (&inetaddr);
 
   if (!create_and_configure_udpsources_one_family (udpsrc_out, rtp_socket,
-        rtcp_socket, family))
+        rtcp_socket, family, addr_str, tmp_rtp, tmp_rtcp, transport)) {
+    if (addr == NULL)
+      g_free (addr_str);
     goto no_udp_protocol;
-  play_udpsources_one_family (stream, family);
+  }
+
+  if (addr == NULL)
+    g_free (addr_str);
+
+  play_udpsources_one_family (stream, udpsrc_out, family);
 
   g_object_get (G_OBJECT (udpsrc_out[0]), "port", &rtpport, NULL);
   g_object_get (G_OBJECT (udpsrc_out[1]), "port", &rtcpport, NULL);
@@ -1320,7 +1333,6 @@ again:
   if (rtpport != tmp_rtp || rtcpport != tmp_rtcp)
     goto port_error;
 
-
   /* set RTP and RTCP sockets */
   set_sockets_for_udpsinks (stream, rtp_socket, rtcp_socket, family);
 
@@ -1368,21 +1380,65 @@ cleanup:
   }
 }
 
-/* must be called with lock */
-static gboolean
-alloc_ports (GstRTSPStream * stream)
+/**
+ * gst_rtsp_stream_allocate_udp_sockets:
+ * @stream: a #GstRTSPStream
+ * @family: protocol family
+ * @transport_method: transport method
+ *
+ * Allocates RTP and RTCP ports.
+ *
+ * Returns: %TRUE if the RTP and RTCP sockets have been succeccully allocated.
+ */
+gboolean
+gst_rtsp_stream_allocate_udp_sockets (GstRTSPStream * stream,
+    GSocketFamily family, GstRTSPTransport *ct, gboolean use_client_settings)
 {
-  GstRTSPStreamPrivate *priv = stream->priv;
+  GstRTSPStreamPrivate *priv;
+  gboolean result = FALSE;
+  GstRTSPLowerTrans transport = ct->lower_transport;
 
-  priv->have_ipv4 =
-      alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV4, priv->udpsrc_v4,
-          &priv->server_port_v4, &priv->server_addr_v4);
+  g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
+  priv = stream->priv;
+  g_return_val_if_fail (priv->is_joined, FALSE);
 
-  priv->have_ipv6 =
-      alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV6, priv->udpsrc_v6,
-          &priv->server_port_v6, &priv->server_addr_v6);
+  g_mutex_lock (&priv->lock);
 
-  return priv->have_ipv4 || priv->have_ipv6;
+  if (family == G_SOCKET_FAMILY_IPV4) {
+    if (transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
+      if (priv->have_ipv4_mcast)
+        goto done;
+      priv->have_ipv4_mcast =
+        alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV4, priv->udpsrc_mcast_v4,
+            &priv->server_port_v4, ct, &priv->addr_v4, use_client_settings);
+    } else {
+      priv->have_ipv4 =
+        alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV4, priv->udpsrc_v4,
+            &priv->server_port_v4, ct, &priv->server_addr_v4, use_client_settings);
+    }
+  } else {
+    if (transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
+      if (priv->have_ipv6_mcast)
+        goto done;
+      priv->have_ipv6_mcast =
+        alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV6, priv->udpsrc_mcast_v6,
+            &priv->server_port_v6, ct, &priv->addr_v6, use_client_settings);
+    } else {
+      if (priv->have_ipv6)
+        goto done;
+      priv->have_ipv6 =
+        alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV6, priv->udpsrc_v6,
+            &priv->server_port_v6, ct, &priv->server_addr_v6, use_client_settings);
+    }
+  }
+
+done:
+  result = priv->have_ipv4 || priv->have_ipv4_mcast || priv->have_ipv6 ||
+    priv->have_ipv6_mcast;
+
+  g_mutex_unlock (&priv->lock);
+
+  return result;
 }
 
 /**
@@ -2474,7 +2530,6 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
   guint idx;
   gchar *name;
   GstPadLinkReturn ret;
-  gboolean is_udp;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
   g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
@@ -2571,12 +2626,6 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
 
   create_receiver_part (stream, bin, state);
 
-  is_udp = ((priv->protocols & GST_RTSP_LOWER_TRANS_UDP) ||
-      (priv->protocols & GST_RTSP_LOWER_TRANS_UDP_MCAST));
-
-  if (is_udp && !alloc_ports (stream))
-    goto no_udp_protocol;
-
   if (priv->srcpad) {
     /* be notified of caps changes */
     priv->caps_sig = g_signal_connect (priv->send_src[0], "notify::caps",
@@ -2629,6 +2678,16 @@ no_udp_protocol:
       gst_object_unref (priv->udpsrc_v4[1]);
       priv->udpsrc_v4[1] = NULL;
     }
+    if (priv->udpsrc_mcast_v4[0]) {
+      gst_element_set_state (priv->udpsrc_mcast_v4[0], GST_STATE_NULL);
+      gst_object_unref (priv->udpsrc_mcast_v4[0]);
+      priv->udpsrc_mcast_v4[0] = NULL;
+    }
+    if (priv->udpsrc_mcast_v4[1]) {
+      gst_element_set_state (priv->udpsrc_mcast_v4[1], GST_STATE_NULL);
+      gst_object_unref (priv->udpsrc_mcast_v4[1]);
+      priv->udpsrc_mcast_v4[1] = NULL;
+    }
     if (priv->udpsrc_v6[0]) {
       gst_element_set_state (priv->udpsrc_v6[0], GST_STATE_NULL);
       gst_object_unref (priv->udpsrc_v6[0]);
@@ -2639,6 +2698,16 @@ no_udp_protocol:
       gst_object_unref (priv->udpsrc_v6[1]);
       priv->udpsrc_v6[1] = NULL;
     }
+    if (priv->udpsrc_mcast_v6[0]) {
+      gst_element_set_state (priv->udpsrc_mcast_v6[0], GST_STATE_NULL);
+      gst_object_unref (priv->udpsrc_mcast_v6[0]);
+      priv->udpsrc_mcast_v6[0] = NULL;
+    }
+    if (priv->udpsrc_mcast_v6[1]) {
+      gst_element_set_state (priv->udpsrc_mcast_v6[1], GST_STATE_NULL);
+      gst_object_unref (priv->udpsrc_mcast_v6[1]);
+      priv->udpsrc_mcast_v6[1] = NULL;
+    }
     g_mutex_unlock (&priv->lock);
     return FALSE;
   }
@@ -2660,7 +2729,6 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
 {
   GstRTSPStreamPrivate *priv;
   gint i;
-  GList *l;
   gboolean is_tcp, is_udp;
 
   g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
@@ -2732,6 +2800,20 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
       }
     }
 
+    if (priv->udpsrc_mcast_v4[i]) {
+      if (priv->sinkpad || i == 1) {
+        /* and set udpsrc to NULL now before removing */
+        gst_element_set_locked_state (priv->udpsrc_mcast_v4[i], FALSE);
+        gst_element_set_state (priv->udpsrc_mcast_v4[i], GST_STATE_NULL);
+        /* removing them should also nicely release the request
+         * pads when they finalize */
+        gst_bin_remove (bin, priv->udpsrc_mcast_v4[i]);
+      } else {
+        gst_element_set_state (priv->udpsrc_mcast_v4[i], GST_STATE_NULL);
+        gst_object_unref (priv->udpsrc_mcast_v4[i]);
+      }
+    }
+
     if (priv->udpsrc_v6[i]) {
       if (priv->sinkpad || i == 1) {
         gst_element_set_locked_state (priv->udpsrc_v6[i], FALSE);
@@ -2742,16 +2824,15 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
         gst_object_unref (priv->udpsrc_v6[i]);
       }
     }
-
-    for (l = priv->transport_sources; l; l = l->next) {
-      GstRTSPMulticastTransportSource *s = l->data;
-
-      if (!s->udpsrc[i])
-        continue;
-
-      gst_element_set_locked_state (s->udpsrc[i], FALSE);
-      gst_element_set_state (s->udpsrc[i], GST_STATE_NULL);
-      gst_bin_remove (bin, s->udpsrc[i]);
+    if (priv->udpsrc_mcast_v6[i]) {
+      if (priv->sinkpad || i == 1) {
+        gst_element_set_locked_state (priv->udpsrc_mcast_v6[i], FALSE);
+        gst_element_set_state (priv->udpsrc_mcast_v6[i], GST_STATE_NULL);
+        gst_bin_remove (bin, priv->udpsrc_mcast_v6[i]);
+      } else {
+        gst_element_set_state (priv->udpsrc_mcast_v6[i], GST_STATE_NULL);
+        gst_object_unref (priv->udpsrc_mcast_v6[i]);
+      }
     }
 
     if (priv->udpsink[i] && is_udp && (priv->srcpad || i == 1))
@@ -2777,6 +2858,8 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
 
     priv->udpsrc_v4[i] = NULL;
     priv->udpsrc_v6[i] = NULL;
+    priv->udpsrc_mcast_v4[i] = NULL;
+    priv->udpsrc_mcast_v6[i] = NULL;
     priv->udpsink[i] = NULL;
     priv->appsrc[i] = NULL;
     priv->appsink[i] = NULL;
@@ -2786,13 +2869,6 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
     priv->funnel[i] = NULL;
   }
 
-  for (l = priv->transport_sources; l; l = l->next) {
-    GstRTSPMulticastTransportSource *s = l->data;
-    g_slice_free (GstRTSPMulticastTransportSource, s);
-  }
-  g_list_free (priv->transport_sources);
-  priv->transport_sources = NULL;
-
   if (priv->srcpad) {
     gst_object_unref (priv->send_src[0]);
     priv->send_src[0] = NULL;
@@ -3139,89 +3215,6 @@ update_transport (GstRTSPStream * stream, GstRTSPStreamTransport * trans,
 
   switch (tr->lower_transport) {
     case GST_RTSP_LOWER_TRANS_UDP_MCAST:
-    {
-      GstRTSPMulticastTransportSource *source;
-      GstBin *bin;
-
-      bin = GST_BIN (gst_object_get_parent (GST_OBJECT (priv->funnel[1])));
-
-      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);
-          g_object_set (source->udpsrc[i], "loop", FALSE, NULL);
-
-          if (priv->srcpad) {
-            /* we set and keep these to playing so that they don't cause NO_PREROLL return
-             * values. This is only relevant for PLAY pipelines */
-            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 */
-          if (priv->sinkpad || i == 1) {
-            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);
-          }
-        }
-
-        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]);
-
-            if (priv->sinkpad || i == 1) {
-              gst_element_release_request_pad (priv->funnel[i],
-                  source->selpad[i]);
-            }
-          }
-
-          g_slice_free (GstRTSPMulticastTransportSource, source);
-        }
-      }
-
-      gst_object_unref (bin);
-
-      /* fall through for the generic case */
-    }
     case GST_RTSP_LOWER_TRANS_UDP:
     {
       gchar *dest;
index bd1d7e5..46304ac 100644 (file)
@@ -168,6 +168,9 @@ guint             gst_rtsp_stream_get_buffer_size  (GstRTSPStream *stream);
 
 void              gst_rtsp_stream_set_pt_map                 (GstRTSPStream * stream, guint pt, GstCaps * caps);
 GstElement *      gst_rtsp_stream_request_aux_sender         (GstRTSPStream * stream, guint sessid);
+
+gboolean          gst_rtsp_stream_allocate_udp_sockets       (GstRTSPStream * stream, GSocketFamily family,
+                                                              GstRTSPTransport *transport, gboolean use_client_setttings);
 /**
  * GstRTSPStreamTransportFilterFunc:
  * @stream: a #GstRTSPStream object