mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-31 19:42:26 +00:00
rtspsink: Add rtspclientsink element
Add an rtspclientsink element that accepts streams for which there is a registered payloader and sends them to an RTSP server using RECORD. Sending is synchronised to the pipeline clock. Payload-types are automatically selected. The 'new-payloader' signal is fired for custom configuration of payloaders when they are created. Can now stream a movie like this: receiver: ./test-record "( decodebin name=depay0 ! videoconvert ! autovideosink \ decodebin name=depay1 ! audioconvert ! autoaudiosink )" sender: gst-launch-1.0 filesrc location=file-with-aac-and-h264.mp4 ! qtdemux name=d ! \ queue ! aacparse ! rtspclientsink location=rtsp://127.0.0.1:8554/test name=s \ https://bugzilla.gnome.org/show_bug.cgi?id=758180
This commit is contained in:
parent
b6ca057c72
commit
f54dd50203
9 changed files with 5428 additions and 4 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -62,6 +62,7 @@ stamp-h.in
|
|||
/tests/check/gst/stream
|
||||
/tests/check/gst/threadpool
|
||||
/tests/check/gst/token
|
||||
/tests/check/gst/rtspclientsink
|
||||
/tests/check/test-registry.reg
|
||||
/tests/test-reuse
|
||||
|
||||
|
|
28
configure.ac
28
configure.ac
|
@ -170,6 +170,8 @@ AC_MSG_NOTICE(Using GStreamer Core Plugins in $GST_PLUGINS_DIR)
|
|||
|
||||
AG_GST_CHECK_GST_BASE($GST_API_VERSION, [$GST_REQ], [yes])
|
||||
|
||||
AG_GST_CHECK_GST_NET($GST_API_VERSION, [$GST_REQ], yes)
|
||||
|
||||
AG_GST_CHECK_GST_PLUGINS_BASE($GST_API_VERSION, [$GSTPB_REQ], [yes])
|
||||
GSTPB_PLUGINS_DIR=`$PKG_CONFIG gstreamer-plugins-base-$GST_API_VERSION --variable pluginsdir`
|
||||
AC_SUBST(GSTPB_PLUGINS_DIR)
|
||||
|
@ -218,6 +220,31 @@ AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO],
|
|||
["${srcdir}/gst-rtsp-server.doap"],
|
||||
[$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO])
|
||||
|
||||
dnl build static plugins or not
|
||||
AC_MSG_CHECKING([whether to build static plugins or not])
|
||||
AC_ARG_ENABLE(
|
||||
static-plugins,
|
||||
AC_HELP_STRING(
|
||||
[--enable-static-plugins],
|
||||
[build static plugins @<:@default=no@:>@]),
|
||||
[AS_CASE(
|
||||
[$enableval], [no], [], [yes], [],
|
||||
[AC_MSG_ERROR([bad value "$enableval" for --enable-static-plugins])])],
|
||||
[enable_static_plugins=no])
|
||||
AC_MSG_RESULT([$enable_static_plugins])
|
||||
if test "x$enable_static_plugins" = xyes; then
|
||||
AC_DEFINE(GST_PLUGIN_BUILD_STATIC, 1,
|
||||
[Define if static plugins should be built])
|
||||
GST_PLUGIN_LIBTOOLFLAGS=""
|
||||
else
|
||||
GST_PLUGIN_LIBTOOLFLAGS="--tag=disable-static"
|
||||
fi
|
||||
AC_SUBST(GST_PLUGIN_LIBTOOLFLAGS)
|
||||
AM_CONDITIONAL(GST_PLUGIN_BUILD_STATIC, test "x$enable_static_plugins" = "xyes")
|
||||
|
||||
GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^[_]*gst_plugin_.*' $GST_ALL_LDFLAGS"
|
||||
AC_SUBST(GST_PLUGIN_LDFLAGS)
|
||||
|
||||
# set by AG_GST_PARSE_SUBSYSTEM_DISABLES above
|
||||
dnl make sure it doesn't complain about unused variables if debugging is disabled
|
||||
NO_WARNINGS=""
|
||||
|
@ -324,6 +351,7 @@ common/Makefile
|
|||
common/m4/Makefile
|
||||
gst/Makefile
|
||||
gst/rtsp-server/Makefile
|
||||
gst/rtsp-sink/Makefile
|
||||
examples/Makefile
|
||||
tests/Makefile
|
||||
tests/check/Makefile
|
||||
|
|
|
@ -1 +1 @@
|
|||
SUBDIRS = rtsp-server
|
||||
SUBDIRS = rtsp-server rtsp-sink
|
||||
|
|
18
gst/rtsp-sink/Makefile.am
Normal file
18
gst/rtsp-sink/Makefile.am
Normal file
|
@ -0,0 +1,18 @@
|
|||
plugin_LTLIBRARIES = libgstrtspclientsink.la
|
||||
|
||||
libgstrtspclientsink_la_SOURCES = gstrtspclientsink.c plugin.c
|
||||
|
||||
libgstrtspclientsink_la_CFLAGS = -I$(top_srcdir) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(GIO_CFLAGS)
|
||||
|
||||
# FIXME: Hack to avoid having to add GETTEXT_PACKAGE to gst-rtsp
|
||||
libgstrtspclientsink_la_CFLAGS += -D"GETTEXT_PACKAGE=gst-rtsp-server-1.0"
|
||||
|
||||
libgstrtspclientsink_la_LIBADD = $(top_builddir)/gst/rtsp-server/libgstrtspserver-@GST_API_VERSION@.la \
|
||||
$(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) \
|
||||
-lgstrtp-@GST_API_VERSION@ -lgstrtsp-@GST_API_VERSION@ \
|
||||
-lgstsdp-@GST_API_VERSION@ $(GST_NET_LIBS) $(GST_LIBS) \
|
||||
$(GIO_LIBS)
|
||||
libgstrtspclientsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgstrtspclientsink_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
|
||||
|
||||
noinst_HEADERS = gstrtspclientsink.h
|
4885
gst/rtsp-sink/gstrtspclientsink.c
Normal file
4885
gst/rtsp-sink/gstrtspclientsink.c
Normal file
File diff suppressed because it is too large
Load diff
244
gst/rtsp-sink/gstrtspclientsink.h
Normal file
244
gst/rtsp-sink/gstrtspclientsink.h
Normal file
|
@ -0,0 +1,244 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* <2006> Wim Taymans <wim@fluendo.com>
|
||||
* <2015> Jan Schmidt <jan at centricular 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., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
/*
|
||||
* Unless otherwise indicated, Source Code is licensed under MIT license.
|
||||
* See further explanation attached in License Statement (distributed in the file
|
||||
* LICENSE).
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __GST_RTSP_CLIENT_SINK_H__
|
||||
#define __GST_RTSP_CLIENT_SINK_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#include <gst/rtsp-server/rtsp-stream.h>
|
||||
#include <gst/rtsp/rtsp.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#define GST_TYPE_RTSP_CLIENT_SINK \
|
||||
(gst_rtsp_client_sink_get_type())
|
||||
#define GST_RTSP_CLIENT_SINK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTSP_CLIENT_SINK,GstRTSPClientSink))
|
||||
#define GST_RTSP_CLIENT_SINK_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTSP_CLIENT_SINK,GstRTSPClientSinkClass))
|
||||
#define GST_IS_RTSP_CLIENT_SINK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTSP_CLIENT_SINK))
|
||||
#define GST_IS_RTSP_CLIENT_SINK_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTSP_CLIENT_SINK))
|
||||
#define GST_RTSP_CLIENT_SINK_CAST(obj) \
|
||||
((GstRTSPClientSink *)(obj))
|
||||
|
||||
typedef struct _GstRTSPClientSink GstRTSPClientSink;
|
||||
typedef struct _GstRTSPClientSinkClass GstRTSPClientSinkClass;
|
||||
|
||||
#define GST_RTSP_STATE_GET_LOCK(rtsp) (&GST_RTSP_CLIENT_SINK_CAST(rtsp)->state_rec_lock)
|
||||
#define GST_RTSP_STATE_LOCK(rtsp) (g_rec_mutex_lock (GST_RTSP_STATE_GET_LOCK(rtsp)))
|
||||
#define GST_RTSP_STATE_UNLOCK(rtsp) (g_rec_mutex_unlock (GST_RTSP_STATE_GET_LOCK(rtsp)))
|
||||
|
||||
#define GST_RTSP_STREAM_GET_LOCK(rtsp) (&GST_RTSP_CLIENT_SINK_CAST(rtsp)->stream_rec_lock)
|
||||
#define GST_RTSP_STREAM_LOCK(rtsp) (g_rec_mutex_lock (GST_RTSP_STREAM_GET_LOCK(rtsp)))
|
||||
#define GST_RTSP_STREAM_UNLOCK(rtsp) (g_rec_mutex_unlock (GST_RTSP_STREAM_GET_LOCK(rtsp)))
|
||||
|
||||
typedef struct _GstRTSPConnInfo GstRTSPConnInfo;
|
||||
|
||||
struct _GstRTSPConnInfo {
|
||||
gchar *location;
|
||||
GstRTSPUrl *url;
|
||||
gchar *url_str;
|
||||
GstRTSPConnection *connection;
|
||||
gboolean connected;
|
||||
gboolean flushing;
|
||||
};
|
||||
|
||||
typedef struct _GstRTSPStreamInfo GstRTSPStreamInfo;
|
||||
typedef struct _GstRTSPStreamContext GstRTSPStreamContext;
|
||||
|
||||
struct _GstRTSPStreamContext {
|
||||
GstRTSPClientSink *parent;
|
||||
|
||||
guint index;
|
||||
/* Index of the SDPMedia in the stored SDP */
|
||||
guint sdp_index;
|
||||
|
||||
GstElement *payloader;
|
||||
guint payloader_block_id;
|
||||
gboolean prerolled;
|
||||
|
||||
/* Stream management object */
|
||||
GstRTSPStream *stream;
|
||||
gboolean joined;
|
||||
|
||||
/* Secure profile key mgmt */
|
||||
GstCaps *srtcpparams;
|
||||
|
||||
/* per stream connection */
|
||||
GstRTSPConnInfo conninfo;
|
||||
/* For interleaved mode */
|
||||
guint8 channel[2];
|
||||
|
||||
GstRTSPStreamTransport *stream_transport;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstRTSPNatMethod:
|
||||
* @GST_RTSP_NAT_NONE: none
|
||||
* @GST_RTSP_NAT_DUMMY: send dummy packets
|
||||
*
|
||||
* Different methods for trying to traverse firewalls.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GST_RTSP_NAT_NONE,
|
||||
GST_RTSP_NAT_DUMMY
|
||||
} GstRTSPNatMethod;
|
||||
|
||||
struct _GstRTSPClientSink {
|
||||
GstBin parent;
|
||||
|
||||
/* task and mutex for interleaved mode */
|
||||
gboolean interleaved;
|
||||
GstTask *task;
|
||||
GRecMutex stream_rec_lock;
|
||||
GstSegment segment;
|
||||
gint free_channel;
|
||||
|
||||
/* UDP mode loop */
|
||||
gint pending_cmd;
|
||||
gint busy_cmd;
|
||||
gboolean ignore_timeout;
|
||||
gboolean open_error;
|
||||
|
||||
/* mutex for protecting state changes */
|
||||
GRecMutex state_rec_lock;
|
||||
|
||||
GstSDPMessage *uri_sdp;
|
||||
gboolean from_sdp;
|
||||
|
||||
/* properties */
|
||||
GstRTSPLowerTrans protocols;
|
||||
gboolean debug;
|
||||
guint retry;
|
||||
guint64 udp_timeout;
|
||||
GTimeVal tcp_timeout;
|
||||
GTimeVal *ptcp_timeout;
|
||||
guint latency;
|
||||
gboolean do_rtsp_keep_alive;
|
||||
gchar *proxy_host;
|
||||
guint proxy_port;
|
||||
gchar *proxy_user; /* from url or property */
|
||||
gchar *proxy_passwd; /* from url or property */
|
||||
gchar *prop_proxy_id; /* set via property */
|
||||
gchar *prop_proxy_pw; /* set via property */
|
||||
guint rtp_blocksize;
|
||||
gchar *user_id;
|
||||
gchar *user_pw;
|
||||
GstRTSPRange client_port_range;
|
||||
gint udp_buffer_size;
|
||||
gboolean udp_reconnect;
|
||||
gchar *multi_iface;
|
||||
gboolean ntp_sync;
|
||||
gboolean use_pipeline_clock;
|
||||
GstStructure *sdes;
|
||||
GTlsCertificateFlags tls_validation_flags;
|
||||
GTlsDatabase *tls_database;
|
||||
GTlsInteraction *tls_interaction;
|
||||
gint ntp_time_source;
|
||||
gchar *user_agent;
|
||||
|
||||
/* state */
|
||||
GstRTSPState state;
|
||||
gchar *content_base;
|
||||
GstRTSPLowerTrans cur_protocols;
|
||||
gboolean tried_url_auth;
|
||||
gchar *addr;
|
||||
gboolean need_redirect;
|
||||
GstRTSPTimeRange *range;
|
||||
gchar *control;
|
||||
guint next_port_num;
|
||||
GstClock *provided_clock;
|
||||
|
||||
/* supported methods */
|
||||
gint methods;
|
||||
|
||||
/* session management */
|
||||
GstRTSPConnInfo conninfo;
|
||||
|
||||
/* Everything goes in an internal
|
||||
* locked-state bin */
|
||||
GstBin *internal_bin;
|
||||
/* Set to true when internal bin state
|
||||
* >= PAUSED */
|
||||
gboolean prerolled;
|
||||
|
||||
/* TRUE if we posted async-start */
|
||||
gboolean in_async;
|
||||
|
||||
/* TRUE when stream info has been collected */
|
||||
gboolean streams_collected;
|
||||
|
||||
guint next_pad_id;
|
||||
gint next_dyn_pt;
|
||||
|
||||
GstElement *rtpbin;
|
||||
|
||||
GList *contexts;
|
||||
GstSDPMessage cursdp;
|
||||
|
||||
GMutex send_lock;
|
||||
|
||||
GMutex preroll_lock;
|
||||
GCond preroll_cond;
|
||||
|
||||
GstClockTime rtx_time;
|
||||
|
||||
GstRTSPProfile profiles;
|
||||
gchar *server_ip;
|
||||
};
|
||||
|
||||
struct _GstRTSPClientSinkClass {
|
||||
GstBinClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_rtsp_client_sink_get_type(void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_RTSP_CLIENT_SINK_H__ */
|
26
gst/rtsp-sink/plugin.c
Normal file
26
gst/rtsp-sink/plugin.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gstrtspclientsink.h"
|
||||
|
||||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
#ifdef ENABLE_NLS
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
#endif /* ENABLE_NLS */
|
||||
|
||||
if (!gst_element_register (plugin, "rtspclientsink", GST_RANK_NONE,
|
||||
GST_TYPE_RTSP_CLIENT_SINK))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
||||
GST_VERSION_MINOR,
|
||||
rtspclientsink,
|
||||
"RTSP client sink element",
|
||||
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|
|
@ -11,8 +11,8 @@ AM_TESTS_ENVIRONMENT = \
|
|||
GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \
|
||||
$(REGISTRY_ENVIRONMENT) \
|
||||
GST_PLUGIN_SYSTEM_PATH_1_0= \
|
||||
GST_PLUGIN_PATH_1_0=$(GST_PLUGINS_DIR):$(GSTPB_PLUGINS_DIR):$(GSTPG_PLUGINS_DIR):$(GSTPD_PLUGINS_DIR) \
|
||||
GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base:gst-plugins-good:gst-plugins-bad"
|
||||
GST_PLUGIN_PATH_1_0=$(GST_PLUGINS_DIR):$(GSTPB_PLUGINS_DIR):$(GSTPG_PLUGINS_DIR):$(GSTPD_PLUGINS_DIR):$(top_builddir)/gst \
|
||||
GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base:gst-plugins-good:gst-plugins-bad:gst-rtsp-server"
|
||||
|
||||
|
||||
# ths core dumps of some machines have PIDs appended
|
||||
|
@ -37,7 +37,8 @@ check_PROGRAMS = \
|
|||
gst/permissions \
|
||||
gst/token \
|
||||
gst/sessionmedia \
|
||||
gst/sessionpool
|
||||
gst/sessionpool \
|
||||
gst/rtspclientsink
|
||||
|
||||
# these tests don't even pass
|
||||
noinst_PROGRAMS =
|
||||
|
|
221
tests/check/gst/rtspclientsink.c
Normal file
221
tests/check/gst/rtspclientsink.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
/* GStreamer unit test for rtspclientsink
|
||||
* Copyright (C) 2012 Axis Communications <dev-gstreamer at axis dot com>
|
||||
* @author David Svensson Fors <davidsf at axis dot com>
|
||||
* Copyright (C) 2015 Centricular Ltd
|
||||
* @author Tim-Philipp Müller <tim@centricular.com>
|
||||
* @author Jan Schmidt <jan@centricular.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., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/sdp/gstsdpmessage.h>
|
||||
#include <gst/rtp/gstrtpbuffer.h>
|
||||
#include <gst/rtp/gstrtcpbuffer.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "rtsp-server.h"
|
||||
|
||||
#define TEST_MOUNT_POINT "/test"
|
||||
|
||||
/* 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 context until there are no events to dispatch */
|
||||
static void
|
||||
iterate (void)
|
||||
{
|
||||
while (g_main_context_iteration (NULL, FALSE)) {
|
||||
GST_DEBUG ("iteration");
|
||||
}
|
||||
}
|
||||
|
||||
/* start the testing rtsp server for RECORD mode */
|
||||
static GstRTSPMediaFactory *
|
||||
start_record_server (const gchar * launch_line)
|
||||
{
|
||||
GstRTSPMediaFactory *factory;
|
||||
GstRTSPMountPoints *mounts;
|
||||
gchar *service;
|
||||
|
||||
mounts = gst_rtsp_server_get_mount_points (server);
|
||||
|
||||
factory = gst_rtsp_media_factory_new ();
|
||||
|
||||
gst_rtsp_media_factory_set_transport_mode (factory,
|
||||
GST_RTSP_TRANSPORT_MODE_RECORD);
|
||||
gst_rtsp_media_factory_set_launch (factory, launch_line);
|
||||
gst_rtsp_mount_points_add_factory (mounts, TEST_MOUNT_POINT, factory);
|
||||
g_object_unref (mounts);
|
||||
|
||||
/* set port to any */
|
||||
gst_rtsp_server_set_service (server, "0");
|
||||
|
||||
/* attach to default main context */
|
||||
source_id = gst_rtsp_server_attach (server, NULL);
|
||||
fail_if (source_id == 0);
|
||||
|
||||
/* get port */
|
||||
service = gst_rtsp_server_get_service (server);
|
||||
test_port = atoi (service);
|
||||
fail_unless (test_port != 0);
|
||||
g_free (service);
|
||||
|
||||
GST_DEBUG ("rtsp server listening on port %d", test_port);
|
||||
return factory;
|
||||
}
|
||||
|
||||
/* stop the tested rtsp server */
|
||||
static void
|
||||
stop_server (void)
|
||||
{
|
||||
g_source_remove (source_id);
|
||||
source_id = 0;
|
||||
|
||||
GST_DEBUG ("rtsp server stopped");
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* create an rtsp connection to the server on test_port */
|
||||
static gchar *
|
||||
get_server_uri (gint port, const gchar * mount_point)
|
||||
{
|
||||
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);
|
||||
|
||||
fail_unless (gst_rtsp_url_parse (uri_string, &url) == GST_RTSP_OK);
|
||||
gst_rtsp_url_free (url);
|
||||
|
||||
return uri_string;
|
||||
}
|
||||
|
||||
static void
|
||||
media_constructed_cb (GstRTSPMediaFactory * mfactory, GstRTSPMedia * media,
|
||||
gpointer user_data)
|
||||
{
|
||||
GstElement **p_sink = user_data;
|
||||
GstElement *bin;
|
||||
|
||||
bin = gst_rtsp_media_get_element (media);
|
||||
*p_sink = gst_bin_get_by_name (GST_BIN (bin), "sink");
|
||||
GST_INFO ("media constructed!: %" GST_PTR_FORMAT, *p_sink);
|
||||
}
|
||||
|
||||
#define AUDIO_PIPELINE "audiotestsrc num-buffers=%d ! " \
|
||||
"audio/x-raw,rate=8000 ! alawenc ! rtspclientsink name=sink location=%s"
|
||||
#define RECORD_N_BUFS 10
|
||||
|
||||
GST_START_TEST (test_record)
|
||||
{
|
||||
GstRTSPMediaFactory *mfactory;
|
||||
GstElement *server_sink = NULL;
|
||||
gint i;
|
||||
|
||||
mfactory =
|
||||
start_record_server ("( rtppcmadepay name=depay0 ! appsink name=sink )");
|
||||
|
||||
g_signal_connect (mfactory, "media-constructed",
|
||||
G_CALLBACK (media_constructed_cb), &server_sink);
|
||||
|
||||
/* Create an rtspclientsink and send some data */
|
||||
{
|
||||
gchar *uri = get_server_uri (test_port, TEST_MOUNT_POINT);
|
||||
gchar *pipe_str = g_strdup_printf (AUDIO_PIPELINE,
|
||||
RECORD_N_BUFS, uri);
|
||||
GstMessage *msg;
|
||||
GstElement *pipeline;
|
||||
GstBus *bus;
|
||||
|
||||
pipeline = gst_parse_launch (pipe_str, NULL);
|
||||
fail_unless (pipeline != NULL);
|
||||
|
||||
bus = gst_element_get_bus (pipeline);
|
||||
fail_if (bus == NULL);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
|
||||
fail_if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_EOS);
|
||||
gst_message_unref (msg);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (pipeline);
|
||||
}
|
||||
|
||||
iterate ();
|
||||
|
||||
/* check received data (we assume every buffer created by audiotestsrc and
|
||||
* subsequently encoded by mulawenc results in exactly one RTP packet) */
|
||||
for (i = 0; i < RECORD_N_BUFS; ++i) {
|
||||
GstSample *sample = NULL;
|
||||
|
||||
g_signal_emit_by_name (G_OBJECT (server_sink), "pull-sample", &sample);
|
||||
GST_INFO ("%2d recv sample: %p", i, sample);
|
||||
if (sample)
|
||||
gst_sample_unref (sample);
|
||||
}
|
||||
|
||||
/* clean up and iterate so the clean-up can finish */
|
||||
stop_server ();
|
||||
iterate ();
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
rtspclientsink_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("rtspclientsink");
|
||||
TCase *tc = tcase_create ("general");
|
||||
|
||||
suite_add_tcase (s, tc);
|
||||
tcase_add_checked_fixture (tc, setup, teardown);
|
||||
tcase_set_timeout (tc, 120);
|
||||
tcase_add_test (tc, test_record);
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (rtspclientsink);
|
Loading…
Reference in a new issue