rtsp: Add support for ONVIF backchannel

This adds a new RTSP server, client, media-factory and media subclass
for handling the specifics of the backchannel. Ideally this later can be
extended with other ONVIF specific features.
This commit is contained in:
Sebastian Dröge 2017-09-25 19:41:05 +03:00
parent 231700b2bb
commit 72dc8acd86
17 changed files with 1497 additions and 7 deletions

View file

@ -33,6 +33,10 @@
<xi:include href="xml/rtsp-token.xml"/> <xi:include href="xml/rtsp-token.xml"/>
<xi:include href="xml/rtsp-permissions.xml"/> <xi:include href="xml/rtsp-permissions.xml"/>
<xi:include href="xml/rtsp-params.xml"/> <xi:include href="xml/rtsp-params.xml"/>
<xi:include href="xml/rtsp-onvif-server.xml"/>
<xi:include href="xml/rtsp-onvif-client.xml"/>
<xi:include href="xml/rtsp-onvif-media-factory.xml"/>
<xi:include href="xml/rtsp-onvif-media.xml"/>
</chapter> </chapter>
<chapter id="rtsp-server-hierarchy"> <chapter id="rtsp-server-hierarchy">

View file

@ -182,7 +182,9 @@ gst_rtsp_media_set_latency
gst_rtsp_media_get_latency gst_rtsp_media_get_latency
gst_rtsp_media_setup_sdp gst_rtsp_media_setup_sdp
gst_rtsp_media_setup_sdp_full
gst_rtsp_media_handle_sdp gst_rtsp_media_handle_sdp
gst_rtsp_media_handle_sdp_full
<SUBSECTION MediaPrepare> <SUBSECTION MediaPrepare>
gst_rtsp_media_prepare gst_rtsp_media_prepare
@ -281,7 +283,9 @@ gst_rtsp_media_factory_set_media_gtype
gst_rtsp_media_factory_get_media_gtype gst_rtsp_media_factory_get_media_gtype
gst_rtsp_media_factory_construct gst_rtsp_media_factory_construct
gst_rtsp_media_factory_construct_full
gst_rtsp_media_factory_create_element gst_rtsp_media_factory_create_element
gst_rtsp_media_factory_create_element_full
<SUBSECTION Standard> <SUBSECTION Standard>
GST_RTSP_MEDIA_FACTORY_CAST GST_RTSP_MEDIA_FACTORY_CAST
@ -739,3 +743,106 @@ GST_TYPE_RTSP_TOKEN
gst_rtsp_token_get_type gst_rtsp_token_get_type
</SECTION> </SECTION>
<SECTION>
<FILE>rtsp-onvif-server</FILE>
<TITLE>GstRTSPOnvifServer</TITLE>
GstRTSPOnvifServer
GstRTSPOnvifServerClass
gst_rtsp_onvif_server_new
GST_RTSP_ONVIF_BACKCHANNEL_REQUIREMENT
<SUBSECTION Standard>
gst_rtsp_onvif_server_get_type
GST_TYPE_RTSP_ONVIF_SERVER
GST_RTSP_ONVIF_SERVER
GST_RTSP_ONVIF_SERVER_CAST
GST_RTSP_ONVIF_SERVER_CLASS
GST_RTSP_ONVIF_SERVER_CLASS_CAST
GST_RTSP_ONVIF_SERVER_GET_CLASS
GST_IS_RTSP_ONVIF_SERVER
GST_IS_RTSP_ONVIF_SERVER_CLASS
</SECTION>
<SECTION>
<FILE>rtsp-onvif-server</FILE>
<TITLE>GstRTSPOnvifServer</TITLE>
GstRTSPOnvifServer
GstRTSPOnvifServerClass
gst_rtsp_onvif_server_new
<SUBSECTION Standard>
gst_rtsp_onvif_server_get_type
GST_TYPE_RTSP_ONVIF_SERVER
GST_RTSP_ONVIF_SERVER
GST_RTSP_ONVIF_SERVER_CAST
GST_RTSP_ONVIF_SERVER_CLASS
GST_RTSP_ONVIF_SERVER_CLASS_CAST
GST_RTSP_ONVIF_SERVER_GET_CLASS
GST_IS_RTSP_ONVIF_SERVER
GST_IS_RTSP_ONVIF_SERVER_CLASS
</SECTION>
<SECTION>
<FILE>rtsp-onvif-client</FILE>
<TITLE>GstRTSPOnvifClient</TITLE>
GstRTSPOnvifClient
GstRTSPOnvifClientClass
<SUBSECTION Standard>
gst_rtsp_onvif_client_get_type
GST_TYPE_RTSP_ONVIF_CLIENT
GST_RTSP_ONVIF_CLIENT
GST_RTSP_ONVIF_CLIENT_CAST
GST_RTSP_ONVIF_CLIENT_CLASS
GST_RTSP_ONVIF_CLIENT_CLASS_CAST
GST_RTSP_ONVIF_CLIENT_GET_CLASS
GST_IS_RTSP_ONVIF_CLIENT
GST_IS_RTSP_ONVIF_CLIENT_CLASS
</SECTION>
<SECTION>
<FILE>rtsp-onvif-media-factory</FILE>
<TITLE>GstRTSPOnvifMediaFactory</TITLE>
GstRTSPOnvifMediaFactory
GstRTSPOnvifMediaFactoryClass
gst_rtsp_onvif_media_factory_new
gst_rtsp_onvif_media_factory_has_backchannel_support
gst_rtsp_onvif_media_factory_set_backchannel_bandwidth
gst_rtsp_onvif_media_factory_get_backchannel_bandwidth
gst_rtsp_onvif_media_factory_set_backchannel_launch
gst_rtsp_onvif_media_factory_get_backchannel_launch
<SUBSECTION Standard>
GstRTSPOnvifMediaFactoryPrivate
gst_rtsp_onvif_media_factory_get_type
GST_TYPE_RTSP_ONVIF_MEDIA_FACTORY
GST_RTSP_ONVIF_MEDIA_FACTORY
GST_RTSP_ONVIF_MEDIA_FACTORY_CAST
GST_RTSP_ONVIF_MEDIA_FACTORY_CLASS
GST_RTSP_ONVIF_MEDIA_FACTORY_CLASS_CAST
GST_RTSP_ONVIF_MEDIA_FACTORY_GET_CLASS
GST_IS_RTSP_ONVIF_MEDIA_FACTORY
GST_IS_RTSP_ONVIF_MEDIA_FACTORY_CLASS
</SECTION>
<SECTION>
<FILE>rtsp-onvif-media</FILE>
<TITLE>GstRTSPOnvifMedia</TITLE>
GstRTSPOnvifMedia
GstRTSPOnvifMediaClass
gst_rtsp_onvif_media_collect_backchannel
gst_rtsp_onvif_media_get_backchannel_bandwidth
gst_rtsp_onvif_media_set_backchannel_bandwidth
<SUBSECTION Standard>
GstRTSPOnvifMediaPrivate
gst_rtsp_onvif_media_get_type
GST_TYPE_RTSP_ONVIF_MEDIA
GST_RTSP_ONVIF_MEDIA
GST_RTSP_ONVIF_MEDIA_CAST
GST_RTSP_ONVIF_MEDIA_CLASS
GST_RTSP_ONVIF_MEDIA_CLASS_CAST
GST_RTSP_ONVIF_MEDIA_GET_CLASS
GST_IS_RTSP_ONVIF_MEDIA
GST_IS_RTSP_ONVIF_MEDIA_CLASS
</SECTION>

1
examples/.gitignore vendored
View file

@ -13,3 +13,4 @@ test-uri
test-auth test-auth
test-netclock test-netclock
test-netclock-client test-netclock-client
test-onvif-backchannel

View file

@ -2,7 +2,8 @@ noinst_PROGRAMS = test-video test-ogg test-mp4 test-readme \
test-launch test-sdp test-uri test-auth test-auth-digest \ test-launch test-sdp test-uri test-auth test-auth-digest \
test-multicast test-multicast2 test-appsrc \ test-multicast test-multicast2 test-appsrc \
test-video-rtx test-record test-record-auth \ test-video-rtx test-record test-record-auth \
test-netclock test-netclock-client test-netclock test-netclock-client \
test-onvif-backchannel
#INCLUDES = -I$(top_srcdir) -I$(srcdir) #INCLUDES = -I$(top_srcdir) -I$(srcdir)
@ -28,3 +29,10 @@ test_netclock_client_LDADD = \
$(LDADD) \ $(LDADD) \
$(GST_NET_LIBS) $(GST_NET_LIBS)
test_onvif_backchannel_CFLAGS = \
$(AM_CFLAGS) \
$(GST_PLUGINS_BASE_CFLAGS)
test_onvif_backchannel_LDADD = \
$(LDADD) \
$(GST_PLUGINS_BASE_LIBS) -lgstrtsp-1.0 -lgstsdp-1.0

View file

@ -0,0 +1,71 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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/gst.h>
#include <gst/rtsp-server/rtsp-onvif-server.h>
#include <string.h>
int
main (int argc, char *argv[])
{
GMainLoop *loop;
GstRTSPServer *server;
GstRTSPMountPoints *mounts;
GstRTSPMediaFactory *factory;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* create a server instance */
server = gst_rtsp_onvif_server_new ();
/* get the mount points for this server, every server has a default object
* that be used to map uri mount points to media factories */
mounts = gst_rtsp_server_get_mount_points (server);
/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d. Each
* element with pay%d names will be a stream */
factory = gst_rtsp_onvif_media_factory_new ();
gst_rtsp_media_factory_set_launch (factory,
"( videotestsrc is-live=true ! x264enc ! rtph264pay name=pay0 pt=96 audiotestsrc is-live=true ! mulawenc ! rtppcmupay name=pay1 )");
gst_rtsp_onvif_media_factory_set_backchannel_launch
(GST_RTSP_ONVIF_MEDIA_FACTORY (factory),
"( capsfilter caps=\"application/x-rtp, media=audio, payload=0, clock-rate=8000, encoding-name=PCMU\" name=depay_backchannel ! rtppcmudepay ! fakesink async=false )");
gst_rtsp_media_factory_set_shared (factory, FALSE);
gst_rtsp_media_factory_set_media_gtype (factory, GST_TYPE_RTSP_ONVIF_MEDIA);
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
/* don't need the ref to the mapper anymore */
g_object_unref (mounts);
/* attach the server to the default maincontext */
gst_rtsp_server_attach (server, NULL);
/* start serving */
g_print ("stream ready at rtsp://127.0.0.1:8554/test\n");
g_main_loop_run (loop);
return 0;
}

View file

@ -17,7 +17,11 @@ public_headers = \
rtsp-session-pool.h \ rtsp-session-pool.h \
rtsp-token.h \ rtsp-token.h \
rtsp-client.h \ rtsp-client.h \
rtsp-server.h rtsp-server.h \
rtsp-onvif-server.h \
rtsp-onvif-client.h \
rtsp-onvif-media-factory.h \
rtsp-onvif-media.h
c_sources = \ c_sources = \
rtsp-auth.c \ rtsp-auth.c \
@ -38,7 +42,11 @@ c_sources = \
rtsp-session-pool.c \ rtsp-session-pool.c \
rtsp-token.c \ rtsp-token.c \
rtsp-client.c \ rtsp-client.c \
rtsp-server.c rtsp-server.c \
rtsp-onvif-server.c \
rtsp-onvif-client.c \
rtsp-onvif-media-factory.c \
rtsp-onvif-media.c
noinst_HEADERS = noinst_HEADERS =

View file

@ -332,7 +332,6 @@ gboolean gst_rtsp_media_setup_sdp (GstRTSPMedia * media, Gst
GST_EXPORT GST_EXPORT
gboolean gst_rtsp_media_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp); gboolean gst_rtsp_media_handle_sdp (GstRTSPMedia * media, GstSDPMessage * sdp);
/* creating streams */ /* creating streams */
GST_EXPORT GST_EXPORT

View file

@ -0,0 +1,100 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include "rtsp-onvif-client.h"
#include "rtsp-onvif-server.h"
#include "rtsp-onvif-media-factory.h"
G_DEFINE_TYPE (GstRTSPOnvifClient, gst_rtsp_onvif_client, GST_TYPE_RTSP_CLIENT);
static gchar *
gst_rtsp_onvif_client_check_requirements (GstRTSPClient * client,
GstRTSPContext * ctx, gchar ** requirements)
{
GstRTSPMountPoints *mount_points = NULL;
GstRTSPMediaFactory *factory = NULL;
gchar *path = NULL;
gboolean has_backchannel = FALSE;
GString *unsupported = g_string_new ("");
while (*requirements) {
if (strcmp (*requirements, GST_RTSP_ONVIF_BACKCHANNEL_REQUIREMENT) == 0) {
has_backchannel = TRUE;
} else {
if (unsupported->len)
g_string_append (unsupported, ", ");
g_string_append (unsupported, *requirements);
}
requirements++;
}
if (unsupported->len)
goto out;
mount_points = gst_rtsp_client_get_mount_points (client);
if (!(path = gst_rtsp_mount_points_make_path (mount_points, ctx->uri)))
goto out;
if (!(factory = gst_rtsp_mount_points_match (mount_points, path, NULL)))
goto out;
if (has_backchannel && !GST_IS_RTSP_ONVIF_MEDIA_FACTORY (factory)) {
if (unsupported->len)
g_string_append (unsupported, ", ");
g_string_append (unsupported, GST_RTSP_ONVIF_BACKCHANNEL_REQUIREMENT);
} else if (has_backchannel) {
GstRTSPOnvifMediaFactory *onvif_factory =
GST_RTSP_ONVIF_MEDIA_FACTORY (factory);
if (!gst_rtsp_onvif_media_factory_has_backchannel_support (onvif_factory)) {
if (unsupported->len)
g_string_append (unsupported, ", ");
g_string_append (unsupported, GST_RTSP_ONVIF_BACKCHANNEL_REQUIREMENT);
}
}
out:
if (path)
g_free (path);
if (factory)
g_object_unref (factory);
if (mount_points)
g_object_unref (mount_points);
return g_string_free (unsupported, FALSE);
}
static void
gst_rtsp_onvif_client_class_init (GstRTSPOnvifClientClass * klass)
{
GstRTSPClientClass *client_klass = (GstRTSPClientClass *) klass;
client_klass->check_requirements = gst_rtsp_onvif_client_check_requirements;
}
static void
gst_rtsp_onvif_client_init (GstRTSPOnvifClient * client)
{
}

View file

@ -0,0 +1,57 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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.
*/
#ifndef __GST_RTSP_ONVIF_CLIENT_H__
#define __GST_RTSP_ONVIF_CLIENT_H__
#include <gst/gst.h>
#include "rtsp-client.h"
#define GST_TYPE_RTSP_ONVIF_CLIENT (gst_rtsp_onvif_client_get_type ())
#define GST_IS_RTSP_ONVIF_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_ONVIF_CLIENT))
#define GST_IS_RTSP_ONVIF_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_ONVIF_CLIENT))
#define GST_RTSP_ONVIF_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_ONVIF_CLIENT, GstRTSPOnvifClientClass))
#define GST_RTSP_ONVIF_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_ONVIF_CLIENT, GstRTSPOnvifClient))
#define GST_RTSP_ONVIF_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_ONVIF_CLIENT, GstRTSPOnvifClientClass))
#define GST_RTSP_ONVIF_CLIENT_CAST(obj) ((GstRTSPOnvifClient*)(obj))
#define GST_RTSP_ONVIF_CLIENT_CLASS_CAST(klass) ((GstRTSPOnvifClientClass*)(klass))
typedef struct GstRTSPOnvifClientClass GstRTSPOnvifClientClass;
typedef struct GstRTSPOnvifClient GstRTSPOnvifClient;
struct GstRTSPOnvifClientClass
{
GstRTSPClientClass parent;
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE];
};
struct GstRTSPOnvifClient
{
GstRTSPClient parent;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GST_EXPORT
GType gst_rtsp_onvif_client_get_type (void);
#endif /* __GST_RTSP_ONVIF_CLIENT_H__ */

View file

@ -0,0 +1,491 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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.
*/
/**
* SECTION:rtsp-onvif-media-factory
* @short_description: A factory for ONVIF media pipelines
* @see_also: #GstRTSPMediaFactory, #GstRTSPOnvifMedia
*
* The #GstRTSPOnvifMediaFactory is responsible for creating or recycling
* #GstRTSPMedia objects based on the passed URL. Different to
* #GstRTSPMediaFactory, this supports special ONVIF features and can create
* #GstRTSPOnvifMedia in addition to normal #GstRTSPMedia.
*
* Special ONVIF features that are currently supported is a backchannel for
* the client to send back media to the server in a normal PLAY media, see
* gst_rtsp_onvif_media_factory_set_backchannel_launch() and
* gst_rtsp_onvif_media_factory_set_backchannel_bandwidth().
*
* Since: 1.14
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include "rtsp-onvif-media-factory.h"
#include "rtsp-onvif-media.h"
#include "rtsp-onvif-server.h"
struct GstRTSPOnvifMediaFactoryPrivate
{
GMutex lock;
gchar *backchannel_launch;
guint backchannel_bandwidth;
};
G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPOnvifMediaFactory,
gst_rtsp_onvif_media_factory, GST_TYPE_RTSP_MEDIA_FACTORY);
static gboolean
requires_backchannel (GstRTSPMessage * msg)
{
GstRTSPResult res;
gint i;
gchar *reqs = NULL;
i = 0;
do {
res = gst_rtsp_message_get_header (msg, GST_RTSP_HDR_REQUIRE, &reqs, i++);
if (res == GST_RTSP_ENOTIMPL)
break;
if (strcmp (reqs, GST_RTSP_ONVIF_BACKCHANNEL_REQUIREMENT) == 0)
return TRUE;
} while (TRUE);
return FALSE;
}
static gchar *
gst_rtsp_onvif_media_factory_gen_key (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url)
{
GstRTSPContext *ctx = gst_rtsp_context_get_current ();
GstRTSPMessage *msg = ctx->request;
/* Only medias where no backchannel was requested can be shared */
if (requires_backchannel (msg))
return NULL;
return
GST_RTSP_MEDIA_FACTORY_CLASS
(gst_rtsp_onvif_media_factory_parent_class)->gen_key (factory, url);
}
static GstRTSPMedia *
gst_rtsp_onvif_media_factory_construct (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url)
{
GstRTSPMedia *media;
GstElement *element, *pipeline;
GstRTSPMediaFactoryClass *klass;
GType media_gtype;
gboolean got_backchannel_stream;
GstRTSPContext *ctx = gst_rtsp_context_get_current ();
/* Mostly a copy of the default implementation but with backchannel support below,
* unfortunately we can't re-use the default one because of how the virtual
* method is define */
/* Everything but play is unsupported */
if (gst_rtsp_media_factory_get_transport_mode (factory) !=
GST_RTSP_TRANSPORT_MODE_PLAY)
return NULL;
/* we only support onvif media here: otherwise a plain GstRTSPMediaFactory
* could've been used as well */
media_gtype = gst_rtsp_media_factory_get_media_gtype (factory);
if (!g_type_is_a (media_gtype, GST_TYPE_RTSP_ONVIF_MEDIA))
return NULL;
klass = GST_RTSP_MEDIA_FACTORY_GET_CLASS (factory);
if (!klass->create_pipeline)
goto no_create;
element = gst_rtsp_media_factory_create_element (factory, url);
if (element == NULL)
goto no_element;
/* create a new empty media */
media =
g_object_new (media_gtype, "element", element,
"transport-mode", GST_RTSP_TRANSPORT_MODE_PLAY, NULL);
/* this adds the non-backchannel streams */
gst_rtsp_media_collect_streams (media);
/* this adds the backchannel stream */
got_backchannel_stream =
gst_rtsp_onvif_media_collect_backchannel (GST_RTSP_ONVIF_MEDIA (media));
/* FIXME: This should not happen! We checked for that before */
if (requires_backchannel (ctx->request) && !got_backchannel_stream) {
g_object_unref (media);
return NULL;
}
pipeline = klass->create_pipeline (factory, media);
if (pipeline == NULL)
goto no_pipeline;
gst_rtsp_onvif_media_set_backchannel_bandwidth (GST_RTSP_ONVIF_MEDIA (media),
GST_RTSP_ONVIF_MEDIA_FACTORY (factory)->priv->backchannel_bandwidth);
return media;
/* ERRORS */
no_create:
{
g_critical ("no create_pipeline function");
return NULL;
}
no_element:
{
g_critical ("could not create element");
return NULL;
}
no_pipeline:
{
g_critical ("can't create pipeline");
g_object_unref (media);
return NULL;
}
}
static GstElement *
gst_rtsp_onvif_media_factory_create_element (GstRTSPMediaFactory * factory,
const GstRTSPUrl * url)
{
GstElement *element;
GError *error = NULL;
gchar *launch;
GstRTSPContext *ctx = gst_rtsp_context_get_current ();
/* Mostly a copy of the default implementation but with backchannel support below,
* unfortunately we can't re-use the default one because of how the virtual
* method is define */
launch = gst_rtsp_media_factory_get_launch (factory);
/* we need a parse syntax */
if (launch == NULL)
goto no_launch;
/* parse the user provided launch line */
element =
gst_parse_launch_full (launch, NULL, GST_PARSE_FLAG_PLACE_IN_BIN, &error);
if (element == NULL)
goto parse_error;
g_free (launch);
if (error != NULL) {
/* a recoverable error was encountered */
GST_WARNING ("recoverable parsing error: %s", error->message);
g_error_free (error);
}
/* add backchannel pipeline part, if requested */
if (requires_backchannel (ctx->request)) {
GstRTSPOnvifMediaFactory *onvif_factory =
GST_RTSP_ONVIF_MEDIA_FACTORY (factory);
GstElement *backchannel_bin;
GstElement *backchannel_depay;
GstPad *depay_pad, *depay_ghostpad;
launch =
gst_rtsp_onvif_media_factory_get_backchannel_launch (onvif_factory);
if (launch == NULL)
goto no_launch_backchannel;
backchannel_bin =
gst_parse_bin_from_description_full (launch, FALSE, NULL,
GST_PARSE_FLAG_PLACE_IN_BIN, &error);
if (backchannel_bin == NULL)
goto parse_error_backchannel;
g_free (launch);
if (error != NULL) {
/* a recoverable error was encountered */
GST_WARNING ("recoverable parsing error: %s", error->message);
g_error_free (error);
}
gst_object_set_name (GST_OBJECT (backchannel_bin), "onvif-backchannel");
backchannel_depay =
gst_bin_get_by_name (GST_BIN (backchannel_bin), "depay_backchannel");
if (!backchannel_depay) {
gst_object_unref (backchannel_bin);
goto wrongly_formatted_backchannel_bin;
}
depay_pad = gst_element_get_static_pad (backchannel_depay, "sink");
if (!depay_pad) {
gst_object_unref (backchannel_depay);
gst_object_unref (backchannel_bin);
goto wrongly_formatted_backchannel_bin;
}
depay_ghostpad = gst_ghost_pad_new ("sink", depay_pad);
gst_element_add_pad (backchannel_bin, depay_ghostpad);
gst_bin_add (GST_BIN (element), backchannel_bin);
}
return element;
/* ERRORS */
no_launch:
{
g_critical ("no launch line specified");
g_free (launch);
return NULL;
}
parse_error:
{
g_critical ("could not parse launch syntax (%s): %s", launch,
(error ? error->message : "unknown reason"));
if (error)
g_error_free (error);
g_free (launch);
return NULL;
}
no_launch_backchannel:
{
g_critical ("no backchannel launch line specified");
gst_object_unref (element);
return NULL;
}
parse_error_backchannel:
{
g_critical ("could not parse backchannel launch syntax (%s): %s", launch,
(error ? error->message : "unknown reason"));
if (error)
g_error_free (error);
g_free (launch);
gst_object_unref (element);
return NULL;
}
wrongly_formatted_backchannel_bin:
{
g_critical ("invalidly formatted backchannel bin");
gst_object_unref (element);
return NULL;
}
}
static gboolean
gst_rtsp_onvif_media_factory_has_backchannel_support_default
(GstRTSPOnvifMediaFactory * factory)
{
/* No locking here, we just check if it's non-NULL */
return factory->priv->backchannel_launch != NULL;
}
static void
gst_rtsp_onvif_media_factory_finalize (GObject * object)
{
GstRTSPOnvifMediaFactory *factory = GST_RTSP_ONVIF_MEDIA_FACTORY (object);
g_free (factory->priv->backchannel_launch);
factory->priv->backchannel_launch = NULL;
g_mutex_clear (&factory->priv->lock);
return
G_OBJECT_CLASS (gst_rtsp_onvif_media_factory_parent_class)->finalize
(object);
}
static void
gst_rtsp_onvif_media_factory_class_init (GstRTSPOnvifMediaFactoryClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GstRTSPMediaFactoryClass *factory_klass = (GstRTSPMediaFactoryClass *) klass;
gobject_class->finalize = gst_rtsp_onvif_media_factory_finalize;
factory_klass->gen_key = gst_rtsp_onvif_media_factory_gen_key;
factory_klass->construct = gst_rtsp_onvif_media_factory_construct;
factory_klass->create_element = gst_rtsp_onvif_media_factory_create_element;
klass->has_backchannel_support =
gst_rtsp_onvif_media_factory_has_backchannel_support_default;
}
static void
gst_rtsp_onvif_media_factory_init (GstRTSPOnvifMediaFactory * factory)
{
factory->priv = gst_rtsp_onvif_media_factory_get_instance_private (factory);
g_mutex_init (&factory->priv->lock);
}
/**
* gst_rtsp_onvif_media_factory_set_backchannel_launch:
* @factory: a #GstRTSPMediaFactory
* @launch: the launch description
*
* The gst_parse_launch() line to use for constructing the ONVIF backchannel
* pipeline in the default prepare vmethod if requested by the client.
*
* The pipeline description should return a GstBin as the toplevel element
* which can be accomplished by enclosing the description with brackets '('
* ')'.
*
* The description should return a pipeline with a single depayloader named
* depay_backchannel. A caps query on the depayloader's sinkpad should return
* all possible, complete RTP caps that are going to be supported. At least
* the payload type, clock-rate and encoding-name need to be specified.
*
* Since: 1.14
*/
void
gst_rtsp_onvif_media_factory_set_backchannel_launch (GstRTSPOnvifMediaFactory *
factory, const gchar * launch)
{
g_return_if_fail (GST_IS_RTSP_ONVIF_MEDIA_FACTORY (factory));
g_mutex_lock (&factory->priv->lock);
g_free (factory->priv->backchannel_launch);
factory->priv->backchannel_launch = g_strdup (launch);
g_mutex_unlock (&factory->priv->lock);
}
/**
* gst_rtsp_onvif_media_factory_get_backchannel_launch:
* @factory: a #GstRTSPMediaFactory
*
* Get the gst_parse_launch() pipeline description that will be used in the
* default prepare vmethod for generating the ONVIF backchannel pipeline.
*
* Returns: (transfer full): the configured backchannel launch description. g_free() after
* usage.
*
* Since: 1.14
*/
gchar *
gst_rtsp_onvif_media_factory_get_backchannel_launch (GstRTSPOnvifMediaFactory *
factory)
{
gchar *launch;
g_return_val_if_fail (GST_IS_RTSP_ONVIF_MEDIA_FACTORY (factory), NULL);
g_mutex_lock (&factory->priv->lock);
launch = g_strdup (factory->priv->backchannel_launch);
g_mutex_unlock (&factory->priv->lock);
return launch;
}
/**
* gst_rtsp_onvif_media_factory_has_backchannel_support:
* @factory: a #GstRTSPMediaFactory
*
* Returns %TRUE if an ONVIF backchannel is supported by the media factory.
*
* Returns: %TRUE if an ONVIF backchannel is supported by the media factory.
*
* Since: 1.14
*/
gboolean
gst_rtsp_onvif_media_factory_has_backchannel_support (GstRTSPOnvifMediaFactory *
factory)
{
GstRTSPOnvifMediaFactoryClass *klass;
g_return_val_if_fail (GST_IS_RTSP_ONVIF_MEDIA_FACTORY (factory), FALSE);
klass = GST_RTSP_ONVIF_MEDIA_FACTORY_GET_CLASS (factory);
if (klass->has_backchannel_support)
return klass->has_backchannel_support (factory);
return FALSE;
}
/**
* gst_rtsp_onvif_media_factory_set_backchannel_bandwidth:
* @factory: a #GstRTSPMediaFactory
* @bandwidth: the bandwidth in bits per second
*
* Set the configured/supported bandwidth of the ONVIF backchannel pipeline in
* bits per second.
*
* Since: 1.14
*/
void
gst_rtsp_onvif_media_factory_set_backchannel_bandwidth (GstRTSPOnvifMediaFactory
* factory, guint bandwidth)
{
g_return_if_fail (GST_IS_RTSP_ONVIF_MEDIA_FACTORY (factory));
g_mutex_lock (&factory->priv->lock);
factory->priv->backchannel_bandwidth = bandwidth;
g_mutex_unlock (&factory->priv->lock);
}
/**
* gst_rtsp_onvif_media_factory_get_backchannel_bandwidth:
* @factory: a #GstRTSPMediaFactory
*
* Get the configured/supported bandwidth of the ONVIF backchannel pipeline in
* bits per second.
*
* Returns: the configured/supported backchannel bandwidth.
*
* Since: 1.14
*/
guint
gst_rtsp_onvif_media_factory_get_backchannel_bandwidth (GstRTSPOnvifMediaFactory
* factory)
{
guint bandwidth;
g_return_val_if_fail (GST_IS_RTSP_ONVIF_MEDIA_FACTORY (factory), 0);
g_mutex_lock (&factory->priv->lock);
bandwidth = factory->priv->backchannel_bandwidth;
g_mutex_unlock (&factory->priv->lock);
return bandwidth;
}
/**
* gst_rtsp_onvif_media_factory_new:
*
* Create a new #GstRTSPOnvifMediaFactory
*
* Returns: A new #GstRTSPOnvifMediaFactory
*
* Since: 1.14
*/
GstRTSPMediaFactory *
gst_rtsp_onvif_media_factory_new (void)
{
return g_object_new (GST_TYPE_RTSP_ONVIF_MEDIA_FACTORY, NULL);
}

View file

@ -0,0 +1,77 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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.
*/
#ifndef __GST_RTSP_ONVIF_MEDIA_FACTORY_H__
#define __GST_RTSP_ONVIF_MEDIA_FACTORY_H__
#include <gst/gst.h>
#include "rtsp-media-factory.h"
#define GST_TYPE_RTSP_ONVIF_MEDIA_FACTORY (gst_rtsp_onvif_media_factory_get_type ())
#define GST_IS_RTSP_ONVIF_MEDIA_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_ONVIF_MEDIA_FACTORY))
#define GST_IS_RTSP_ONVIF_MEDIA_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_ONVIF_MEDIA_FACTORY))
#define GST_RTSP_ONVIF_MEDIA_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_ONVIF_MEDIA_FACTORY, GstRTSPOnvifMediaFactoryClass))
#define GST_RTSP_ONVIF_MEDIA_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_ONVIF_MEDIA_FACTORY, GstRTSPOnvifMediaFactory))
#define GST_RTSP_ONVIF_MEDIA_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_ONVIF_MEDIA_FACTORY, GstRTSPOnvifMediaFactoryClass))
#define GST_RTSP_ONVIF_MEDIA_FACTORY_CAST(obj) ((GstRTSPOnvifMediaFactory*)(obj))
#define GST_RTSP_ONVIF_MEDIA_FACTORY_CLASS_CAST(klass) ((GstRTSPOnvifMediaFactoryClass*)(klass))
typedef struct GstRTSPOnvifMediaFactoryClass GstRTSPOnvifMediaFactoryClass;
typedef struct GstRTSPOnvifMediaFactory GstRTSPOnvifMediaFactory;
typedef struct GstRTSPOnvifMediaFactoryPrivate GstRTSPOnvifMediaFactoryPrivate;
struct GstRTSPOnvifMediaFactoryClass
{
GstRTSPMediaFactoryClass parent;
gboolean (*has_backchannel_support) (GstRTSPOnvifMediaFactory * factory);
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE];
};
struct GstRTSPOnvifMediaFactory
{
GstRTSPMediaFactory parent;
GstRTSPOnvifMediaFactoryPrivate *priv;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GST_EXPORT
GType gst_rtsp_onvif_media_factory_get_type (void);
GST_EXPORT
GstRTSPMediaFactory *gst_rtsp_onvif_media_factory_new (void);
GST_EXPORT
void gst_rtsp_onvif_media_factory_set_backchannel_launch (GstRTSPOnvifMediaFactory *
factory, const gchar * launch);
GST_EXPORT
gchar * gst_rtsp_onvif_media_factory_get_backchannel_launch (GstRTSPOnvifMediaFactory * factory);
GST_EXPORT
gboolean gst_rtsp_onvif_media_factory_has_backchannel_support (GstRTSPOnvifMediaFactory * factory);
GST_EXPORT
void gst_rtsp_onvif_media_factory_set_backchannel_bandwidth (GstRTSPOnvifMediaFactory * factory, guint bandwidth);
GST_EXPORT
guint gst_rtsp_onvif_media_factory_get_backchannel_bandwidth (GstRTSPOnvifMediaFactory * factory);
#endif /* __GST_RTSP_ONVIF_MEDIA_FACTORY_H__ */

View file

@ -0,0 +1,330 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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.
*/
/**
* SECTION:rtsp-onvif-media
* @short_description: The ONVIF media pipeline
* @see_also: #GstRTSPMedia, #GstRTSPOnvifMediaFactory, #GstRTSPStream, #GstRTSPSession,
* #GstRTSPSessionMedia
*
* a #GstRTSPOnvifMedia contains the complete GStreamer pipeline to manage the
* streaming to the clients. The actual data transfer is done by the
* #GstRTSPStream objects that are created and exposed by the #GstRTSPMedia.
*
* On top of #GstRTSPMedia this subclass adds special ONVIF features.
* Special ONVIF features that are currently supported is a backchannel for
* the client to send back media to the server in a normal PLAY media. To
* handle the ONVIF backchannel, a #GstRTSPOnvifMediaFactory and
* #GstRTSPOnvifServer has to be used.
*
* Since: 1.14
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "rtsp-onvif-media.h"
struct GstRTSPOnvifMediaPrivate
{
GMutex lock;
guint backchannel_bandwidth;
};
G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPOnvifMedia, gst_rtsp_onvif_media,
GST_TYPE_RTSP_MEDIA);
static gboolean
gst_rtsp_onvif_media_setup_sdp (GstRTSPMedia * media, GstSDPMessage * sdp,
GstSDPInfo * info)
{
guint i, n_streams;
gchar *rangestr;
gboolean res;
/* Mostly a copy of gst_rtsp_sdp_from_media() which handles the backchannel
* stream separately and adds sendonly/recvonly attributes to each media
*/
n_streams = gst_rtsp_media_n_streams (media);
rangestr = gst_rtsp_media_get_range_string (media, FALSE, GST_RTSP_RANGE_NPT);
if (rangestr == NULL)
goto not_prepared;
gst_sdp_message_add_attribute (sdp, "range", rangestr);
g_free (rangestr);
res = TRUE;
for (i = 0; res && (i < n_streams); i++) {
GstRTSPStream *stream;
GstCaps *caps = NULL;
GstRTSPProfile profiles;
guint mask;
gboolean res;
GstPad *sinkpad = NULL;
guint n_caps, j;
/* Mostly a copy of gst_rtsp_sdp_from_stream() which handles the
* backchannel stream separately */
stream = gst_rtsp_media_get_stream (media, i);
if ((sinkpad = gst_rtsp_stream_get_sinkpad (stream))) {
caps = gst_pad_query_caps (sinkpad, NULL);
} else {
caps = gst_rtsp_stream_get_caps (stream);
}
if (caps == NULL) {
GST_ERROR ("stream %p has no caps", stream);
res = FALSE;
if (sinkpad)
gst_object_unref (sinkpad);
break;
} else if (!sinkpad && !gst_caps_is_fixed (caps)) {
GST_ERROR ("stream %p has unfixed caps", stream);
res = FALSE;
gst_caps_unref (caps);
break;
}
n_caps = gst_caps_get_size (caps);
for (j = 0; res && j < n_caps; j++) {
GstStructure *s = gst_caps_get_structure (caps, j);
GstCaps *media_caps = gst_caps_new_full (gst_structure_copy (s), NULL);
if (!gst_caps_is_fixed (media_caps)) {
GST_ERROR ("media caps for stream %p are not all fixed", stream);
res = FALSE;
gst_caps_unref (media_caps);
break;
}
/* make a new media for each profile */
profiles = gst_rtsp_stream_get_profiles (stream);
mask = 1;
res = TRUE;
while (res && (profiles >= mask)) {
GstRTSPProfile prof = profiles & mask;
if (prof) {
res = gst_rtsp_sdp_make_media (sdp, info, stream, media_caps, prof);
if (res) {
GstSDPMedia *smedia =
&g_array_index (sdp->medias, GstSDPMedia, sdp->medias->len - 1);
if (sinkpad) {
GstRTSPOnvifMedia *onvif_media = GST_RTSP_ONVIF_MEDIA (media);
gst_sdp_media_add_attribute (smedia, "sendonly", "");
if (onvif_media->priv->backchannel_bandwidth > 0)
gst_sdp_media_add_bandwidth (smedia, GST_SDP_BWTYPE_AS,
onvif_media->priv->backchannel_bandwidth);
} else {
gst_sdp_media_add_attribute (smedia, "recvonly", "");
}
}
}
mask <<= 1;
}
if (sinkpad) {
GstStructure *s = gst_caps_get_structure (media_caps, 0);
gint pt = -1;
if (!gst_structure_get_int (s, "payload", &pt) || pt < 0) {
GST_ERROR ("stream %p has no payload type", stream);
res = FALSE;
gst_caps_unref (media_caps);
gst_object_unref (sinkpad);
break;
}
gst_rtsp_stream_set_pt_map (stream, pt, media_caps);
}
gst_caps_unref (media_caps);
}
gst_caps_unref (caps);
if (sinkpad)
gst_object_unref (sinkpad);
}
{
GstNetTimeProvider *provider;
if ((provider =
gst_rtsp_media_get_time_provider (media, info->server_ip, 0))) {
GstClock *clock;
gchar *address, *str;
gint port;
g_object_get (provider, "clock", &clock, "address", &address, "port",
&port, NULL);
str = g_strdup_printf ("GstNetTimeProvider %s %s:%d %" G_GUINT64_FORMAT,
g_type_name (G_TYPE_FROM_INSTANCE (clock)), address, port,
gst_clock_get_time (clock));
gst_sdp_message_add_attribute (sdp, "x-gst-clock", str);
g_free (str);
gst_object_unref (clock);
g_free (address);
gst_object_unref (provider);
}
}
return res;
/* ERRORS */
not_prepared:
{
GST_ERROR ("media %p is not prepared", media);
return FALSE;
}
}
static void
gst_rtsp_onvif_media_finalize (GObject * object)
{
GstRTSPOnvifMedia *media = GST_RTSP_ONVIF_MEDIA (object);
g_mutex_clear (&media->priv->lock);
return G_OBJECT_CLASS (gst_rtsp_onvif_media_parent_class)->finalize (object);
}
static void
gst_rtsp_onvif_media_class_init (GstRTSPOnvifMediaClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GstRTSPMediaClass *media_class = (GstRTSPMediaClass *) klass;
gobject_class->finalize = gst_rtsp_onvif_media_finalize;
media_class->setup_sdp = gst_rtsp_onvif_media_setup_sdp;
}
static void
gst_rtsp_onvif_media_init (GstRTSPOnvifMedia * media)
{
media->priv = gst_rtsp_onvif_media_get_instance_private (media);
g_mutex_init (&media->priv->lock);
}
/**
* gst_rtsp_onvif_media_collect_backchannel:
* @media: a #GstRTSPOnvifMedia
*
* Find the ONVIF backchannel depayloader element. It should be named
* 'depay_backchannel', be placed in a bin called 'onvif-backchannel'
* and return all supported RTP caps on a caps query. Complete RTP caps with
* at least the payload type, clock-rate and encoding-name are required.
*
* A new #GstRTSPStream is created for the backchannel if found.
*
* Returns: %TRUE if a backchannel stream could be found and created
*
* Since: 1.14
*/
gboolean
gst_rtsp_onvif_media_collect_backchannel (GstRTSPOnvifMedia * media)
{
GstElement *element, *backchannel_bin = NULL;
GstPad *pad = NULL;
gboolean ret = FALSE;
g_return_val_if_fail (GST_IS_RTSP_ONVIF_MEDIA (media), FALSE);
element = gst_rtsp_media_get_element (GST_RTSP_MEDIA (media));
if (!element)
return ret;
backchannel_bin =
gst_bin_get_by_name (GST_BIN (element), "onvif-backchannel");
if (!backchannel_bin)
goto out;
pad = gst_element_get_static_pad (backchannel_bin, "sink");
if (!pad)
goto out;
gst_rtsp_media_create_stream (GST_RTSP_MEDIA (media), backchannel_bin, pad);
ret = TRUE;
out:
if (pad)
gst_object_unref (pad);
if (backchannel_bin)
gst_object_unref (backchannel_bin);
gst_object_unref (element);
return ret;
}
/**
* gst_rtsp_onvif_media_set_backchannel_bandwidth:
* @factory: a #GstRTSPMedia
* @bandwidth: the bandwidth in bits per second
*
* Set the configured/supported bandwidth of the ONVIF backchannel pipeline in
* bits per second.
*
* Since: 1.14
*/
void
gst_rtsp_onvif_media_set_backchannel_bandwidth (GstRTSPOnvifMedia * media,
guint bandwidth)
{
g_return_if_fail (GST_IS_RTSP_ONVIF_MEDIA (media));
g_mutex_lock (&media->priv->lock);
media->priv->backchannel_bandwidth = bandwidth;
g_mutex_unlock (&media->priv->lock);
}
/**
* gst_rtsp_onvif_media_get_backchannel_bandwidth:
* @factory: a #GstRTSPMedia
*
* Get the configured/supported bandwidth of the ONVIF backchannel pipeline in
* bits per second.
*
* Returns: the configured/supported backchannel bandwidth.
*
* Since: 1.14
*/
guint
gst_rtsp_onvif_media_get_backchannel_bandwidth (GstRTSPOnvifMedia * media)
{
guint bandwidth;
g_return_val_if_fail (GST_IS_RTSP_ONVIF_MEDIA (media), 0);
g_mutex_lock (&media->priv->lock);
bandwidth = media->priv->backchannel_bandwidth;
g_mutex_unlock (&media->priv->lock);
return bandwidth;
}

View file

@ -0,0 +1,66 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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.
*/
#ifndef __GST_RTSP_ONVIF_MEDIA_H__
#define __GST_RTSP_ONVIF_MEDIA_H__
#include <gst/gst.h>
#include "rtsp-media.h"
#define GST_TYPE_RTSP_ONVIF_MEDIA (gst_rtsp_onvif_media_get_type ())
#define GST_IS_RTSP_ONVIF_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_ONVIF_MEDIA))
#define GST_IS_RTSP_ONVIF_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_ONVIF_MEDIA))
#define GST_RTSP_ONVIF_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_ONVIF_MEDIA, GstRTSPOnvifMediaClass))
#define GST_RTSP_ONVIF_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_ONVIF_MEDIA, GstRTSPOnvifMedia))
#define GST_RTSP_ONVIF_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_ONVIF_MEDIA, GstRTSPOnvifMediaClass))
#define GST_RTSP_ONVIF_MEDIA_CAST(obj) ((GstRTSPOnvifMedia*)(obj))
#define GST_RTSP_ONVIF_MEDIA_CLASS_CAST(klass) ((GstRTSPOnvifMediaClass*)(klass))
typedef struct GstRTSPOnvifMediaClass GstRTSPOnvifMediaClass;
typedef struct GstRTSPOnvifMedia GstRTSPOnvifMedia;
typedef struct GstRTSPOnvifMediaPrivate GstRTSPOnvifMediaPrivate;
struct GstRTSPOnvifMediaClass
{
GstRTSPMediaClass parent;
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE];
};
struct GstRTSPOnvifMedia
{
GstRTSPMedia parent;
GstRTSPOnvifMediaPrivate *priv;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GST_EXPORT
GType gst_rtsp_onvif_media_get_type (void);
GST_EXPORT
gboolean gst_rtsp_onvif_media_collect_backchannel (GstRTSPOnvifMedia * media);
GST_EXPORT
void gst_rtsp_onvif_media_set_backchannel_bandwidth (GstRTSPOnvifMedia * media, guint bandwidth);
GST_EXPORT
guint gst_rtsp_onvif_media_get_backchannel_bandwidth (GstRTSPOnvifMedia * media);
#endif /* __GST_RTSP_ONVIF_MEDIA_H__ */

View file

@ -0,0 +1,100 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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.
*/
/**
* SECTION:rtsp-onvif-server
* @short_description: The main server object
* @see_also: #GstRTSPOnvifMediaFactory, #GstRTSPClient
*
* The server object is the object listening for connections on a port and
* creating #GstRTSPOnvifClient objects to handle those connections.
*
* The only different to #GstRTSPServer is that #GstRTSPOnvifServer creates
* #GstRTSPOnvifClient that have special handling for ONVIF specific features,
* like a backchannel that allows clients to send back media to the server.
*
* Since: 1.14
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "rtsp-onvif-server.h"
#include "rtsp-onvif-client.h"
G_DEFINE_TYPE (GstRTSPOnvifServer, gst_rtsp_onvif_server, GST_TYPE_RTSP_SERVER);
static GstRTSPClient *
gst_rtsp_onvif_server_create_client (GstRTSPServer * server)
{
GstRTSPClient *client;
GstRTSPSessionPool *session_pool;
GstRTSPMountPoints *mount_points;
GstRTSPAuth *auth;
GstRTSPThreadPool *thread_pool;
/* a new client connected, create a session to handle the client. */
client = g_object_new (GST_TYPE_RTSP_ONVIF_CLIENT, NULL);
/* set the session pool that this client should use */
session_pool = gst_rtsp_server_get_session_pool (server);
gst_rtsp_client_set_session_pool (client, session_pool);
g_object_unref (session_pool);
/* set the mount points that this client should use */
mount_points = gst_rtsp_server_get_mount_points (server);
gst_rtsp_client_set_mount_points (client, mount_points);
g_object_unref (mount_points);
/* set authentication manager */
auth = gst_rtsp_server_get_auth (server);
gst_rtsp_client_set_auth (client, auth);
if (auth)
g_object_unref (auth);
/* set threadpool */
thread_pool = gst_rtsp_server_get_thread_pool (server);
gst_rtsp_client_set_thread_pool (client, thread_pool);
g_object_unref (thread_pool);
return client;
}
/**
* gst_rtsp_onvif_server_new:
*
* Create a new #GstRTSPOnvifServer instance.
*
* Returns: (transfer full): a new #GstRTSPOnvifServer
*/
GstRTSPServer *
gst_rtsp_onvif_server_new (void)
{
return g_object_new (GST_TYPE_RTSP_ONVIF_SERVER, NULL);
}
static void
gst_rtsp_onvif_server_class_init (GstRTSPOnvifServerClass * klass)
{
GstRTSPServerClass *server_klass = (GstRTSPServerClass *) klass;
server_klass->create_client = gst_rtsp_onvif_server_create_client;
}
static void
gst_rtsp_onvif_server_init (GstRTSPOnvifServer * server)
{
}

View file

@ -0,0 +1,65 @@
/* GStreamer
* Copyright (C) 2017 Sebastian Dröge <sebastian@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.
*/
#ifndef __GST_RTSP_ONVIF_SERVER_H__
#define __GST_RTSP_ONVIF_SERVER_H__
#include <gst/gst.h>
#include "rtsp-server.h"
#define GST_TYPE_RTSP_ONVIF_SERVER (gst_rtsp_onvif_server_get_type ())
#define GST_IS_RTSP_ONVIF_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_ONVIF_SERVER))
#define GST_IS_RTSP_ONVIF_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_ONVIF_SERVER))
#define GST_RTSP_ONVIF_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTSP_ONVIF_SERVER, GstRTSPOnvifServerClass))
#define GST_RTSP_ONVIF_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_ONVIF_SERVER, GstRTSPOnvifServer))
#define GST_RTSP_ONVIF_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_RTSP_ONVIF_SERVER, GstRTSPOnvifServerClass))
#define GST_RTSP_ONVIF_SERVER_CAST(obj) ((GstRTSPOnvifServer*)(obj))
#define GST_RTSP_ONVIF_SERVER_CLASS_CAST(klass) ((GstRTSPOnvifServerClass*)(klass))
typedef struct GstRTSPOnvifServerClass GstRTSPOnvifServerClass;
typedef struct GstRTSPOnvifServer GstRTSPOnvifServer;
struct GstRTSPOnvifServerClass
{
GstRTSPServerClass parent;
/*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE];
};
struct GstRTSPOnvifServer
{
GstRTSPServer parent;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GST_EXPORT
GType gst_rtsp_onvif_server_get_type (void);
GST_EXPORT
GstRTSPServer *gst_rtsp_onvif_server_new (void);
#define GST_RTSP_ONVIF_BACKCHANNEL_REQUIREMENT "www.onvif.org/ver20/backchannel"
#include "rtsp-onvif-client.h"
#include "rtsp-onvif-media-factory.h"
#include "rtsp-onvif-media.h"
#endif /* __GST_RTSP_ONVIF_SERVER_H__ */

View file

@ -70,6 +70,8 @@ update_sdp_from_tags (GstRTSPStream * stream, GstSDPMedia * stream_media)
GstPad *src_pad; GstPad *src_pad;
src_pad = gst_rtsp_stream_get_srcpad (stream); src_pad = gst_rtsp_stream_get_srcpad (stream);
if (!src_pad)
return;
gst_pad_sticky_events_foreach (src_pad, get_info_from_tags, stream_media); gst_pad_sticky_events_foreach (src_pad, get_info_from_tags, stream_media);
@ -179,8 +181,8 @@ cleanup:
} }
} }
static gboolean gboolean
make_media (GstSDPMessage * sdp, GstSDPInfo * info, gst_rtsp_sdp_make_media (GstSDPMessage * sdp, GstSDPInfo * info,
GstRTSPStream * stream, GstCaps * caps, GstRTSPProfile profile) GstRTSPStream * stream, GstCaps * caps, GstRTSPProfile profile)
{ {
GstSDPMedia *smedia; GstSDPMedia *smedia;
@ -557,7 +559,7 @@ gst_rtsp_sdp_from_stream (GstSDPMessage * sdp, GstSDPInfo * info,
GstRTSPProfile prof = profiles & mask; GstRTSPProfile prof = profiles & mask;
if (prof) if (prof)
res = make_media (sdp, info, stream, caps, prof); res = gst_rtsp_sdp_make_media (sdp, info, stream, caps, prof);
mask <<= 1; mask <<= 1;
} }

View file

@ -40,6 +40,10 @@ gboolean gst_rtsp_sdp_from_media (GstSDPMessage *sdp, GstSDPInfo *in
GST_EXPORT GST_EXPORT
gboolean gst_rtsp_sdp_from_stream (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPStream *stream); gboolean gst_rtsp_sdp_from_stream (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPStream *stream);
GST_EXPORT
gboolean
gst_rtsp_sdp_make_media (GstSDPMessage * sdp, GstSDPInfo * info, GstRTSPStream * stream, GstCaps * caps, GstRTSPProfile profile);
G_END_DECLS G_END_DECLS
#endif /* __GST_RTSP_SDP_H__ */ #endif /* __GST_RTSP_SDP_H__ */