mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 20:42:30 +00:00
rtsp: add unit test
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=678076
This commit is contained in:
parent
36df0dd8be
commit
df54c553ae
4 changed files with 782 additions and 0 deletions
|
@ -44,6 +44,7 @@ AS_LIBTOOL(GST, 0, 0, 0)
|
|||
dnl *** required versions of GStreamer stuff ***
|
||||
GST_REQ=0.11.0
|
||||
GSTPB_REQ=0.11.0
|
||||
GSTPG_REQ=0.11.0
|
||||
|
||||
dnl *** autotools stuff ****
|
||||
|
||||
|
@ -142,6 +143,11 @@ GSTPB_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-base-$GST_API_VERSION --variabl
|
|||
AC_SUBST(GSTPB_PLUGINS_DIR)
|
||||
AC_MSG_NOTICE(Using GStreamer Base Plugins in $GSTPB_PLUGINS_DIR)
|
||||
|
||||
AG_GST_CHECK_GST_PLUGINS_GOOD($GST_API_VERSION, [$GSTPG_REQ], [yes])
|
||||
GSTPG_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-good-$GST_API_VERSION --variable pluginsdir`
|
||||
AC_SUBST(GSTPG_PLUGINS_DIR)
|
||||
AC_MSG_NOTICE(Using GStreamer Good Plugins in $GSTPG_PLUGINS_DIR)
|
||||
|
||||
AG_GST_CHECK_GST_CHECK($GST_API_VERSION, [$GST_REQ], no)
|
||||
|
||||
dnl FIXME: get rid of this by making sure gstreamer-check brings it in
|
||||
|
@ -250,6 +256,7 @@ gst/Makefile
|
|||
gst/rtsp-server/Makefile
|
||||
examples/Makefile
|
||||
tests/Makefile
|
||||
tests/check/Makefile
|
||||
bindings/Makefile
|
||||
bindings/vala/Makefile
|
||||
pkgconfig/Makefile
|
||||
|
|
|
@ -7,3 +7,14 @@ AM_LDFLAGS = \
|
|||
$(GST_LIBS) \
|
||||
$(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la
|
||||
|
||||
if HAVE_CHECK
|
||||
SUBDIRS_CHECK = check
|
||||
else
|
||||
SUBDIRS_CHECK =
|
||||
endif
|
||||
|
||||
SUBDIRS = \
|
||||
$(SUBDIRS_CHECK)
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
check
|
||||
|
|
54
tests/check/Makefile.am
Normal file
54
tests/check/Makefile.am
Normal file
|
@ -0,0 +1,54 @@
|
|||
include $(top_srcdir)/common/check.mak
|
||||
|
||||
CHECK_REGISTRY = $(top_builddir)/tests/check/test-registry.reg
|
||||
TEST_FILES_DIRECTORY = $(top_srcdir)/tests/files
|
||||
|
||||
REGISTRY_ENVIRONMENT = \
|
||||
GST_REGISTRY=$(CHECK_REGISTRY)
|
||||
|
||||
TESTS_ENVIRONMENT = \
|
||||
CK_DEFAULT_TIMEOUT=120 \
|
||||
GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \
|
||||
$(REGISTRY_ENVIRONMENT) \
|
||||
GST_PLUGIN_SYSTEM_PATH= \
|
||||
GST_PLUGIN_PATH=$(GST_PLUGINS_DIR):$(GSTPB_PLUGINS_DIR):$(GSTPG_PLUGINS_DIR) \
|
||||
GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base:gst-plugins-good"
|
||||
|
||||
|
||||
# ths core dumps of some machines have PIDs appended
|
||||
CLEANFILES = core.* test-registry.*
|
||||
|
||||
clean-local: clean-local-check
|
||||
|
||||
$(CHECK_REGISTRY):
|
||||
$(TESTS_ENVIRONMENT)
|
||||
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
check_PROGRAMS = \
|
||||
gst/rtspserver
|
||||
|
||||
# these tests don't even pass
|
||||
noinst_PROGRAMS =
|
||||
|
||||
AM_CFLAGS = $(GST_CFLAGS) $(GST_CHECK_CFLAGS) \
|
||||
-DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \
|
||||
-UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS
|
||||
AM_CXXFLAGS = $(GST_CXXFLAGS) $(GST_CHECK_CFLAGS) \
|
||||
-DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \
|
||||
-UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS
|
||||
LDADD = $(GST_LIBS) $(GST_CHECK_LIBS) $(GST_RTSP_SERVER_LIBS)
|
||||
|
||||
SUPPRESSIONS = $(top_srcdir)/common/gst.supp
|
||||
|
||||
gst_rtspserver_CFLAGS = \
|
||||
$(GST_PLUGINS_GOOD_CFLAGS) \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(GST_BASE_CFLAGS) \
|
||||
$(AM_CFLAGS)
|
||||
|
||||
gst_rtspserver_LDADD = \
|
||||
$(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \
|
||||
$(GST_PLUGINS_GOOD_LIBS) \
|
||||
$(GST_BASE_LIBS) -lgstrtsp-@GST_API_VERSION@ -lgstsdp-@GST_API_VERSION@ \
|
||||
$(LDADD)
|
710
tests/check/gst/rtspserver.c
Normal file
710
tests/check/gst/rtspserver.c
Normal file
|
@ -0,0 +1,710 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* unit test for GstRTSPServer
|
||||
*
|
||||
* Copyright (C) 2012 Axis Communications <dev-gstreamer at axis dot com>
|
||||
* @author David Svensson Fors <davidsf at axis dot com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/rtsp-server/rtsp-server.h>
|
||||
#include <gst/sdp/gstsdpmessage.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define VIDEO_PIPELINE "videotestsrc ! " \
|
||||
"video/x-raw,width=352,height=288 ! " \
|
||||
"rtpgstpay name=pay0 pt=96"
|
||||
#define AUDIO_PIPELINE "audiotestsrc ! " \
|
||||
"audio/x-raw,rate=8000 ! " \
|
||||
"rtpgstpay name=pay1 pt=97"
|
||||
|
||||
#define TEST_MOUNT_POINT "/test"
|
||||
#define TEST_PROTO "RTP/AVP"
|
||||
#define TEST_ENCODING "X-GST"
|
||||
#define TEST_CLOCK_RATE "90000"
|
||||
|
||||
/* tested rtsp server */
|
||||
static GstRTSPServer *server = NULL;
|
||||
|
||||
/* tcp port that the test server listens for rtsp requests on */
|
||||
static gint test_port = 0;
|
||||
|
||||
/* id of the server's source within the GMainContext */
|
||||
static guint source_id;
|
||||
|
||||
/* iterate the default main loop until there are no events to dispatch */
|
||||
static void
|
||||
iterate (void)
|
||||
{
|
||||
while (g_main_context_iteration (NULL, FALSE)) {
|
||||
GST_DEBUG ("iteration");
|
||||
}
|
||||
}
|
||||
|
||||
/* returns an unused port that can be used by the test */
|
||||
static int
|
||||
get_unused_port (gint type)
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addr_len;
|
||||
gint port;
|
||||
|
||||
/* create socket */
|
||||
fail_unless ((sock = socket (AF_INET, type, 0)) > 0);
|
||||
|
||||
/* pass port 0 to bind, which will bind to any free port */
|
||||
memset (&addr, 0, sizeof addr);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_port = htons (0);
|
||||
fail_unless (bind (sock, (struct sockaddr *) &addr, sizeof addr) == 0);
|
||||
|
||||
/* ask what port was bound using getsockname */
|
||||
addr_len = sizeof addr;
|
||||
memset (&addr, 0, addr_len);
|
||||
fail_unless (getsockname (sock, (struct sockaddr *) &addr, &addr_len) == 0);
|
||||
port = ntohs (addr.sin_port);
|
||||
|
||||
/* close the socket so the port gets unbound again (and can be used by the
|
||||
* test) */
|
||||
close (sock);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
/* returns TRUE if the given port is not currently bound */
|
||||
static gboolean
|
||||
port_is_unused (gint port, gint type)
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_in addr;
|
||||
gboolean is_bound;
|
||||
|
||||
/* create socket */
|
||||
fail_unless ((sock = socket (AF_INET, type, 0)) > 0);
|
||||
|
||||
/* check if the port is already bound by trying to bind to it (again) */
|
||||
memset (&addr, 0, sizeof addr);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_port = htons (port);
|
||||
is_bound = (bind (sock, (struct sockaddr *) &addr, sizeof addr) != 0);
|
||||
|
||||
/* close the socket, which will unbind if bound by our call to bind */
|
||||
close (sock);
|
||||
|
||||
return !is_bound;
|
||||
}
|
||||
|
||||
/* get a free rtp/rtcp client port pair */
|
||||
static void
|
||||
get_client_ports (GstRTSPRange * range)
|
||||
{
|
||||
gint rtp_port;
|
||||
gint rtcp_port;
|
||||
|
||||
/* get a pair of unused ports, where the rtp port is even */
|
||||
do {
|
||||
rtp_port = get_unused_port (SOCK_DGRAM);
|
||||
rtcp_port = rtp_port + 1;
|
||||
} while (rtp_port % 2 != 0 || !port_is_unused (rtcp_port, SOCK_DGRAM));
|
||||
range->min = rtp_port;
|
||||
range->max = rtcp_port;
|
||||
GST_DEBUG ("client_port=%d-%d", range->min, range->max);
|
||||
}
|
||||
|
||||
/* start the tested rtsp server */
|
||||
static void
|
||||
start_server ()
|
||||
{
|
||||
GstRTSPMediaMapping *mapping;
|
||||
gchar *service;
|
||||
GstRTSPMediaFactory *factory;
|
||||
|
||||
mapping = gst_rtsp_server_get_media_mapping (server);
|
||||
|
||||
factory = gst_rtsp_media_factory_new ();
|
||||
|
||||
gst_rtsp_media_factory_set_launch (factory,
|
||||
"( " VIDEO_PIPELINE " " AUDIO_PIPELINE " )");
|
||||
|
||||
gst_rtsp_media_mapping_add_factory (mapping, TEST_MOUNT_POINT, factory);
|
||||
g_object_unref (mapping);
|
||||
|
||||
/* set port */
|
||||
test_port = get_unused_port (SOCK_STREAM);
|
||||
service = g_strdup_printf ("%d", test_port);
|
||||
gst_rtsp_server_set_service (server, service);
|
||||
g_free (service);
|
||||
|
||||
/* attach to default main context */
|
||||
source_id = gst_rtsp_server_attach (server, NULL);
|
||||
fail_if (source_id == 0);
|
||||
|
||||
GST_DEBUG ("rtsp server listening on port %d", test_port);
|
||||
}
|
||||
|
||||
/* stop the tested rtsp server */
|
||||
static void
|
||||
stop_server ()
|
||||
{
|
||||
g_source_remove (source_id);
|
||||
source_id = 0;
|
||||
|
||||
GST_DEBUG ("rtsp server stopped");
|
||||
}
|
||||
|
||||
/* create an rtsp connection to the server on test_port */
|
||||
static GstRTSPConnection *
|
||||
connect_to_server (gint port, const gchar * mount_point)
|
||||
{
|
||||
GstRTSPConnection *conn = NULL;
|
||||
gchar *address;
|
||||
gchar *uri_string;
|
||||
GstRTSPUrl *url = NULL;
|
||||
|
||||
address = gst_rtsp_server_get_address (server);
|
||||
uri_string = g_strdup_printf ("rtsp://%s:%d%s", address, port, mount_point);
|
||||
g_free (address);
|
||||
gst_rtsp_url_parse (uri_string, &url);
|
||||
g_free (uri_string);
|
||||
|
||||
fail_unless (gst_rtsp_connection_create (url, &conn) == GST_RTSP_OK);
|
||||
gst_rtsp_url_free (url);
|
||||
|
||||
fail_unless (gst_rtsp_connection_connect (conn, NULL) == GST_RTSP_OK);
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
/* create an rtsp request */
|
||||
static GstRTSPMessage *
|
||||
create_request (GstRTSPConnection * conn, GstRTSPMethod method,
|
||||
const gchar * control)
|
||||
{
|
||||
GstRTSPMessage *request = NULL;
|
||||
gchar *base_uri;
|
||||
gchar *full_uri;
|
||||
|
||||
base_uri = gst_rtsp_url_get_request_uri (gst_rtsp_connection_get_url (conn));
|
||||
full_uri = g_strdup_printf ("%s/%s", base_uri, control ? control : "");
|
||||
g_free (base_uri);
|
||||
if (gst_rtsp_message_new_request (&request, method, full_uri) != GST_RTSP_OK) {
|
||||
GST_DEBUG ("failed to create request object");
|
||||
g_free (full_uri);
|
||||
return NULL;
|
||||
}
|
||||
g_free (full_uri);
|
||||
return request;
|
||||
}
|
||||
|
||||
/* send an rtsp request */
|
||||
static gboolean
|
||||
send_request (GstRTSPConnection * conn, GstRTSPMessage * request)
|
||||
{
|
||||
if (gst_rtsp_connection_send (conn, request, NULL) != GST_RTSP_OK) {
|
||||
GST_DEBUG ("failed to send request");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* read rtsp response. response must be freed by the caller */
|
||||
static GstRTSPMessage *
|
||||
read_response (GstRTSPConnection * conn)
|
||||
{
|
||||
GstRTSPMessage *response = NULL;
|
||||
|
||||
if (gst_rtsp_message_new (&response) != GST_RTSP_OK) {
|
||||
GST_DEBUG ("failed to create response object");
|
||||
return NULL;
|
||||
}
|
||||
if (gst_rtsp_connection_receive (conn, response, NULL) != GST_RTSP_OK) {
|
||||
GST_DEBUG ("failed to read response");
|
||||
gst_rtsp_message_free (response);
|
||||
return NULL;
|
||||
}
|
||||
fail_unless (gst_rtsp_message_get_type (response) ==
|
||||
GST_RTSP_MESSAGE_RESPONSE);
|
||||
return response;
|
||||
}
|
||||
|
||||
/* send an rtsp request and receive response. gchar** parameters are out
|
||||
* parameters that have to be freed by the caller */
|
||||
static GstRTSPStatusCode
|
||||
do_request (GstRTSPConnection * conn, GstRTSPMethod method,
|
||||
const gchar * control, const gchar * session_in, const gchar * transport_in,
|
||||
gchar ** content_type, gchar ** content_base, gchar ** body,
|
||||
gchar ** session_out, gchar ** transport_out)
|
||||
{
|
||||
GstRTSPMessage *request;
|
||||
GstRTSPMessage *response;
|
||||
GstRTSPStatusCode code;
|
||||
gchar *value;
|
||||
|
||||
/* create request */
|
||||
request = create_request (conn, method, control);
|
||||
|
||||
/* add headers */
|
||||
if (session_in) {
|
||||
gst_rtsp_message_add_header (request, GST_RTSP_HDR_SESSION, session_in);
|
||||
}
|
||||
if (transport_in) {
|
||||
gst_rtsp_message_add_header (request, GST_RTSP_HDR_TRANSPORT, transport_in);
|
||||
}
|
||||
|
||||
/* send request */
|
||||
fail_unless (send_request (conn, request));
|
||||
gst_rtsp_message_free (request);
|
||||
|
||||
iterate ();
|
||||
|
||||
/* read response */
|
||||
response = read_response (conn);
|
||||
|
||||
/* check status line */
|
||||
gst_rtsp_message_parse_response (response, &code, NULL, NULL);
|
||||
if (code != GST_RTSP_STS_OK) {
|
||||
gst_rtsp_message_free (response);
|
||||
return code;
|
||||
}
|
||||
|
||||
/* get information from response */
|
||||
if (content_type) {
|
||||
gst_rtsp_message_get_header (response, GST_RTSP_HDR_CONTENT_TYPE,
|
||||
&value, 0);
|
||||
*content_type = g_strdup (value);
|
||||
}
|
||||
if (content_base) {
|
||||
gst_rtsp_message_get_header (response, GST_RTSP_HDR_CONTENT_BASE,
|
||||
&value, 0);
|
||||
*content_base = g_strdup (value);
|
||||
}
|
||||
if (body) {
|
||||
*body = g_malloc (response->body_size + 1);
|
||||
strncpy (*body, (gchar *) response->body, response->body_size);
|
||||
}
|
||||
if (session_out) {
|
||||
gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION, &value, 0);
|
||||
if (session_in) {
|
||||
/* check that we got the same session back */
|
||||
fail_unless (!g_strcmp0 (value, session_in));
|
||||
}
|
||||
*session_out = g_strdup (value);
|
||||
}
|
||||
if (transport_out) {
|
||||
gst_rtsp_message_get_header (response, GST_RTSP_HDR_TRANSPORT, &value, 0);
|
||||
*transport_out = g_strdup (value);
|
||||
}
|
||||
|
||||
gst_rtsp_message_free (response);
|
||||
return code;
|
||||
}
|
||||
|
||||
/* send an rtsp request with a method and a session, and receive response */
|
||||
static GstRTSPStatusCode
|
||||
do_simple_request (GstRTSPConnection * conn, GstRTSPMethod method,
|
||||
const gchar * session)
|
||||
{
|
||||
return do_request (conn, method, NULL, session, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* send a DESCRIBE request and receive response. returns a received
|
||||
* GstSDPMessage that must be freed by the caller */
|
||||
static GstSDPMessage *
|
||||
do_describe (GstRTSPConnection * conn, const gchar * mount_point)
|
||||
{
|
||||
GstSDPMessage *sdp_message;
|
||||
gchar *content_type;
|
||||
gchar *content_base;
|
||||
gchar *body;
|
||||
gchar *address;
|
||||
gchar *expected_content_base;
|
||||
|
||||
/* send DESCRIBE request */
|
||||
fail_unless (do_request (conn, GST_RTSP_DESCRIBE, NULL, NULL, NULL,
|
||||
&content_type, &content_base, &body, NULL, NULL) == GST_RTSP_STS_OK);
|
||||
|
||||
/* check response values */
|
||||
fail_unless (!g_strcmp0 (content_type, "application/sdp"));
|
||||
address = gst_rtsp_server_get_address (server);
|
||||
expected_content_base =
|
||||
g_strdup_printf ("rtsp://%s:%d%s/", address, test_port, mount_point);
|
||||
fail_unless (!g_strcmp0 (content_base, expected_content_base));
|
||||
|
||||
/* create sdp message */
|
||||
fail_unless (gst_sdp_message_new (&sdp_message) == GST_SDP_OK);
|
||||
fail_unless (gst_sdp_message_parse_buffer ((guint8 *) body,
|
||||
strlen (body), sdp_message) == GST_SDP_OK);
|
||||
|
||||
/* clean up */
|
||||
g_free (content_type);
|
||||
g_free (content_base);
|
||||
g_free (body);
|
||||
g_free (address);
|
||||
g_free (expected_content_base);
|
||||
|
||||
return sdp_message;
|
||||
}
|
||||
|
||||
/* send a SETUP request and receive response. if *session is not NULL,
|
||||
* it is used in the request. otherwise, *session is set to a returned
|
||||
* session string that must be freed by the caller. the returned
|
||||
* transport must be freed by the caller. */
|
||||
static GstRTSPStatusCode
|
||||
do_setup (GstRTSPConnection * conn, const gchar * control,
|
||||
const GstRTSPRange * client_ports, gchar ** session,
|
||||
GstRTSPTransport ** transport)
|
||||
{
|
||||
GstRTSPStatusCode code;
|
||||
gchar *session_in = NULL;
|
||||
gchar *transport_string_in = NULL;
|
||||
gchar **session_out = NULL;
|
||||
gchar *transport_string_out = NULL;
|
||||
|
||||
/* prepare and send SETUP request */
|
||||
if (session) {
|
||||
if (*session) {
|
||||
session_in = *session;
|
||||
} else {
|
||||
session_out = session;
|
||||
}
|
||||
}
|
||||
transport_string_in =
|
||||
g_strdup_printf (TEST_PROTO ";unicast;client_port=%d-%d",
|
||||
client_ports->min, client_ports->max);
|
||||
code =
|
||||
do_request (conn, GST_RTSP_SETUP, control, session_in,
|
||||
transport_string_in, NULL, NULL, NULL, session_out,
|
||||
&transport_string_out);
|
||||
g_free (transport_string_in);
|
||||
|
||||
if (transport_string_out) {
|
||||
/* create transport */
|
||||
fail_unless (gst_rtsp_transport_new (transport) == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_transport_parse (transport_string_out,
|
||||
*transport) == GST_RTSP_OK);
|
||||
g_free (transport_string_out);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/* fixture setup function */
|
||||
static void
|
||||
setup (void)
|
||||
{
|
||||
server = gst_rtsp_server_new ();
|
||||
}
|
||||
|
||||
/* fixture clean-up function */
|
||||
static void
|
||||
teardown (void)
|
||||
{
|
||||
if (server) {
|
||||
g_object_unref (server);
|
||||
server = NULL;
|
||||
}
|
||||
test_port = 0;
|
||||
}
|
||||
|
||||
GST_START_TEST (test_connect)
|
||||
{
|
||||
GstRTSPConnection *conn;
|
||||
|
||||
start_server ();
|
||||
|
||||
/* connect to server */
|
||||
conn = connect_to_server (test_port, TEST_MOUNT_POINT);
|
||||
|
||||
/* clean up */
|
||||
gst_rtsp_connection_free (conn);
|
||||
stop_server ();
|
||||
|
||||
/* iterate so the clean-up can finish */
|
||||
iterate ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_describe)
|
||||
{
|
||||
GstRTSPConnection *conn;
|
||||
GstSDPMessage *sdp_message = NULL;
|
||||
const GstSDPMedia *sdp_media;
|
||||
gint32 format;
|
||||
gchar *expected_rtpmap;
|
||||
const gchar *rtpmap;
|
||||
const gchar *control_video;
|
||||
const gchar *control_audio;
|
||||
|
||||
start_server ();
|
||||
|
||||
conn = connect_to_server (test_port, TEST_MOUNT_POINT);
|
||||
|
||||
/* send DESCRIBE request */
|
||||
sdp_message = do_describe (conn, TEST_MOUNT_POINT);
|
||||
|
||||
fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
|
||||
|
||||
/* check video sdp */
|
||||
sdp_media = gst_sdp_message_get_media (sdp_message, 0);
|
||||
fail_unless (!g_strcmp0 (gst_sdp_media_get_proto (sdp_media), TEST_PROTO));
|
||||
fail_unless (gst_sdp_media_formats_len (sdp_media) == 1);
|
||||
sscanf (gst_sdp_media_get_format (sdp_media, 0), "%" G_GINT32_FORMAT,
|
||||
&format);
|
||||
expected_rtpmap =
|
||||
g_strdup_printf ("%d " TEST_ENCODING "/" TEST_CLOCK_RATE, format);
|
||||
rtpmap = gst_sdp_media_get_attribute_val (sdp_media, "rtpmap");
|
||||
fail_unless (!g_strcmp0 (rtpmap, expected_rtpmap));
|
||||
g_free (expected_rtpmap);
|
||||
control_video = gst_sdp_media_get_attribute_val (sdp_media, "control");
|
||||
fail_unless (!g_strcmp0 (control_video, "stream=0"));
|
||||
|
||||
/* check audio sdp */
|
||||
sdp_media = gst_sdp_message_get_media (sdp_message, 1);
|
||||
fail_unless (!g_strcmp0 (gst_sdp_media_get_proto (sdp_media), TEST_PROTO));
|
||||
fail_unless (gst_sdp_media_formats_len (sdp_media) == 1);
|
||||
sscanf (gst_sdp_media_get_format (sdp_media, 0), "%" G_GINT32_FORMAT,
|
||||
&format);
|
||||
expected_rtpmap =
|
||||
g_strdup_printf ("%d " TEST_ENCODING "/" TEST_CLOCK_RATE, format);
|
||||
rtpmap = gst_sdp_media_get_attribute_val (sdp_media, "rtpmap");
|
||||
fail_unless (!g_strcmp0 (rtpmap, expected_rtpmap));
|
||||
g_free (expected_rtpmap);
|
||||
control_audio = gst_sdp_media_get_attribute_val (sdp_media, "control");
|
||||
fail_unless (!g_strcmp0 (control_audio, "stream=1"));
|
||||
|
||||
/* clean up and iterate so the clean-up can finish */
|
||||
gst_sdp_message_free (sdp_message);
|
||||
gst_rtsp_connection_free (conn);
|
||||
stop_server ();
|
||||
iterate ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_describe_non_existing_mount_point)
|
||||
{
|
||||
GstRTSPConnection *conn;
|
||||
|
||||
start_server ();
|
||||
|
||||
/* send DESCRIBE request for a non-existing mount point
|
||||
* and check that we get a 404 Not Found */
|
||||
conn = connect_to_server (test_port, "/non-existing");
|
||||
fail_unless (do_simple_request (conn, GST_RTSP_DESCRIBE, NULL)
|
||||
== GST_RTSP_STS_NOT_FOUND);
|
||||
|
||||
/* clean up and iterate so the clean-up can finish */
|
||||
gst_rtsp_connection_free (conn);
|
||||
stop_server ();
|
||||
iterate ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_setup)
|
||||
{
|
||||
GstRTSPConnection *conn;
|
||||
GstSDPMessage *sdp_message = NULL;
|
||||
const GstSDPMedia *sdp_media;
|
||||
const gchar *video_control;
|
||||
const gchar *audio_control;
|
||||
GstRTSPRange client_ports;
|
||||
gchar *session = NULL;
|
||||
GstRTSPTransport *video_transport = NULL;
|
||||
GstRTSPTransport *audio_transport = NULL;
|
||||
|
||||
start_server ();
|
||||
|
||||
conn = connect_to_server (test_port, TEST_MOUNT_POINT);
|
||||
|
||||
sdp_message = do_describe (conn, TEST_MOUNT_POINT);
|
||||
|
||||
/* get control strings from DESCRIBE response */
|
||||
fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
|
||||
sdp_media = gst_sdp_message_get_media (sdp_message, 0);
|
||||
video_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
|
||||
sdp_media = gst_sdp_message_get_media (sdp_message, 1);
|
||||
audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
|
||||
|
||||
get_client_ports (&client_ports);
|
||||
|
||||
/* send SETUP request for video */
|
||||
fail_unless (do_setup (conn, video_control, &client_ports, &session,
|
||||
&video_transport) == GST_RTSP_STS_OK);
|
||||
GST_DEBUG ("set up video %s, got session '%s'", video_control, session);
|
||||
|
||||
/* check response from SETUP */
|
||||
fail_unless (video_transport->trans == GST_RTSP_TRANS_RTP);
|
||||
fail_unless (video_transport->profile == GST_RTSP_PROFILE_AVP);
|
||||
fail_unless (video_transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP);
|
||||
fail_unless (video_transport->mode_play);
|
||||
gst_rtsp_transport_free (video_transport);
|
||||
|
||||
/* send SETUP request for audio */
|
||||
fail_unless (do_setup (conn, audio_control, &client_ports, &session,
|
||||
&audio_transport) == GST_RTSP_STS_OK);
|
||||
GST_DEBUG ("set up audio %s with session '%s'", audio_control, session);
|
||||
|
||||
/* check response from SETUP */
|
||||
fail_unless (audio_transport->trans == GST_RTSP_TRANS_RTP);
|
||||
fail_unless (audio_transport->profile == GST_RTSP_PROFILE_AVP);
|
||||
fail_unless (audio_transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP);
|
||||
fail_unless (audio_transport->mode_play);
|
||||
gst_rtsp_transport_free (audio_transport);
|
||||
|
||||
/* clean up and iterate so the clean-up can finish */
|
||||
g_free (session);
|
||||
gst_sdp_message_free (sdp_message);
|
||||
gst_rtsp_connection_free (conn);
|
||||
stop_server ();
|
||||
iterate ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_setup_non_existing_stream)
|
||||
{
|
||||
GstRTSPConnection *conn;
|
||||
GstRTSPRange client_ports;
|
||||
|
||||
start_server ();
|
||||
|
||||
conn = connect_to_server (test_port, TEST_MOUNT_POINT);
|
||||
|
||||
get_client_ports (&client_ports);
|
||||
|
||||
/* send SETUP request with a non-existing stream and check that we get a
|
||||
* 404 Not Found */
|
||||
fail_unless (do_setup (conn, "stream=7", &client_ports, NULL,
|
||||
NULL) == GST_RTSP_STS_NOT_FOUND);
|
||||
|
||||
/* clean up and iterate so the clean-up can finish */
|
||||
gst_rtsp_connection_free (conn);
|
||||
stop_server ();
|
||||
iterate ();
|
||||
|
||||
/* need to unref the server here, otherwise threads will remain
|
||||
* and teardown won't be run */
|
||||
g_object_unref (server);
|
||||
server = NULL;
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_play)
|
||||
{
|
||||
GstRTSPConnection *conn;
|
||||
GstSDPMessage *sdp_message = NULL;
|
||||
const GstSDPMedia *sdp_media;
|
||||
const gchar *video_control;
|
||||
const gchar *audio_control;
|
||||
GstRTSPRange client_port;
|
||||
gchar *session = NULL;
|
||||
GstRTSPTransport *video_transport = NULL;
|
||||
GstRTSPTransport *audio_transport = NULL;
|
||||
|
||||
start_server ();
|
||||
|
||||
conn = connect_to_server (test_port, TEST_MOUNT_POINT);
|
||||
|
||||
sdp_message = do_describe (conn, TEST_MOUNT_POINT);
|
||||
|
||||
/* get control strings from DESCRIBE response */
|
||||
fail_unless (gst_sdp_message_medias_len (sdp_message) == 2);
|
||||
sdp_media = gst_sdp_message_get_media (sdp_message, 0);
|
||||
video_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
|
||||
sdp_media = gst_sdp_message_get_media (sdp_message, 1);
|
||||
audio_control = gst_sdp_media_get_attribute_val (sdp_media, "control");
|
||||
|
||||
get_client_ports (&client_port);
|
||||
|
||||
/* do SETUP for video and audio */
|
||||
fail_unless (do_setup (conn, video_control, &client_port, &session,
|
||||
&video_transport) == GST_RTSP_STS_OK);
|
||||
fail_unless (do_setup (conn, audio_control, &client_port, &session,
|
||||
&audio_transport) == GST_RTSP_STS_OK);
|
||||
|
||||
/* send PLAY request and check that we get 200 OK */
|
||||
fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
|
||||
session) == GST_RTSP_STS_OK);
|
||||
|
||||
/* send TEARDOWN request and check that we get 200 OK */
|
||||
fail_unless (do_simple_request (conn, GST_RTSP_TEARDOWN,
|
||||
session) == GST_RTSP_STS_OK);
|
||||
|
||||
/* clean up and iterate so the clean-up can finish */
|
||||
g_free (session);
|
||||
gst_rtsp_transport_free (video_transport);
|
||||
gst_rtsp_transport_free (audio_transport);
|
||||
gst_sdp_message_free (sdp_message);
|
||||
gst_rtsp_connection_free (conn);
|
||||
stop_server ();
|
||||
iterate ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_play_without_session)
|
||||
{
|
||||
GstRTSPConnection *conn;
|
||||
|
||||
start_server ();
|
||||
|
||||
conn = connect_to_server (test_port, TEST_MOUNT_POINT);
|
||||
|
||||
/* send PLAY request without a session and check that we get a
|
||||
* 454 Session Not Found */
|
||||
fail_unless (do_simple_request (conn, GST_RTSP_PLAY,
|
||||
NULL) == GST_RTSP_STS_SESSION_NOT_FOUND);
|
||||
|
||||
/* clean up and iterate so the clean-up can finish */
|
||||
gst_rtsp_connection_free (conn);
|
||||
stop_server ();
|
||||
iterate ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
rtspserver_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("rtspserver");
|
||||
TCase *tc = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc);
|
||||
tcase_add_checked_fixture (tc, setup, teardown);
|
||||
tcase_set_timeout (tc, 20);
|
||||
tcase_add_test (tc, test_connect);
|
||||
tcase_add_test (tc, test_describe);
|
||||
tcase_add_test (tc, test_describe_non_existing_mount_point);
|
||||
tcase_add_test (tc, test_setup);
|
||||
tcase_add_test (tc, test_setup_non_existing_stream);
|
||||
tcase_add_test (tc, test_play);
|
||||
tcase_add_test (tc, test_play_without_session);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (rtspserver);
|
Loading…
Reference in a new issue