gboolean stop_on_disconnect;
gchar *multicast_iface;
guint max_mcast_ttl;
+ gboolean bind_mcast_address;
GstClockTime rtx_time;
guint latency;
#define DEFAULT_BUFFER_SIZE 0x80000
#define DEFAULT_LATENCY 200
#define DEFAULT_MAX_MCAST_TTL 255
+#define DEFAULT_BIND_MCAST_ADDRESS FALSE
#define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
#define DEFAULT_STOP_ON_DISCONNECT TRUE
#define DEFAULT_DO_RETRANSMISSION FALSE
PROP_STOP_ON_DISCONNECT,
PROP_CLOCK,
PROP_MAX_MCAST_TTL,
+ PROP_BIND_MCAST_ADDRESS,
PROP_LAST
};
255, DEFAULT_MAX_MCAST_TTL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_BIND_MCAST_ADDRESS,
+ g_param_spec_boolean ("bind-mcast-address", "Bind mcast address",
+ "Whether the multicast sockets should be bound to multicast addresses "
+ "or INADDR_ANY",
+ DEFAULT_BIND_MCAST_ADDRESS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gst_rtsp_media_factory_signals[SIGNAL_MEDIA_CONSTRUCTED] =
g_signal_new ("media-constructed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPMediaFactoryClass,
priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL;
+ priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS;
g_mutex_init (&priv->lock);
g_mutex_init (&priv->medias_lock);
g_value_set_uint (value,
gst_rtsp_media_factory_get_max_mcast_ttl (factory));
break;
+ case PROP_BIND_MCAST_ADDRESS:
+ g_value_set_boolean (value,
+ gst_rtsp_media_factory_is_bind_mcast_address (factory));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
gst_rtsp_media_factory_set_max_mcast_ttl (factory,
g_value_get_uint (value));
break;
+ case PROP_BIND_MCAST_ADDRESS:
+ gst_rtsp_media_factory_set_bind_mcast_address (factory,
+ g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
return result;
}
+/**
+ * gst_rtsp_media_factory_set_bind_mcast_address:
+ * @factory: a #GstRTSPMediaFactory
+ * @bind_mcast_addr: the new value
+ *
+ * Decide whether the multicast socket should be bound to a multicast address or
+ * INADDR_ANY.
+ */
+void
+gst_rtsp_media_factory_set_bind_mcast_address (GstRTSPMediaFactory * factory,
+ gboolean bind_mcast_addr)
+{
+ GstRTSPMediaFactoryPrivate *priv;
+
+ g_return_if_fail (GST_IS_RTSP_MEDIA_FACTORY (factory));
+
+ priv = factory->priv;
+
+ GST_RTSP_MEDIA_FACTORY_LOCK (factory);
+ priv->bind_mcast_address = bind_mcast_addr;
+ GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
+}
+
+/**
+ * gst_rtsp_media_factory_is_bind_mcast_address:
+ * @factory: a #GstRTSPMediaFactory
+ *
+ * Check if multicast sockets are configured to be bound to multicast addresses.
+ *
+ * Returns: %TRUE if multicast sockets are configured to be bound to multicast addresses.
+ */
+gboolean
+gst_rtsp_media_factory_is_bind_mcast_address (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->bind_mcast_address;
+ GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
+
+ return result;
+}
+
static gchar *
default_gen_key (GstRTSPMediaFactory * factory, const GstRTSPUrl * url)
{
gchar *multicast_iface;
GstRTSPPublishClockMode publish_clock_mode;
guint ttl;
+ gboolean bind_mcast;
/* configure the sharedness */
GST_RTSP_MEDIA_FACTORY_LOCK (factory);
clock = priv->clock ? gst_object_ref (priv->clock) : NULL;
publish_clock_mode = priv->publish_clock_mode;
ttl = priv->max_mcast_ttl;
+ bind_mcast = priv->bind_mcast_address;
GST_RTSP_MEDIA_FACTORY_UNLOCK (factory);
gst_rtsp_media_set_suspend_mode (media, suspend_mode);
gst_rtsp_media_set_stop_on_disconnect (media, stop_on_disconnect);
gst_rtsp_media_set_publish_clock_mode (media, publish_clock_mode);
gst_rtsp_media_set_max_mcast_ttl (media, ttl);
+ gst_rtsp_media_set_bind_mcast_address (media, bind_mcast);
if (clock) {
gst_rtsp_media_set_clock (media, clock);
GST_RTSP_SERVER_API
guint gst_rtsp_media_factory_get_max_mcast_ttl (GstRTSPMediaFactory * factory);
+GST_RTSP_SERVER_API
+void gst_rtsp_media_factory_set_bind_mcast_address (GstRTSPMediaFactory * factory,
+ gboolean bind_mcast_addr);
+GST_RTSP_SERVER_API
+gboolean gst_rtsp_media_factory_is_bind_mcast_address (GstRTSPMediaFactory * factory);
+
/* creating the media from the factory and a url */
GST_RTSP_SERVER_API
GstRTSPAddressPool *pool;
gchar *multicast_iface;
guint max_mcast_ttl;
+ gboolean bind_mcast_address;
gboolean blocked;
GstRTSPTransportMode transport_mode;
gboolean stop_on_disconnect;
#define DEFAULT_TRANSPORT_MODE GST_RTSP_TRANSPORT_MODE_PLAY
#define DEFAULT_STOP_ON_DISCONNECT TRUE
#define DEFAULT_MAX_MCAST_TTL 255
+#define DEFAULT_BIND_MCAST_ADDRESS FALSE
#define DEFAULT_DO_RETRANSMISSION FALSE
PROP_STOP_ON_DISCONNECT,
PROP_CLOCK,
PROP_MAX_MCAST_TTL,
+ PROP_BIND_MCAST_ADDRESS,
PROP_LAST
};
255, DEFAULT_MAX_MCAST_TTL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_BIND_MCAST_ADDRESS,
+ g_param_spec_boolean ("bind-mcast-address", "Bind mcast address",
+ "Whether the multicast sockets should be bound to multicast addresses "
+ "or INADDR_ANY",
+ DEFAULT_BIND_MCAST_ADDRESS,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstRTSPMediaClass, new_stream), NULL, NULL,
priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
priv->do_retransmission = DEFAULT_DO_RETRANSMISSION;
priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL;
+ priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS;
}
static void
case PROP_MAX_MCAST_TTL:
g_value_set_uint (value, gst_rtsp_media_get_max_mcast_ttl (media));
break;
+ case PROP_BIND_MCAST_ADDRESS:
+ g_value_set_boolean (value, gst_rtsp_media_is_bind_mcast_address (media));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
case PROP_MAX_MCAST_TTL:
gst_rtsp_media_set_max_mcast_ttl (media, g_value_get_uint (value));
break;
+ case PROP_BIND_MCAST_ADDRESS:
+ gst_rtsp_media_set_bind_mcast_address (media,
+ g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
}
return res;
}
+/**
+ * gst_rtsp_media_set_bind_mcast_address:
+ * @media: a #GstRTSPMedia
+ * @bind_mcast_addr: the new value
+ *
+ * Decide whether the multicast socket should be bound to a multicast address or
+ * INADDR_ANY.
+ */
+void
+gst_rtsp_media_set_bind_mcast_address (GstRTSPMedia * media,
+ gboolean bind_mcast_addr)
+{
+ GstRTSPMediaPrivate *priv;
+ guint i;
+
+ g_return_if_fail (GST_IS_RTSP_MEDIA (media));
+
+ priv = media->priv;
+
+ g_mutex_lock (&priv->lock);
+ priv->bind_mcast_address = bind_mcast_addr;
+ for (i = 0; i < priv->streams->len; i++) {
+ GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
+ gst_rtsp_stream_set_bind_mcast_address (stream, bind_mcast_addr);
+ }
+ g_mutex_unlock (&priv->lock);
+}
+
+/**
+ * gst_rtsp_media_is_bind_mcast_address:
+ * @media: a #GstRTSPMedia
+ *
+ * Check if multicast sockets are configured to be bound to multicast addresses.
+ *
+ * Returns: %TRUE if multicast sockets are configured to be bound to multicast addresses.
+ */
+gboolean
+gst_rtsp_media_is_bind_mcast_address (GstRTSPMedia * media)
+{
+ GstRTSPMediaPrivate *priv;
+ gboolean result;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+
+ priv = media->priv;
+
+ g_mutex_lock (&priv->lock);
+ result = priv->bind_mcast_address;
+ g_mutex_unlock (&priv->lock);
+
+ return result;
+}
+
static GList *
_find_payload_types (GstRTSPMedia * media)
{
gst_rtsp_stream_set_address_pool (stream, priv->pool);
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_profiles (stream, priv->profiles);
gst_rtsp_stream_set_protocols (stream, priv->protocols);
gst_rtsp_stream_set_retransmission_time (stream, priv->rtx_time);
GST_RTSP_SERVER_API
guint gst_rtsp_media_get_max_mcast_ttl (GstRTSPMedia *media);
+GST_RTSP_SERVER_API
+void gst_rtsp_media_set_bind_mcast_address (GstRTSPMedia *media, gboolean bind_mcast_addr);
+GST_RTSP_SERVER_API
+gboolean gst_rtsp_media_is_bind_mcast_address (GstRTSPMedia *media);
+
/* prepare the media for playback */
GST_RTSP_SERVER_API
gchar *multicast_iface;
guint max_mcast_ttl;
+ gboolean bind_mcast_address;
/* the caps of the stream */
gulong caps_sig;
#define DEFAULT_PROTOCOLS GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST | \
GST_RTSP_LOWER_TRANS_TCP
#define DEFAULT_MAX_MCAST_TTL 255
+#define DEFAULT_BIND_MCAST_ADDRESS FALSE
enum
{
priv->configured_protocols = 0;
priv->publish_clock_mode = GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK;
priv->max_mcast_ttl = DEFAULT_MAX_MCAST_TTL;
+ priv->bind_mcast_address = DEFAULT_BIND_MCAST_ADDRESS;
g_mutex_init (&priv->lock);
if (ct->destination != NULL) {
tmp_rtp = ct->port.min;
tmp_rtcp = ct->port.max;
+
+ /* check if the provided address is a multicast address */
inetaddr = g_inet_address_new_from_string (ct->destination);
if (inetaddr == NULL)
goto destination_error;
if (!g_inet_address_get_is_multicast (inetaddr))
goto destination_no_mcast;
- g_object_unref (inetaddr);
- inetaddr = g_inet_address_new_any (family);
+
+
+ if (!priv->bind_mcast_address) {
+ g_clear_object (&inetaddr);
+ inetaddr = g_inet_address_new_any (family);
+ }
GST_DEBUG_OBJECT (stream, "use transport settings");
transport_settings_defined = TRUE;
g_clear_object (&inetaddr);
/* FIXME: Does it really work with the IP_MULTICAST_ALL socket option and
* socket control message set in udpsrc? */
- if (multicast)
- inetaddr = g_inet_address_new_any (family);
- else
+ if (priv->bind_mcast_address || !multicast)
inetaddr = g_inet_address_new_from_string (addr->address);
+ else
+ inetaddr = g_inet_address_new_any (family);
} else {
if (tmp_rtp != 0) {
tmp_rtp += 2;
return res;
}
+/**
+ * gst_rtsp_stream_set_bind_mcast_address:
+ * @stream: a #GstRTSPStream,
+ * @bind_mcast_addr: the new value
+ *
+ * Decide whether the multicast socket should be bound to a multicast address or
+ * INADDR_ANY.
+ */
+void
+gst_rtsp_stream_set_bind_mcast_address (GstRTSPStream * stream,
+ gboolean bind_mcast_addr)
+{
+ g_return_if_fail (GST_IS_RTSP_STREAM (stream));
+
+ g_mutex_lock (&stream->priv->lock);
+ stream->priv->bind_mcast_address = bind_mcast_addr;
+ g_mutex_unlock (&stream->priv->lock);
+}
+
+/**
+ * gst_rtsp_stream_is_bind_mcast_address:
+ * @stream: a #GstRTSPStream
+ *
+ * Check if multicast sockets are configured to be bound to multicast addresses.
+ *
+ * Returns: %TRUE if multicast sockets are configured to be bound to multicast addresses.
+ */
+gboolean
+gst_rtsp_stream_is_bind_mcast_address (GstRTSPStream * stream)
+{
+ gboolean result;
+
+ g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
+
+ g_mutex_lock (&stream->priv->lock);
+ result = stream->priv->bind_mcast_address;
+ g_mutex_unlock (&stream->priv->lock);
+
+ return result;
+}
+
/* executed from streaming thread */
static void
caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPStream * stream)
gboolean gst_rtsp_stream_verify_mcast_ttl (GstRTSPStream *stream, guint ttl);
GST_RTSP_SERVER_API
+void gst_rtsp_stream_set_bind_mcast_address (GstRTSPStream * stream, gboolean bind_mcast_addr);
+
+GST_RTSP_SERVER_API
+gboolean gst_rtsp_stream_is_bind_mcast_address (GstRTSPStream * stream);
+
+GST_RTSP_SERVER_API
gboolean gst_rtsp_stream_complete_stream (GstRTSPStream * stream, const GstRTSPTransport * transport);
GST_RTSP_SERVER_API
"user", NULL);
gst_rtsp_context_push_current (&ctx);
- expected_transport = "RTP/AVP;multicast;destination=233.252.0.1;"
- "ttl=1;port=5000-5001;mode=\"PLAY\"";
-
/* simple SETUP with a valid URI */
fail_unless (gst_rtsp_message_init_request (&request, GST_RTSP_SETUP,
"rtsp://localhost/test/stream=0") == GST_RTSP_OK);
mcast_transport_two_clients (gboolean shared, const gchar * transport1,
const gchar * expected_transport1, const gchar * addr1,
const gchar * transport2, const gchar * expected_transport2,
- const gchar * addr2)
+ const gchar * addr2, gboolean bind_mcast_address)
{
GstRTSPClient *client1, *client2;
GstRTSPMessage request = { 0, };
if (shared)
gst_rtsp_media_factory_set_shared (factory, TRUE);
gst_rtsp_media_factory_set_max_mcast_ttl (factory, 5);
+ gst_rtsp_media_factory_set_bind_mcast_address (factory, bind_mcast_address);
gst_rtsp_media_factory_set_launch (factory,
"audiotestsrc ! audio/x-raw,rate=44100 ! audioconvert ! rtpL16pay name=pay0");
address_pool = gst_rtsp_address_pool_new ();
mcast_transport_two_clients (TRUE, transport_client_1,
expected_transport_1, addr_client_1, transport_client_2,
- expected_transport_2, addr_client_2);
+ expected_transport_2, addr_client_2, FALSE);
}
GST_END_TEST;
mcast_transport_two_clients (FALSE, transport_client_1,
expected_transport_1, addr_client_1, transport_client_2,
- expected_transport_2, addr_client_2);
+ expected_transport_2, addr_client_2, FALSE);
+}
+
+GST_END_TEST;
+
+/* test if two multicast clients can choose the same ports but different
+ * multicast destinations
+ * CASE: media is not shared */
+GST_START_TEST (test_client_multicast_transport_specific_two_clients_same_ports)
+{
+ const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.1;"
+ "ttl=1;port=9000-9001;mode=\"PLAY\"";
+ const gchar *expected_transport_1 = transport_client_1;
+ const gchar *addr_client_1 = "233.252.0.1:9000";
+
+ const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=1;port=9000-9001;mode=\"PLAY\"";
+ const gchar *expected_transport_2 = transport_client_2;
+ const gchar *addr_client_2 = "233.252.0.2:9000";
+
+ /* configure the multicast socket to be bound to the requested multicast address instead of INADDR_ANY.
+ * The clients request the same rtp/rtcp borts and having the socket that are bound to ANY would result
+ * in bind() failure */
+ gboolean allow_bind_mcast_address = TRUE;
+
+ mcast_transport_two_clients (FALSE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2, allow_bind_mcast_address);
}
GST_END_TEST;
+/* test if two multicast clients can choose the same multicast destination but different
+ * ports
+ * CASE: media is not shared */
+GST_START_TEST
+ (test_client_multicast_transport_specific_two_clients_same_destination) {
+ const gchar *transport_client_1 = "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=1;port=9002-9003;mode=\"PLAY\"";
+ const gchar *expected_transport_1 = transport_client_1;
+ const gchar *addr_client_1 = "233.252.0.2:9002";
+
+ const gchar *transport_client_2 = "RTP/AVP;multicast;destination=233.252.0.2;"
+ "ttl=1;port=9004-9005;mode=\"PLAY\"";
+ const gchar *expected_transport_2 = transport_client_2;
+ const gchar *addr_client_2 = "233.252.0.2:9004";
+
+ mcast_transport_two_clients (FALSE, transport_client_1,
+ expected_transport_1, addr_client_1, transport_client_2,
+ expected_transport_2, addr_client_2, FALSE);
+}
+
+GST_END_TEST;
/* test if two multicast clients can choose the same transport settings.
* CASE: media is shared */
GST_START_TEST
mcast_transport_two_clients (TRUE, transport_client_1,
expected_transport_1, addr_client_1, transport_client_2,
- expected_transport_2, addr_client_2);
+ expected_transport_2, addr_client_2, FALSE);
}
GST_END_TEST;
mcast_transport_two_clients (TRUE, transport_client_1,
expected_transport_1, addr_client_1, transport_client_2,
- expected_transport_2, addr_client_2);
+ expected_transport_2, addr_client_2, FALSE);
}
GST_END_TEST;
mcast_transport_two_clients (TRUE, transport_client_1,
expected_transport_1, addr_client_1, transport_client_2,
- expected_transport_2, addr_client_2);
+ expected_transport_2, addr_client_2, FALSE);
}
GST_END_TEST;
mcast_transport_two_clients (TRUE, transport_client_1,
expected_transport_1, addr_client_1, transport_client_2,
- expected_transport_2, addr_client_2);
+ expected_transport_2, addr_client_2, FALSE);
}
GST_END_TEST;
mcast_transport_two_clients (TRUE, transport_client_1,
expected_transport_1, addr_client_1, transport_client_2,
- expected_transport_2, addr_client_2);
+ expected_transport_2, addr_client_2, FALSE);
}
GST_END_TEST;
mcast_transport_two_clients (TRUE, transport_client_1,
expected_transport_1, addr_client_1, transport_client_2,
- expected_transport_2, addr_client_2);
+ expected_transport_2, addr_client_2, FALSE);
}
GST_END_TEST;
tcase_add_test (tc,
test_client_multicast_transport_specific_two_clients_shared_media);
tcase_add_test (tc, test_client_multicast_transport_specific_two_clients);
+#ifndef G_OS_WIN32
+ tcase_add_test (tc,
+ test_client_multicast_transport_specific_two_clients_same_ports);
+#else
+ /* skip the test on windows as the test restricts the multicast sockets to multicast traffic only,
+ * by specifying the multicast IP as the bind address and this currently doesn't work on Windows */
+ tcase_skip_broken_test (tc,
+ test_client_multicast_transport_specific_two_clients_same_ports);
+#endif
+ tcase_add_test (tc,
+ test_client_multicast_transport_specific_two_clients_same_destination);
tcase_add_test (tc,
test_client_multicast_transport_specific_two_clients_shared_media_same_transport);
tcase_add_test (tc, test_client_multicast_two_clients_shared_media);
GST_END_TEST;
+
+GST_START_TEST (test_allow_bind_mcast)
+{
+ GstRTSPMediaFactory *factory;
+ GstRTSPMedia *media;
+ GstRTSPUrl *url;
+ GstRTSPStream *stream;
+
+ factory = gst_rtsp_media_factory_new ();
+ gst_rtsp_media_factory_set_shared (factory, TRUE);
+ fail_unless (gst_rtsp_url_parse ("rtsp://localhost:8554/test",
+ &url) == GST_RTSP_OK);
+
+ gst_rtsp_media_factory_set_launch (factory,
+ "( videotestsrc ! rtpvrawpay pt=96 name=pay0 "
+ " audiotestsrc ! audioconvert ! rtpL16pay name=pay1 )");
+
+ /* verify that by default binding sockets to multicast addresses is not enabled */
+ fail_unless (gst_rtsp_media_factory_is_bind_mcast_address (factory) == FALSE);
+
+ /* allow multicast sockets to be bound to multicast addresses */
+ gst_rtsp_media_factory_set_bind_mcast_address (factory, TRUE);
+ /* verify that the socket binding to multicast address has been enabled */
+ fail_unless (gst_rtsp_media_factory_is_bind_mcast_address (factory) == TRUE);
+
+ media = gst_rtsp_media_factory_construct (factory, url);
+ fail_unless (GST_IS_RTSP_MEDIA (media));
+
+ /* verify that the correct socket binding configuration has been propageted to the media */
+ fail_unless (gst_rtsp_media_is_bind_mcast_address (media) == TRUE);
+
+ fail_unless (gst_rtsp_media_n_streams (media) == 2);
+
+ /* verify that the correct socket binding configuration has been propageted to the media streams */
+ stream = gst_rtsp_media_get_stream (media, 0);
+ fail_unless (stream != NULL);
+ fail_unless (gst_rtsp_stream_is_bind_mcast_address (stream) == TRUE);
+
+ stream = gst_rtsp_media_get_stream (media, 1);
+ fail_unless (stream != NULL);
+ fail_unless (gst_rtsp_stream_is_bind_mcast_address (stream) == TRUE);
+
+ g_object_unref (media);
+ gst_rtsp_url_free (url);
+ g_object_unref (factory);
+}
+
+GST_END_TEST;
+
static Suite *
rtspmediafactory_suite (void)
{
tcase_add_test (tc, test_permissions);
tcase_add_test (tc, test_reset);
tcase_add_test (tc, test_mcast_ttl);
+ tcase_add_test (tc, test_allow_bind_mcast);
return s;
}