mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
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:
parent
231700b2bb
commit
72dc8acd86
17 changed files with 1497 additions and 7 deletions
|
@ -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">
|
||||||
|
|
|
@ -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
1
examples/.gitignore
vendored
|
@ -13,3 +13,4 @@ test-uri
|
||||||
test-auth
|
test-auth
|
||||||
test-netclock
|
test-netclock
|
||||||
test-netclock-client
|
test-netclock-client
|
||||||
|
test-onvif-backchannel
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
71
examples/test-onvif-backchannel.c
Normal file
71
examples/test-onvif-backchannel.c
Normal 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;
|
||||||
|
}
|
|
@ -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 =
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
100
gst/rtsp-server/rtsp-onvif-client.c
Normal file
100
gst/rtsp-server/rtsp-onvif-client.c
Normal 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)
|
||||||
|
{
|
||||||
|
}
|
57
gst/rtsp-server/rtsp-onvif-client.h
Normal file
57
gst/rtsp-server/rtsp-onvif-client.h
Normal 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__ */
|
491
gst/rtsp-server/rtsp-onvif-media-factory.c
Normal file
491
gst/rtsp-server/rtsp-onvif-media-factory.c
Normal 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);
|
||||||
|
}
|
77
gst/rtsp-server/rtsp-onvif-media-factory.h
Normal file
77
gst/rtsp-server/rtsp-onvif-media-factory.h
Normal 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__ */
|
330
gst/rtsp-server/rtsp-onvif-media.c
Normal file
330
gst/rtsp-server/rtsp-onvif-media.c
Normal 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;
|
||||||
|
}
|
66
gst/rtsp-server/rtsp-onvif-media.h
Normal file
66
gst/rtsp-server/rtsp-onvif-media.h
Normal 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__ */
|
100
gst/rtsp-server/rtsp-onvif-server.c
Normal file
100
gst/rtsp-server/rtsp-onvif-server.c
Normal 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)
|
||||||
|
{
|
||||||
|
}
|
65
gst/rtsp-server/rtsp-onvif-server.h
Normal file
65
gst/rtsp-server/rtsp-onvif-server.h
Normal 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__ */
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
Loading…
Reference in a new issue