mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 19:20:35 +00:00
rtsp-stream: postpone UDP socket allocation until SETUP
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
This commit is contained in:
parent
d10ba734cd
commit
f62a9a7eb9
3 changed files with 186 additions and 180 deletions
|
@ -1403,26 +1403,26 @@ default_configure_client_transport (GstRTSPClient * client,
|
||||||
/* we have a valid transport now, set the destination of the client. */
|
/* we have a valid transport now, set the destination of the client. */
|
||||||
if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
|
if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
|
||||||
gboolean use_client_settings;
|
gboolean use_client_settings;
|
||||||
|
GSocketFamily family;
|
||||||
|
|
||||||
use_client_settings =
|
use_client_settings =
|
||||||
gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS);
|
gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS);
|
||||||
|
|
||||||
if (ct->destination && use_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,
|
if (!gst_rtsp_stream_allocate_udp_sockets (ctx->stream, family, ct, TRUE))
|
||||||
ct->port.min, ct->port.max - ct->port.min + 1, ct->ttl);
|
goto no_udp_protocol;
|
||||||
|
|
||||||
if (addr == NULL)
|
|
||||||
goto no_address;
|
|
||||||
|
|
||||||
gst_rtsp_address_free (addr);
|
|
||||||
} else {
|
} else {
|
||||||
GstRTSPAddress *addr;
|
GstRTSPAddress *addr;
|
||||||
GSocketFamily family;
|
|
||||||
|
|
||||||
family = priv->is_ipv6 ? G_SOCKET_FAMILY_IPV6 : G_SOCKET_FAMILY_IPV4;
|
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);
|
addr = gst_rtsp_stream_get_multicast_address (ctx->stream, family);
|
||||||
if (addr == NULL)
|
if (addr == NULL)
|
||||||
goto no_address;
|
goto no_address;
|
||||||
|
@ -1475,6 +1475,11 @@ default_configure_client_transport (GstRTSPClient * client,
|
||||||
gst_rtsp_session_media_alloc_channels (ctx->sessmedia,
|
gst_rtsp_session_media_alloc_channels (ctx->sessmedia,
|
||||||
&ct->interleaved);
|
&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;
|
return TRUE;
|
||||||
|
@ -1485,6 +1490,11 @@ no_address:
|
||||||
GST_ERROR_OBJECT (client, "failed to acquire address for stream");
|
GST_ERROR_OBJECT (client, "failed to acquire address for stream");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
no_udp_protocol:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (client, "failed to allocate udp ports");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstRTSPTransport *
|
static GstRTSPTransport *
|
||||||
|
|
|
@ -62,15 +62,6 @@
|
||||||
#define GST_RTSP_STREAM_GET_PRIVATE(obj) \
|
#define GST_RTSP_STREAM_GET_PRIVATE(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_RTSP_STREAM, GstRTSPStreamPrivate))
|
(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
|
struct _GstRTSPStreamPrivate
|
||||||
{
|
{
|
||||||
GMutex lock;
|
GMutex lock;
|
||||||
|
@ -106,10 +97,14 @@ struct _GstRTSPStreamPrivate
|
||||||
/* sinks used for sending and receiving RTP and RTCP over ipv4, they share
|
/* sinks used for sending and receiving RTP and RTCP over ipv4, they share
|
||||||
* sockets */
|
* sockets */
|
||||||
GstElement *udpsrc_v4[2];
|
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
|
/* sinks used for sending and receiving RTP and RTCP over ipv6, they share
|
||||||
* sockets */
|
* sockets */
|
||||||
GstElement *udpsrc_v6[2];
|
GstElement *udpsrc_v6[2];
|
||||||
|
/* UDP sources for UDP multicast transports */
|
||||||
|
GstElement *udpsrc_mcast_v6[2];
|
||||||
|
|
||||||
GstElement *udpqueue[2];
|
GstElement *udpqueue[2];
|
||||||
GstElement *udpsink[2];
|
GstElement *udpsink[2];
|
||||||
|
@ -142,6 +137,8 @@ struct _GstRTSPStreamPrivate
|
||||||
GstRTSPAddressPool *pool;
|
GstRTSPAddressPool *pool;
|
||||||
GstRTSPAddress *addr_v4;
|
GstRTSPAddress *addr_v4;
|
||||||
GstRTSPAddress *addr_v6;
|
GstRTSPAddress *addr_v6;
|
||||||
|
gboolean have_ipv4_mcast;
|
||||||
|
gboolean have_ipv6_mcast;
|
||||||
|
|
||||||
/* the caps of the stream */
|
/* the caps of the stream */
|
||||||
gulong caps_sig;
|
gulong caps_sig;
|
||||||
|
@ -157,9 +154,6 @@ struct _GstRTSPStreamPrivate
|
||||||
guint tr_cache_cookie_rtcp;
|
guint tr_cache_cookie_rtcp;
|
||||||
|
|
||||||
|
|
||||||
/* UDP sources for UDP multicast transports */
|
|
||||||
GList *transport_sources;
|
|
||||||
|
|
||||||
gint dscp_qos;
|
gint dscp_qos;
|
||||||
|
|
||||||
/* stream blocking */
|
/* stream blocking */
|
||||||
|
@ -1106,7 +1100,8 @@ no_udp_protocol:
|
||||||
|
|
||||||
/* must be called with lock */
|
/* must be called with lock */
|
||||||
static void
|
static void
|
||||||
play_udpsources_one_family (GstRTSPStream * stream, GSocketFamily family)
|
play_udpsources_one_family (GstRTSPStream * stream, GstElement * udpsrc_out[2],
|
||||||
|
GSocketFamily family)
|
||||||
{
|
{
|
||||||
GstRTSPStreamPrivate *priv;
|
GstRTSPStreamPrivate *priv;
|
||||||
GstPad *pad, *selpad;
|
GstPad *pad, *selpad;
|
||||||
|
@ -1118,38 +1113,21 @@ play_udpsources_one_family (GstRTSPStream * stream, GSocketFamily family)
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
if (priv->sinkpad || i == 1) {
|
if (priv->sinkpad || i == 1) {
|
||||||
if (family == G_SOCKET_FAMILY_IPV4 && priv->udpsrc_v4[i]) {
|
if (priv->srcpad) {
|
||||||
if (priv->srcpad) {
|
/* we set and keep these to playing so that they don't cause NO_PREROLL return
|
||||||
/* we set and keep these to playing so that they don't cause NO_PREROLL return
|
* values. This is only relevant for PLAY pipelines */
|
||||||
* values. This is only relevant for PLAY pipelines */
|
gst_element_set_state (udpsrc_out[i], GST_STATE_PLAYING);
|
||||||
gst_element_set_state (priv->udpsrc_v4[i], GST_STATE_PLAYING);
|
gst_element_set_locked_state (udpsrc_out[i], TRUE);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
/* add udpsrc */
|
||||||
|
gst_bin_add (bin, udpsrc_out[i]);
|
||||||
|
|
||||||
if (family == G_SOCKET_FAMILY_IPV6 && priv->udpsrc_v6[i]) {
|
/* and link to the funnel */
|
||||||
if (priv->srcpad) {
|
selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
|
||||||
gst_element_set_state (priv->udpsrc_v6[i], GST_STATE_PLAYING);
|
pad = gst_element_get_static_pad (udpsrc_out[i], "src");
|
||||||
gst_element_set_locked_state (priv->udpsrc_v6[i], TRUE);
|
gst_pad_link (pad, selpad);
|
||||||
}
|
gst_object_unref (pad);
|
||||||
gst_bin_add (bin, priv->udpsrc_v6[i]);
|
gst_object_unref (selpad);
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1159,18 +1137,27 @@ play_udpsources_one_family (GstRTSPStream * stream, GSocketFamily family)
|
||||||
/* must be called with lock */
|
/* must be called with lock */
|
||||||
static gboolean
|
static gboolean
|
||||||
create_and_configure_udpsources_one_family (GstElement * udpsrc_out[2],
|
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;
|
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[0] = gst_element_factory_make ("udpsrc", NULL);
|
||||||
udpsrc_out[1] = gst_element_factory_make ("udpsrc", NULL);
|
udpsrc_out[1] = gst_element_factory_make ("udpsrc", NULL);
|
||||||
|
|
||||||
if (udpsrc_out[0] == NULL || udpsrc_out[1] == NULL)
|
if (udpsrc_out[0] == NULL || udpsrc_out[1] == NULL)
|
||||||
goto error;
|
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[0]), "socket", rtp_socket, NULL);
|
||||||
g_object_set (G_OBJECT (udpsrc_out[1]), "socket", rtcp_socket, NULL);
|
g_object_set (G_OBJECT (udpsrc_out[1]), "socket", rtcp_socket, NULL);
|
||||||
|
|
||||||
|
@ -1198,7 +1185,8 @@ error:
|
||||||
static gboolean
|
static gboolean
|
||||||
alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
|
alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
|
||||||
GstElement * udpsrc_out[2], GstRTSPRange * server_port_out,
|
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;
|
GstRTSPStreamPrivate *priv = stream->priv;
|
||||||
GSocket *rtp_socket = NULL;
|
GSocket *rtp_socket = NULL;
|
||||||
|
@ -1209,12 +1197,15 @@ alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family,
|
||||||
GList *rejected_addresses = NULL;
|
GList *rejected_addresses = NULL;
|
||||||
GstRTSPAddress *addr = NULL;
|
GstRTSPAddress *addr = NULL;
|
||||||
GInetAddress *inetaddr = NULL;
|
GInetAddress *inetaddr = NULL;
|
||||||
|
gchar *addr_str;
|
||||||
GSocketAddress *rtp_sockaddr = NULL;
|
GSocketAddress *rtp_sockaddr = NULL;
|
||||||
GSocketAddress *rtcp_sockaddr = NULL;
|
GSocketAddress *rtcp_sockaddr = NULL;
|
||||||
GstRTSPAddressPool * pool;
|
GstRTSPAddressPool * pool;
|
||||||
|
GstRTSPLowerTrans transport;
|
||||||
|
|
||||||
pool = priv->pool;
|
pool = priv->pool;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
transport = ct->lower_transport;
|
||||||
|
|
||||||
/* Start with random port */
|
/* Start with random port */
|
||||||
tmp_rtp = 0;
|
tmp_rtp = 0;
|
||||||
|
@ -1238,19 +1229,30 @@ again:
|
||||||
goto no_udp_protocol;
|
goto no_udp_protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool && gst_rtsp_address_pool_has_unicast_addresses (pool)) {
|
if (pool) {
|
||||||
GstRTSPAddressFlags flags;
|
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)
|
if (addr)
|
||||||
rejected_addresses = g_list_prepend (rejected_addresses, 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)
|
if (family == G_SOCKET_FAMILY_IPV6)
|
||||||
flags |= GST_RTSP_ADDRESS_FLAG_IPV6;
|
flags |= GST_RTSP_ADDRESS_FLAG_IPV6;
|
||||||
else
|
else
|
||||||
flags |= GST_RTSP_ADDRESS_FLAG_IPV4;
|
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)
|
if (addr == NULL)
|
||||||
goto no_ports;
|
goto no_ports;
|
||||||
|
@ -1306,12 +1308,23 @@ again:
|
||||||
}
|
}
|
||||||
g_object_unref (rtcp_sockaddr);
|
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);
|
g_clear_object (&inetaddr);
|
||||||
|
|
||||||
if (!create_and_configure_udpsources_one_family (udpsrc_out, rtp_socket,
|
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;
|
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[0]), "port", &rtpport, NULL);
|
||||||
g_object_get (G_OBJECT (udpsrc_out[1]), "port", &rtcpport, NULL);
|
g_object_get (G_OBJECT (udpsrc_out[1]), "port", &rtcpport, NULL);
|
||||||
|
@ -1320,7 +1333,6 @@ again:
|
||||||
if (rtpport != tmp_rtp || rtcpport != tmp_rtcp)
|
if (rtpport != tmp_rtp || rtcpport != tmp_rtcp)
|
||||||
goto port_error;
|
goto port_error;
|
||||||
|
|
||||||
|
|
||||||
/* set RTP and RTCP sockets */
|
/* set RTP and RTCP sockets */
|
||||||
set_sockets_for_udpsinks (stream, rtp_socket, rtcp_socket, family);
|
set_sockets_for_udpsinks (stream, rtp_socket, rtcp_socket, family);
|
||||||
|
|
||||||
|
@ -1368,21 +1380,65 @@ cleanup:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* must be called with lock */
|
/**
|
||||||
static gboolean
|
* gst_rtsp_stream_allocate_udp_sockets:
|
||||||
alloc_ports (GstRTSPStream * stream)
|
* @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 =
|
g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
|
||||||
alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV4, priv->udpsrc_v4,
|
priv = stream->priv;
|
||||||
&priv->server_port_v4, &priv->server_addr_v4);
|
g_return_val_if_fail (priv->is_joined, FALSE);
|
||||||
|
|
||||||
priv->have_ipv6 =
|
g_mutex_lock (&priv->lock);
|
||||||
alloc_ports_one_family (stream, G_SOCKET_FAMILY_IPV6, priv->udpsrc_v6,
|
|
||||||
&priv->server_port_v6, &priv->server_addr_v6);
|
|
||||||
|
|
||||||
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;
|
guint idx;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
GstPadLinkReturn ret;
|
GstPadLinkReturn ret;
|
||||||
gboolean is_udp;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
|
g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
|
||||||
g_return_val_if_fail (GST_IS_BIN (bin), 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);
|
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) {
|
if (priv->srcpad) {
|
||||||
/* be notified of caps changes */
|
/* be notified of caps changes */
|
||||||
priv->caps_sig = g_signal_connect (priv->send_src[0], "notify::caps",
|
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]);
|
gst_object_unref (priv->udpsrc_v4[1]);
|
||||||
priv->udpsrc_v4[1] = NULL;
|
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]) {
|
if (priv->udpsrc_v6[0]) {
|
||||||
gst_element_set_state (priv->udpsrc_v6[0], GST_STATE_NULL);
|
gst_element_set_state (priv->udpsrc_v6[0], GST_STATE_NULL);
|
||||||
gst_object_unref (priv->udpsrc_v6[0]);
|
gst_object_unref (priv->udpsrc_v6[0]);
|
||||||
|
@ -2639,6 +2698,16 @@ no_udp_protocol:
|
||||||
gst_object_unref (priv->udpsrc_v6[1]);
|
gst_object_unref (priv->udpsrc_v6[1]);
|
||||||
priv->udpsrc_v6[1] = NULL;
|
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);
|
g_mutex_unlock (&priv->lock);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2660,7 +2729,6 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
|
||||||
{
|
{
|
||||||
GstRTSPStreamPrivate *priv;
|
GstRTSPStreamPrivate *priv;
|
||||||
gint i;
|
gint i;
|
||||||
GList *l;
|
|
||||||
gboolean is_tcp, is_udp;
|
gboolean is_tcp, is_udp;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
|
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->udpsrc_v6[i]) {
|
||||||
if (priv->sinkpad || i == 1) {
|
if (priv->sinkpad || i == 1) {
|
||||||
gst_element_set_locked_state (priv->udpsrc_v6[i], FALSE);
|
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]);
|
gst_object_unref (priv->udpsrc_v6[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (priv->udpsrc_mcast_v6[i]) {
|
||||||
for (l = priv->transport_sources; l; l = l->next) {
|
if (priv->sinkpad || i == 1) {
|
||||||
GstRTSPMulticastTransportSource *s = l->data;
|
gst_element_set_locked_state (priv->udpsrc_mcast_v6[i], FALSE);
|
||||||
|
gst_element_set_state (priv->udpsrc_mcast_v6[i], GST_STATE_NULL);
|
||||||
if (!s->udpsrc[i])
|
gst_bin_remove (bin, priv->udpsrc_mcast_v6[i]);
|
||||||
continue;
|
} else {
|
||||||
|
gst_element_set_state (priv->udpsrc_mcast_v6[i], GST_STATE_NULL);
|
||||||
gst_element_set_locked_state (s->udpsrc[i], FALSE);
|
gst_object_unref (priv->udpsrc_mcast_v6[i]);
|
||||||
gst_element_set_state (s->udpsrc[i], GST_STATE_NULL);
|
}
|
||||||
gst_bin_remove (bin, s->udpsrc[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->udpsink[i] && is_udp && (priv->srcpad || i == 1))
|
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_v4[i] = NULL;
|
||||||
priv->udpsrc_v6[i] = NULL;
|
priv->udpsrc_v6[i] = NULL;
|
||||||
|
priv->udpsrc_mcast_v4[i] = NULL;
|
||||||
|
priv->udpsrc_mcast_v6[i] = NULL;
|
||||||
priv->udpsink[i] = NULL;
|
priv->udpsink[i] = NULL;
|
||||||
priv->appsrc[i] = NULL;
|
priv->appsrc[i] = NULL;
|
||||||
priv->appsink[i] = NULL;
|
priv->appsink[i] = NULL;
|
||||||
|
@ -2786,13 +2869,6 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
|
||||||
priv->funnel[i] = NULL;
|
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) {
|
if (priv->srcpad) {
|
||||||
gst_object_unref (priv->send_src[0]);
|
gst_object_unref (priv->send_src[0]);
|
||||||
priv->send_src[0] = NULL;
|
priv->send_src[0] = NULL;
|
||||||
|
@ -3139,89 +3215,6 @@ update_transport (GstRTSPStream * stream, GstRTSPStreamTransport * trans,
|
||||||
|
|
||||||
switch (tr->lower_transport) {
|
switch (tr->lower_transport) {
|
||||||
case GST_RTSP_LOWER_TRANS_UDP_MCAST:
|
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:
|
case GST_RTSP_LOWER_TRANS_UDP:
|
||||||
{
|
{
|
||||||
gchar *dest;
|
gchar *dest;
|
||||||
|
|
|
@ -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);
|
void gst_rtsp_stream_set_pt_map (GstRTSPStream * stream, guint pt, GstCaps * caps);
|
||||||
GstElement * gst_rtsp_stream_request_aux_sender (GstRTSPStream * stream, guint sessid);
|
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:
|
* GstRTSPStreamTransportFilterFunc:
|
||||||
* @stream: a #GstRTSPStream object
|
* @stream: a #GstRTSPStream object
|
||||||
|
|
Loading…
Reference in a new issue