From 1730940abd0f6dbdb69b4ab554403b70ac4fe810 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Fri, 4 Sep 2020 21:14:35 +0200 Subject: [PATCH] rtsp-media-factory: expose API to disable RTCP This is supported by the RFC, and can be useful on systems where allocating two consecutive ports is problematic, and RTCP is not necessary. Part-of: --- examples/test-launch.c | 5 ++ gst/rtsp-server/rtsp-media-factory.c | 81 +++++++++++++++++++++++ gst/rtsp-server/rtsp-media-factory.h | 7 ++ gst/rtsp-server/rtsp-media.c | 18 +++++ gst/rtsp-server/rtsp-server-internal.h | 3 + gst/rtsp-server/rtsp-stream.c | 116 +++++++++++++++++++++------------ tests/check/gst/client.c | 47 +++++++++++-- 7 files changed, 232 insertions(+), 45 deletions(-) diff --git a/examples/test-launch.c b/examples/test-launch.c index 1675591..b21df8e 100644 --- a/examples/test-launch.c +++ b/examples/test-launch.c @@ -22,12 +22,16 @@ #include #define DEFAULT_RTSP_PORT "8554" +#define DEFAULT_DISABLE_RTCP FALSE static char *port = (char *) DEFAULT_RTSP_PORT; +static gboolean disable_rtcp = DEFAULT_DISABLE_RTCP; static GOptionEntry entries[] = { {"port", 'p', 0, G_OPTION_ARG_STRING, &port, "Port to listen on (default: " DEFAULT_RTSP_PORT ")", "PORT"}, + {"disable-rtcp", '\0', 0, G_OPTION_ARG_NONE, &disable_rtcp, + "Whether RTCP should be disabled (default false)", NULL}, {NULL} }; @@ -70,6 +74,7 @@ main (int argc, char *argv[]) factory = gst_rtsp_media_factory_new (); gst_rtsp_media_factory_set_launch (factory, argv[1]); gst_rtsp_media_factory_set_shared (factory, TRUE); + gst_rtsp_media_factory_set_enable_rtcp (factory, !disable_rtcp); /* attach the test factory to the /test url */ gst_rtsp_mount_points_add_factory (mounts, "/test", factory); diff --git a/gst/rtsp-server/rtsp-media-factory.c b/gst/rtsp-server/rtsp-media-factory.c index a2d091d..5dd9dc0 100644 --- a/gst/rtsp-server/rtsp-media-factory.c +++ b/gst/rtsp-server/rtsp-media-factory.c @@ -41,6 +41,7 @@ #include "config.h" #endif +#include "rtsp-server-internal.h" #include "rtsp-media-factory.h" #define GST_RTSP_MEDIA_FACTORY_GET_LOCK(f) (&(GST_RTSP_MEDIA_FACTORY_CAST(f)->priv->lock)) @@ -65,6 +66,7 @@ struct _GstRTSPMediaFactoryPrivate gchar *multicast_iface; guint max_mcast_ttl; gboolean bind_mcast_address; + gboolean enable_rtcp; GstClockTime rtx_time; guint latency; @@ -95,6 +97,7 @@ struct _GstRTSPMediaFactoryPrivate #define DEFAULT_STOP_ON_DISCONNECT TRUE #define DEFAULT_DO_RETRANSMISSION FALSE #define DEFAULT_DSCP_QOS (-1) +#define DEFAULT_ENABLE_RTCP TRUE enum { @@ -113,6 +116,7 @@ enum PROP_MAX_MCAST_TTL, PROP_BIND_MCAST_ADDRESS, PROP_DSCP_QOS, + PROP_ENABLE_RTCP, PROP_LAST }; @@ -247,6 +251,18 @@ gst_rtsp_media_factory_class_init (GstRTSPMediaFactoryClass * klass) DEFAULT_BIND_MCAST_ADDRESS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstRTSPMediaFactory:enable-rtcp: + * + * Whether the created media should send and receive RTCP + * + * Since: 1.20 + */ + g_object_class_install_property (gobject_class, PROP_ENABLE_RTCP, + g_param_spec_boolean ("enable-rtcp", "Enable RTCP", + "Whether the created media should send and receive RTCP", + DEFAULT_ENABLE_RTCP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DSCP_QOS, g_param_spec_int ("dscp-qos", "DSCP QoS", "The IP DSCP field to use", -1, 63, @@ -295,6 +311,7 @@ gst_rtsp_media_factory_init (GstRTSPMediaFactory * factory) priv->do_retransmission = DEFAULT_DO_RETRANSMISSION; priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL; priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS; + priv->enable_rtcp = DEFAULT_ENABLE_RTCP; priv->dscp_qos = DEFAULT_DSCP_QOS; g_mutex_init (&priv->lock); @@ -381,6 +398,10 @@ gst_rtsp_media_factory_get_property (GObject * object, guint propid, case PROP_DSCP_QOS: g_value_set_int (value, gst_rtsp_media_factory_get_dscp_qos (factory)); break; + case PROP_ENABLE_RTCP: + g_value_set_boolean (value, + gst_rtsp_media_factory_is_enable_rtcp (factory)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); } @@ -442,6 +463,10 @@ gst_rtsp_media_factory_set_property (GObject * object, guint propid, case PROP_DSCP_QOS: gst_rtsp_media_factory_set_dscp_qos (factory, g_value_get_int (value)); break; + case PROP_ENABLE_RTCP: + gst_rtsp_media_factory_set_enable_rtcp (factory, + g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); } @@ -1686,6 +1711,57 @@ gst_rtsp_media_factory_is_bind_mcast_address (GstRTSPMediaFactory * factory) return result; } +/** + * gst_rtsp_media_factory_set_enable_rtcp: + * @factory: a #GstRTSPMediaFactory + * @enable: the new value + * + * Decide whether the created media should send and receive RTCP + * + * Since: 1.20 + */ +void +gst_rtsp_media_factory_set_enable_rtcp (GstRTSPMediaFactory * factory, + gboolean enable) +{ + GstRTSPMediaFactoryPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory)); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + priv->enable_rtcp = enable; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); +} + +/** + * gst_rtsp_media_factory_is_enable_rtcp: + * @factory: a #GstRTSPMediaFactory + * + * Check if created media will send and receive RTCP + * + * Returns: %TRUE if created media will send and receive RTCP + * + * Since: 1.20 + */ +gboolean +gst_rtsp_media_factory_is_enable_rtcp (GstRTSPMediaFactory * factory) +{ + GstRTSPMediaFactoryPrivate *priv; + gboolean result; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory), FALSE); + + priv = factory->priv; + + GST_RTSP_MEDIA_FACTORY_LOCK (factory); + result = priv->enable_rtcp; + GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); + + return result; +} + static gchar * default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url) { @@ -1757,6 +1833,7 @@ default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url) GstElement *element, *pipeline; GstRTSPMediaFactoryClass *klass; GType media_gtype; + gboolean enable_rtcp; klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory); @@ -1769,6 +1846,7 @@ default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url) GST_RTSP_MEDIA_FACTORY_LOCK (factory); media_gtype = factory->priv->media_gtype; + enable_rtcp = factory->priv->enable_rtcp; GST_RTSP_MEDIA_FACTORY_UNLOCK (factory); /* create a new empty media */ @@ -1776,6 +1854,9 @@ default_construct (GstRTSPMediaFactory * factory, const GstRTSPUrl * url) g_object_new (media_gtype, "element", element, "transport-mode", factory->priv->transport_mode, NULL); + /* We need to call this prior to collecting streams */ + gst_rtsp_media_set_enable_rtcp (media, enable_rtcp); + gst_rtsp_media_collect_streams (media); pipeline = klass->create_pipeline (factory, media); diff --git a/gst/rtsp-server/rtsp-media-factory.h b/gst/rtsp-server/rtsp-media-factory.h index dd08498..8e847fd 100644 --- a/gst/rtsp-server/rtsp-media-factory.h +++ b/gst/rtsp-server/rtsp-media-factory.h @@ -258,6 +258,13 @@ void gst_rtsp_media_factory_set_dscp_qos (GstRTSPMediaFactory * GST_RTSP_SERVER_API gint gst_rtsp_media_factory_get_dscp_qos (GstRTSPMediaFactory * factory); +GST_RTSP_SERVER_API +void gst_rtsp_media_factory_set_enable_rtcp (GstRTSPMediaFactory * factory, + gboolean enable); + +GST_RTSP_SERVER_API +gboolean gst_rtsp_media_factory_is_enable_rtcp (GstRTSPMediaFactory * factory); + /* creating the media from the factory and a url */ GST_RTSP_SERVER_API diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index eb9ead1..b22b95f 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -112,6 +112,7 @@ struct _GstRTSPMediaPrivate gchar *multicast_iface; guint max_mcast_ttl; gboolean bind_mcast_address; + gboolean enable_rtcp; gboolean blocked; GstRTSPTransportMode transport_mode; gboolean stop_on_disconnect; @@ -180,6 +181,7 @@ struct _GstRTSPMediaPrivate #define DEFAULT_MAX_MCAST_TTL 255 #define DEFAULT_BIND_MCAST_ADDRESS FALSE #define DEFAULT_DO_RATE_CONTROL TRUE +#define DEFAULT_ENABLE_RTCP TRUE #define DEFAULT_DO_RETRANSMISSION FALSE @@ -492,6 +494,7 @@ gst_rtsp_media_init (GstRTSPMedia * media) priv->do_retransmission = DEFAULT_DO_RETRANSMISSION; priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL; priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS; + priv->enable_rtcp = DEFAULT_ENABLE_RTCP; priv->do_rate_control = DEFAULT_DO_RATE_CONTROL; priv->dscp_qos = DEFAULT_DSCP_QOS; priv->expected_async_done = FALSE; @@ -2104,6 +2107,20 @@ gst_rtsp_media_is_bind_mcast_address (GstRTSPMedia * media) return result; } +void +gst_rtsp_media_set_enable_rtcp (GstRTSPMedia * media, gboolean enable) +{ + GstRTSPMediaPrivate *priv; + + g_return_if_fail (GST_IS_RTSP_MEDIA (media)); + + priv = media->priv; + + g_mutex_lock (&priv->lock); + priv->enable_rtcp = enable; + g_mutex_unlock (&priv->lock); +} + static GList * _find_payload_types (GstRTSPMedia * media) { @@ -2425,6 +2442,7 @@ gst_rtsp_media_create_stream (GstRTSPMedia * media, GstElement * payloader, gst_rtsp_stream_set_multicast_iface (stream, priv->multicast_iface); gst_rtsp_stream_set_max_mcast_ttl (stream, priv->max_mcast_ttl); gst_rtsp_stream_set_bind_mcast_address (stream, priv->bind_mcast_address); + gst_rtsp_stream_set_enable_rtcp (stream, priv->enable_rtcp); gst_rtsp_stream_set_profiles (stream, priv->profiles); gst_rtsp_stream_set_protocols (stream, priv->protocols); gst_rtsp_stream_set_retransmission_time (stream, priv->rtx_time); diff --git a/gst/rtsp-server/rtsp-server-internal.h b/gst/rtsp-server/rtsp-server-internal.h index 008b755..b5aaeff 100644 --- a/gst/rtsp-server/rtsp-server-internal.h +++ b/gst/rtsp-server/rtsp-server-internal.h @@ -58,6 +58,9 @@ gboolean gst_rtsp_stream_transport_check_back_pressure (GstRTSPS gboolean gst_rtsp_stream_is_tcp_receiver (GstRTSPStream * stream); +void gst_rtsp_media_set_enable_rtcp (GstRTSPMedia *media, gboolean enable); +void gst_rtsp_stream_set_enable_rtcp (GstRTSPStream *stream, gboolean enable); + G_END_DECLS #endif /* __GST_RTSP_SERVER_INTERNAL_H__ */ diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c index 7585a0c..3243e59 100644 --- a/gst/rtsp-server/rtsp-stream.c +++ b/gst/rtsp-server/rtsp-stream.c @@ -220,6 +220,9 @@ struct _GstRTSPStreamPrivate guint32 blocked_seqnum; guint32 blocked_rtptime; GstClockTime blocked_running_time; + + /* Whether we should send and receive RTCP */ + gboolean enable_rtcp; }; #define DEFAULT_CONTROL NULL @@ -229,6 +232,7 @@ struct _GstRTSPStreamPrivate #define DEFAULT_MAX_MCAST_TTL 255 #define DEFAULT_BIND_MCAST_ADDRESS FALSE #define DEFAULT_DO_RATE_CONTROL TRUE +#define DEFAULT_ENABLE_RTCP TRUE enum { @@ -328,6 +332,7 @@ gst_rtsp_stream_init (GstRTSPStream * stream) priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL; priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS; priv->do_rate_control = DEFAULT_DO_RATE_CONTROL; + priv->enable_rtcp = DEFAULT_ENABLE_RTCP; g_mutex_init (&priv->lock); @@ -1422,6 +1427,7 @@ alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family, /* Start with random port */ tmp_rtp = 0; + tmp_rtcp = 0; if (use_transport_settings) { if (!multicast) @@ -1453,14 +1459,16 @@ alloc_ports_one_family (GstRTSPStream * stream, GSocketFamily family, } } - rtcp_socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, - G_SOCKET_PROTOCOL_UDP, NULL); - if (!rtcp_socket) - goto no_udp_protocol; - g_socket_set_multicast_loopback (rtcp_socket, FALSE); + if (priv->enable_rtcp) { + rtcp_socket = g_socket_new (family, G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, NULL); + if (!rtcp_socket) + goto no_udp_protocol; + g_socket_set_multicast_loopback (rtcp_socket, FALSE); + } - /* try to allocate 2 UDP ports, the RTP port should be an even - * number and the RTCP port should be the next (uneven) port */ + /* try to allocate UDP ports, the RTP port should be an even + * number and the RTCP port (if enabled) should be the next (uneven) port */ again: if (rtp_socket == NULL) { @@ -1496,7 +1504,8 @@ again: if (*server_addr_out) addr = *server_addr_out; else - addr = gst_rtsp_address_pool_acquire_address (pool, flags, 2); + addr = gst_rtsp_address_pool_acquire_address (pool, flags, + priv->enable_rtcp ? 2 : 1); if (addr == NULL) goto no_address; @@ -1556,18 +1565,20 @@ again: g_object_unref (rtp_sockaddr); /* set port */ - tmp_rtcp = tmp_rtp + 1; + if (priv->enable_rtcp) { + tmp_rtcp = tmp_rtp + 1; - rtcp_sockaddr = g_inet_socket_address_new (inetaddr, tmp_rtcp); - if (!g_socket_bind (rtcp_socket, rtcp_sockaddr, FALSE, NULL)) { - GST_DEBUG_OBJECT (stream, "rctp bind() failed, will try again"); + rtcp_sockaddr = g_inet_socket_address_new (inetaddr, tmp_rtcp); + if (!g_socket_bind (rtcp_socket, rtcp_sockaddr, FALSE, NULL)) { + GST_DEBUG_OBJECT (stream, "rctp bind() failed, will try again"); + g_object_unref (rtcp_sockaddr); + g_clear_object (&rtp_socket); + if (transport_settings_defined) + goto transport_settings_error; + goto again; + } g_object_unref (rtcp_sockaddr); - g_clear_object (&rtp_socket); - if (transport_settings_defined) - goto transport_settings_error; - goto again; } - g_object_unref (rtcp_sockaddr); if (!addr) { addr = g_slice_new0 (GstRTSPAddress); @@ -1585,15 +1596,21 @@ again: if (multicast && (ct->ttl > 0) && (ct->ttl <= priv->max_mcast_ttl)) { GST_DEBUG ("setting mcast ttl to %d", ct->ttl); g_socket_set_multicast_ttl (rtp_socket, ct->ttl); - g_socket_set_multicast_ttl (rtcp_socket, ct->ttl); + if (rtcp_socket) + g_socket_set_multicast_ttl (rtcp_socket, ct->ttl); } socket_out[0] = rtp_socket; socket_out[1] = rtcp_socket; *server_addr_out = addr; - GST_DEBUG_OBJECT (stream, "allocated address: %s and ports: %d, %d", - addr->address, tmp_rtp, tmp_rtcp); + if (priv->enable_rtcp) { + GST_DEBUG_OBJECT (stream, "allocated address: %s and ports: %d, %d", + addr->address, tmp_rtp, tmp_rtcp); + } else { + GST_DEBUG_OBJECT (stream, "allocated address: %s and port: %d", + addr->address, tmp_rtp); + } g_list_free_full (rejected_addresses, (GDestroyNotify) gst_rtsp_address_free); @@ -1922,14 +1939,18 @@ gst_rtsp_stream_get_server_port (GstRTSPStream * stream, if (family == G_SOCKET_FAMILY_IPV4) { if (server_port && priv->server_addr_v4) { server_port->min = priv->server_addr_v4->port; - server_port->max = - priv->server_addr_v4->port + priv->server_addr_v4->n_ports - 1; + if (priv->enable_rtcp) { + server_port->max = + priv->server_addr_v4->port + priv->server_addr_v4->n_ports - 1; + } } } else { if (server_port && priv->server_addr_v6) { server_port->min = priv->server_addr_v6->port; - server_port->max = - priv->server_addr_v6->port + priv->server_addr_v6->n_ports - 1; + if (priv->enable_rtcp) { + server_port->max = + priv->server_addr_v6->port + priv->server_addr_v6->n_ports - 1; + } } } g_mutex_unlock (&priv->lock); @@ -2262,6 +2283,16 @@ gst_rtsp_stream_is_bind_mcast_address (GstRTSPStream * stream) return result; } +void +gst_rtsp_stream_set_enable_rtcp (GstRTSPStream * stream, gboolean enable) +{ + g_return_if_fail (GST_IS_RTSP_STREAM (stream)); + + g_mutex_lock (&stream->priv->lock); + stream->priv->enable_rtcp = enable; + g_mutex_unlock (&stream->priv->lock); +} + /* executed from streaming thread */ static void caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPStream * stream) @@ -3518,10 +3549,10 @@ create_sender_part (GstRTSPStream * stream, const GstRTSPTransport * transport) g_object_set (priv->payloader, "onvif-no-rate-control", !priv->do_rate_control, NULL); - for (i = 0; i < 2; i++) { + for (i = 0; i < (priv->enable_rtcp ? 2 : 1); i++) { gboolean link_tee = FALSE; /* For the sender we create this bit of pipeline for both - * RTP and RTCP. + * RTP and RTCP (when enabled). * Initially there will be only one active transport for * the stream, so the pipeline will look like this: * @@ -3674,9 +3705,9 @@ create_receiver_part (GstRTSPStream * stream, const GstRTSPTransport * "RTP caps: %" GST_PTR_FORMAT " RTCP caps: %" GST_PTR_FORMAT, rtp_caps, rtcp_caps); - for (i = 0; i < 2; i++) { + for (i = 0; i < (priv->enable_rtcp ? 2 : 1); i++) { /* For the receiver we create this bit of pipeline for both - * RTP and RTCP. We receive RTP/RTCP on appsrc and udpsrc + * RTP and RTCP (when enabled). We receive RTP/RTCP on appsrc and udpsrc * and it is all funneled into the rtpbin receive pad. * * @@ -3938,12 +3969,15 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin, g_free (name); } - name = g_strdup_printf ("send_rtcp_src_%u", idx); - priv->send_src[1] = gst_element_get_request_pad (rtpbin, name); - g_free (name); - name = g_strdup_printf ("recv_rtcp_sink_%u", idx); - priv->recv_sink[1] = gst_element_get_request_pad (rtpbin, name); - g_free (name); + if (priv->enable_rtcp) { + name = g_strdup_printf ("send_rtcp_src_%u", idx); + priv->send_src[1] = gst_element_get_request_pad (rtpbin, name); + g_free (name); + + name = g_strdup_printf ("recv_rtcp_sink_%u", idx); + priv->recv_sink[1] = gst_element_get_request_pad (rtpbin, name); + g_free (name); + } /* get the session */ g_signal_emit_by_name (rtpbin, "get-internal-session", idx, &priv->session); @@ -4085,7 +4119,7 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin, priv->recv_rtp_src = NULL; } - for (i = 0; i < 2; i++) { + for (i = 0; i < (priv->enable_rtcp ? 2 : 1); i++) { clear_element (bin, &priv->udpsrc_v4[i]); clear_element (bin, &priv->udpsrc_v6[i]); clear_element (bin, &priv->udpqueue[i]); @@ -4115,9 +4149,11 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin, priv->send_src[0] = NULL; } - gst_element_release_request_pad (rtpbin, priv->send_src[1]); - gst_object_unref (priv->send_src[1]); - priv->send_src[1] = NULL; + if (priv->enable_rtcp) { + gst_element_release_request_pad (rtpbin, priv->send_src[1]); + gst_object_unref (priv->send_src[1]); + priv->send_src[1] = NULL; + } g_object_unref (priv->session); priv->session = NULL; @@ -6206,8 +6242,8 @@ gst_rtsp_stream_set_rate_control (GstRTSPStream * stream, gboolean enabled) if (stream->priv->appsink[0]) g_object_set (stream->priv->appsink[0], "sync", enabled, NULL); if (stream->priv->payloader - && g_object_class_find_property (G_OBJECT_GET_CLASS (stream-> - priv->payloader), "onvif-no-rate-control")) + && g_object_class_find_property (G_OBJECT_GET_CLASS (stream->priv-> + payloader), "onvif-no-rate-control")) g_object_set (stream->priv->payloader, "onvif-no-rate-control", !enabled, NULL); if (stream->priv->session) { diff --git a/tests/check/gst/client.c b/tests/check/gst/client.c index 6bf6544..d506f9a 100644 --- a/tests/check/gst/client.c +++ b/tests/check/gst/client.c @@ -206,7 +206,7 @@ create_connection (GstRTSPConnection ** conn) } static GstRTSPClient * -setup_client (const gchar * launch_line) +setup_client (const gchar * launch_line, gboolean enable_rtcp) { GstRTSPClient *client; GstRTSPSessionPool *session_pool; @@ -227,6 +227,8 @@ setup_client (const gchar * launch_line) else gst_rtsp_media_factory_set_launch (factory, launch_line); + gst_rtsp_media_factory_set_enable_rtcp (factory, enable_rtcp); + gst_rtsp_mount_points_add_factory (mount_points, "/test", factory); gst_rtsp_client_set_mount_points (client, mount_points); @@ -515,7 +517,7 @@ GST_START_TEST (test_describe) g_object_unref (client); /* simple DESCRIBE for an existing url */ - client = setup_client (NULL); + client = setup_client (NULL, TRUE); fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE, "rtsp://localhost/test") == GST_RTSP_OK); str = g_strdup_printf ("%d", cseq); @@ -688,7 +690,7 @@ GST_START_TEST (test_setup_tcp) GstRTSPMessage request = { 0, }; gchar *str; - client = setup_client (NULL); + client = setup_client (NULL, TRUE); create_connection (&conn); fail_unless (gst_rtsp_client_set_connection (client, conn)); @@ -714,6 +716,40 @@ GST_START_TEST (test_setup_tcp) GST_END_TEST; +GST_START_TEST (test_setup_no_rtcp) +{ + GstRTSPClient *client; + GstRTSPConnection *conn; + GstRTSPMessage request = { 0, }; + gchar *str; + + client = setup_client (NULL, FALSE); + create_connection (&conn); + fail_unless (gst_rtsp_client_set_connection (client, conn)); + + fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP, + "rtsp://localhost/test/stream=0") == GST_RTSP_OK); + str = g_strdup_printf ("%d", cseq); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CSEQ, str); + g_free (str); + gst_rtsp_message_add_header (&request, GST_RTSP_HDR_TRANSPORT, + "RTP/AVP;unicast;client_port=5000-5001"); + + gst_rtsp_client_set_send_func (client, test_setup_response_200, NULL, NULL); + /* We want to verify that server_port holds a single number, not a range */ + expected_transport = + "RTP/AVP;unicast;client_port=5000-5001;server_port=[0-9]+;ssrc=.*;mode=\"PLAY\""; + fail_unless (gst_rtsp_client_handle_message (client, + &request) == GST_RTSP_OK); + + gst_rtsp_message_unset (&request); + + send_teardown (client); + teardown_client (client); +} + +GST_END_TEST; + GST_START_TEST (test_setup_tcp_two_streams_same_channels) { GstRTSPClient *client; @@ -721,7 +757,7 @@ GST_START_TEST (test_setup_tcp_two_streams_same_channels) GstRTSPMessage request = { 0, }; gchar *str; - client = setup_client (NULL); + client = setup_client (NULL, TRUE); create_connection (&conn); fail_unless (gst_rtsp_client_set_connection (client, conn)); @@ -1044,7 +1080,7 @@ test_client_sdp (const gchar * launch_line, guint * bandwidth_val) gchar *str; /* simple DESCRIBE for an existing url */ - client = setup_client (launch_line); + client = setup_client (launch_line, TRUE); fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_DESCRIBE, "rtsp://localhost/test") == GST_RTSP_OK); str = g_strdup_printf ("%d", cseq); @@ -2044,6 +2080,7 @@ rtspclient_suite (void) tcase_add_test (tc, test_options); tcase_add_test (tc, test_describe); tcase_add_test (tc, test_setup_tcp); + tcase_add_test (tc, test_setup_no_rtcp); tcase_add_test (tc, test_setup_tcp_two_streams_same_channels); tcase_add_test (tc, test_client_multicast_transport_404); tcase_add_test (tc, test_client_multicast_transport); -- 2.7.4