Commit 505fe698 authored by Thibault Saunier's avatar Thibault Saunier 🌵

Merging gst-rtsp-server

parents f09f27a9 8d4a9f37
*~
/build
/_build
/b/
include: "https://gitlab.freedesktop.org/gstreamer/gst-ci/raw/master/gitlab/ci_template.yml"
Wim Taymans <wim.taymans@collabora.co.uk>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
gst-rtsp-server is a library on top of GStreamer for building an RTSP server
There are some examples in the examples/ directory and more comprehensive
documentation in docs/README.
This is GStreamer gst-rtsp-server 1.17.0.1.
The GStreamer team is thrilled to announce a new major feature release in the
stable 1.0 API series of your favourite cross-platform multimedia framework!
As always, this release is again packed with new features, bug fixes and
other improvements.
The 1.16 release series adds new features on top of the 1.14 series and is
part of the API and ABI-stable 1.x release series of the GStreamer multimedia
framework.
Full release notes will one day be found at:
https://gstreamer.freedesktop.org/releases/1.16/
Binaries for Android, iOS, Mac OS X and Windows will usually be provided
shortly after the release.
This module will not be very useful by itself and should be used in conjunction
with other GStreamer modules for a complete multimedia experience.
- gstreamer: provides the core GStreamer libraries and some generic plugins
- gst-plugins-base: a basic set of well-supported plugins and additional
media-specific GStreamer helper libraries for audio,
video, rtsp, rtp, tags, OpenGL, etc.
- gst-plugins-good: a set of well-supported plugins under our preferred
license
- gst-plugins-ugly: a set of well-supported plugins which might pose
problems for distributors
- gst-plugins-bad: a set of plugins of varying quality that have not made
their way into one of core/base/good/ugly yet, for one
reason or another. Many of these are are production quality
elements, but may still be missing documentation or unit
tests; others haven't passed the rigorous quality testing
we expect yet.
- gst-libav: a set of codecs plugins based on the ffmpeg library. This is
where you can find audio and video decoders and encoders
for a wide variety of formats including H.264, AAC, etc.
- gstreamer-vaapi: hardware-accelerated video decoding and encoding using
VA-API on Linux. Primarily for Intel graphics hardware.
- gst-omx: hardware-accelerated video decoding and encoding, primarily for
embedded Linux systems that provide an OpenMax
implementation layer such as the Raspberry Pi.
- gst-rtsp-server: library to serve files or streaming pipelines via RTSP
- gst-editing-services: library an plugins for non-linear editing
==== Download ====
You can find source releases of gstreamer in the download
directory: https://gstreamer.freedesktop.org/src/gstreamer/
The git repository and details how to clone it can be found at
https://cgit.freedesktop.org/gstreamer/gstreamer/
==== Homepage ====
The project's website is https://gstreamer.freedesktop.org/
==== Support and Bugs ====
We have recently moved from GNOME Bugzilla to GitLab on freedesktop.org
for bug reports and feature requests:
https://gitlab.freedesktop.org/gstreamer
Please submit patches via GitLab as well, in form of Merge Requests. See
https://gstreamer.freedesktop.org/documentation/contribute/
for more details.
For help and support, please subscribe to and send questions to the
gstreamer-devel mailing list (see below for details).
There is also a #gstreamer IRC channel on the Freenode IRC network.
==== Developers ====
GStreamer source code repositories can be found on GitLab on freedesktop.org:
https://gitlab.freedesktop.org/gstreamer
and can also be cloned from there and this is also where you can submit
Merge Requests or file issues for bugs or feature requests.
Interested developers of the core library, plugins, and applications should
subscribe to the gstreamer-devel list:
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
You need to have GStreamer. You can use an installed version of
GStreamer or from its build dir.
- use a config file to configure the server
- error recovery
This diff is collapsed.
RTSP server
-----------
This directory contains an example RTSP server built with various GStreamer
components and libraries. It also uses GStreamer for all of the multimedia
procesing and RTP bits. The following features are implemented:
-
Server Design
-------------
The toplevel component of the server is a GstRTSPServer object. This object
creates and binds on the server socket and attaches into the mainloop.
For each request a new GstRTSPClient object is created that will accept the
request and a thread is started to handle further communication with the
client until the connection is closed.
When a client issues a SETUP request we create a GstRTSPSession object,
identified with a sessionid, that will keep track of the state of a client.
The object is destroyed when a TEARDOWN request is made for that sessionid.
We also maintain a pool of URL to media pipeline mappings. Each url is mapped to
an object that is able to provide a pipeline for that media. We provide
pipelines to stream live captured data, on-demand file streaming or on-demand
transcoding of a file or stream.
A pool of currently active pipelines is also maintained. Usually the active
pipelines are in use by one or more GstRTSPSession objects. An active pipeline
becomes inactive when no more sessions refer to it.
A client can choose to start a new pipeline or join a currently active pipeline.
Some active pipeline cannot be joined (such as on-demand streams) but a new
instance of that pipeline can be created.
This diff is collapsed.
# GStreamer RTSP Server
build_hotdoc = false
if meson.is_cross_build()
if get_option('doc').enabled()
error('Documentation enabled but building the doc while cross building is not supported yet.')
endif
message('Documentation not built as building it while cross building is not supported yet.')
subdir_done()
endif
required_hotdoc_extensions = ['gi-extension', 'gst-extension']
if gst_dep.type_name() == 'internal'
gst_proj = subproject('gstreamer')
plugins_cache_generator = gst_proj.get_variable('plugins_cache_generator')
else
required_hotdoc_extensions += ['gst-extension']
plugins_cache_generator = find_program(join_paths(gst_dep.get_pkgconfig_variable('libexecdir'), 'gstreamer-' + api_version, 'gst-plugins-doc-cache-generator'),
required: false)
endif
plugins_cache = join_paths(meson.current_source_dir(), 'gst_plugins_cache.json')
if plugins.length() == 0
message('All rtsp-server plugins have been disabled')
elif plugins_cache_generator.found()
plugins_doc_dep = custom_target('rtsp-server-plugins-doc-cache',
command: [plugins_cache_generator, plugins_cache, '@OUTPUT@', '@INPUT@'],
input: plugins,
output: 'gst_plugins_cache.json',
)
else
warning('GStreamer plugin inspector for documentation not found, can\'t update the cache')
endif
hotdoc_p = find_program('hotdoc', required: get_option('doc'))
if not hotdoc_p.found()
message('Hotdoc not found, not building the documentation')
subdir_done()
endif
hotdoc = import('hotdoc')
foreach extension: required_hotdoc_extensions
if not hotdoc.has_extensions(extension)
if get_option('doc').enabled()
error('Documentation enabled but @0@ missing'.format(extension))
endif
message('@0@ extension not found, not building documentation'.format(extension))
subdir_done()
endif
endforeach
if not build_gir
if get_option('doc').enabled()
error('Documentation enabled but introspection not built.')
endif
message('Introspection not built, can\'t build the documentation')
subdir_done()
endif
build_hotdoc = true
hotdoc = import('hotdoc')
libs_doc = [hotdoc.generate_doc('gst-rtsp-server',
project_version: api_version,
gi_c_sources: ['../gst/rtsp-server/*.[hc]'],
gi_sources: rtsp_server_gir[0].full_path(),
sitemap: 'sitemap.txt',
index: 'index.md',
gi_index: 'index.md',
gi_smart_index: true,
gi_order_generated_subpages: true,
)]
plugins_doc = [hotdoc.generate_doc('rtspclientsink',
project_version: api_version,
sitemap: 'plugin-sitemap.txt',
index: 'plugin-index.md',
gst_index: 'plugin-index.md',
gst_c_sources: ['../gst/rtsp-sink/*.[ch]'],
gst_dl_sources: [rtspsink.full_path()],
gst_smart_index: true,
dependencies: gst_rtsp_server_deps + [rtspsink],
gst_cache_file: plugins_cache,
gst_plugin_name: 'rtspclientsink',
)]
doc = libs_doc[0]
# rtspclientsink
gi-index
gst-index
examples = [
'test-appsrc',
'test-appsrc2',
'test-auth',
'test-auth-digest',
'test-launch',
'test-mp4',
'test-multicast2',
'test-multicast',
'test-netclock',
'test-netclock-client',
'test-ogg',
'test-onvif-client',
'test-onvif-server',
'test-readme',
'test-record-auth',
'test-record',
'test-sdp',
'test-uri',
'test-video',
'test-video-rtx',
]
foreach example : examples
executable(example, '@0@.c'.format(example),
c_args : rtspserver_args,
include_directories : rtspserver_incs,
dependencies : [glib_dep, gst_dep, gstapp_dep, gstnet_dep, gst_rtsp_server_dep],
install: false)
endforeach
cgroup_dep = dependency('libcgroup', version : '>= 0.26', required : false)
if cgroup_dep.found()
executable('test-cgroups', 'test-cgroups.c',
c_args : rtspserver_args,
include_directories : rtspserver_incs,
dependencies : [glib_dep, gst_dep, gstnet_dep, gst_rtsp_server_dep, cgroup_dep],
install: false)
endif
/* GStreamer
* Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.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-server.h>
typedef struct
{
gboolean white;
GstClockTime timestamp;
} MyContext;
/* called when we need to give data to appsrc */
static void
need_data (GstElement * appsrc, guint unused, MyContext * ctx)
{
GstBuffer *buffer;
guint size;
GstFlowReturn ret;
size = 385 * 288 * 2;
buffer = gst_buffer_new_allocate (NULL, size, NULL);
/* this makes the image black/white */
gst_buffer_memset (buffer, 0, ctx->white ? 0xff : 0x0, size);
ctx->white = !ctx->white;
/* increment the timestamp every 1/2 second */
GST_BUFFER_PTS (buffer) = ctx->timestamp;
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 2);
ctx->timestamp += GST_BUFFER_DURATION (buffer);
g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
gst_buffer_unref (buffer);
}
/* called when a new media pipeline is constructed. We can query the
* pipeline and configure our appsrc */
static void
media_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media,
gpointer user_data)
{
GstElement *element, *appsrc;
MyContext *ctx;
/* get the element used for providing the streams of the media */
element = gst_rtsp_media_get_element (media);
/* get our appsrc, we named it 'mysrc' with the name property */
appsrc = gst_bin_get_by_name_recurse_up (GST_BIN (element), "mysrc");
/* this instructs appsrc that we will be dealing with timed buffer */
gst_util_set_object_arg (G_OBJECT (appsrc), "format", "time");
/* configure the caps of the video */
g_object_set (G_OBJECT (appsrc), "caps",
gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "RGB16",
"width", G_TYPE_INT, 384,
"height", G_TYPE_INT, 288,
"framerate", GST_TYPE_FRACTION, 0, 1, NULL), NULL);
ctx = g_new0 (MyContext, 1);
ctx->white = FALSE;
ctx->timestamp = 0;
/* make sure ther datais freed when the media is gone */
g_object_set_data_full (G_OBJECT (media), "my-extra-data", ctx,
(GDestroyNotify) g_free);
/* install the callback that will be called when a buffer is needed */
g_signal_connect (appsrc, "need-data", (GCallback) need_data, ctx);
gst_object_unref (appsrc);
gst_object_unref (element);
}
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_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_media_factory_new ();
gst_rtsp_media_factory_set_launch (factory,
"( appsrc name=mysrc ! videoconvert ! x264enc ! rtph264pay name=pay0 pt=96 )");
/* notify when our media is ready, This is called whenever someone asks for
* the media and a new pipeline with our appsrc is created */
g_signal_connect (factory, "media-configure", (GCallback) media_configure,
NULL);
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
/* don't need the ref to the mounts 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;
}
/* GStreamer
* Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.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/app/app.h>
#include <gst/rtsp-server/rtsp-server.h>
typedef struct
{
GstElement *generator_pipe;
GstElement *vid_appsink;
GstElement *vid_appsrc;
GstElement *aud_appsink;
GstElement *aud_appsrc;
} MyContext;
/* called when we need to give data to an appsrc */
static void
need_data (GstElement * appsrc, guint unused, MyContext * ctx)
{
GstSample *sample;
GstFlowReturn ret;
if (appsrc == ctx->vid_appsrc)
sample = gst_app_sink_pull_sample (GST_APP_SINK (ctx->vid_appsink));
else
sample = gst_app_sink_pull_sample (GST_APP_SINK (ctx->aud_appsink));
if (sample) {
GstBuffer *buffer = gst_sample_get_buffer (sample);
GstSegment *seg = gst_sample_get_segment (sample);
GstClockTime pts, dts;
/* Convert the PTS/DTS to running time so they start from 0 */
pts = GST_BUFFER_PTS (buffer);
if (GST_CLOCK_TIME_IS_VALID (pts))
pts = gst_segment_to_running_time (seg, GST_FORMAT_TIME, pts);
dts = GST_BUFFER_DTS (buffer);
if (GST_CLOCK_TIME_IS_VALID (dts))
dts = gst_segment_to_running_time (seg, GST_FORMAT_TIME, dts);
if (buffer) {
/* Make writable so we can adjust the timestamps */
buffer = gst_buffer_copy (buffer);
GST_BUFFER_PTS (buffer) = pts;
GST_BUFFER_DTS (buffer) = dts;
g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
}
/* we don't need the appsink sample anymore */
gst_sample_unref (sample);
}
}
static void
ctx_free (MyContext * ctx)
{
gst_element_set_state (ctx->generator_pipe, GST_STATE_NULL);
gst_object_unref (ctx->generator_pipe);
gst_object_unref (ctx->vid_appsrc);
gst_object_unref (ctx->vid_appsink);
gst_object_unref (ctx->aud_appsrc);
gst_object_unref (ctx->aud_appsink);
g_free (ctx);
}
/* called when a new media pipeline is constructed. We can query the
* pipeline and configure our appsrc */
static void
media_configure (GstRTSPMediaFactory * factory, GstRTSPMedia * media,
gpointer user_data)
{
GstElement *element, *appsrc, *appsink;
GstCaps *caps;
MyContext *ctx;
ctx = g_new0 (MyContext, 1);
/* This pipeline generates H264 video and PCM audio. The appsinks are kept small so that if delivery is slow,
* encoded buffers are dropped as needed. There's slightly more buffers (32) allowed for audio */
ctx->generator_pipe =
gst_parse_launch
("videotestsrc is-live=true ! x264enc speed-preset=superfast tune=zerolatency ! h264parse ! appsink name=vid max-buffers=1 drop=true "
"audiotestsrc is-live=true ! appsink name=aud max-buffers=32 drop=true",
NULL);
/* make sure the data is freed when the media is gone */
g_object_set_data_full (G_OBJECT (media), "rtsp-extra-data", ctx,
(GDestroyNotify) ctx_free);
/* get the element (bin) used for providing the streams of the media */
element = gst_rtsp_media_get_element (media);
/* Find the 2 app sources (video / audio), and configure them, connect to the
* signals to request data */
/* configure the caps of the video */
caps = gst_caps_new_simple ("video/x-h264",
"stream-format", G_TYPE_STRING, "byte-stream",
"alignment", G_TYPE_STRING, "au",
"width", G_TYPE_INT, 384, "height", G_TYPE_INT, 288,
"framerate", GST_TYPE_FRACTION, 15, 1, NULL);
ctx->vid_appsrc = appsrc =
gst_bin_get_by_name_recurse_up (GST_BIN (element), "videosrc");
ctx->vid_appsink = appsink =
gst_bin_get_by_name (GST_BIN (ctx->generator_pipe), "vid");
gst_util_set_object_arg (G_OBJECT (appsrc), "format", "time");
g_object_set (G_OBJECT (appsrc), "caps", caps, NULL);
g_object_set (G_OBJECT (appsink), "caps", caps, NULL);
/* install the callback that will be called when a buffer is needed */
g_signal_connect (appsrc, "need-data", (GCallback) need_data, ctx);
gst_caps_unref (caps);
caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S24BE",
"layout", G_TYPE_STRING, "interleaved", "rate", G_TYPE_INT, 48000,
"channels", G_TYPE_INT, 2, NULL);
ctx->aud_appsrc = appsrc =
gst_bin_get_by_name_recurse_up (GST_BIN (element), "audiosrc");
ctx->aud_appsink = appsink =
gst_bin_get_by_name (GST_BIN (ctx->generator_pipe), "aud");
gst_util_set_object_arg (G_OBJECT (appsrc), "format", "time");
g_object_set (G_OBJECT (appsrc), "caps", caps, NULL);
g_object_set (G_OBJECT (appsink), "caps", caps, NULL);
g_signal_connect (appsrc, "need-data", (GCallback) need_data, ctx);
gst_caps_unref (caps);
gst_element_set_state (ctx->generator_pipe, GST_STATE_PLAYING);
gst_object_unref (element);
}
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_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_media_factory_new ();
gst_rtsp_media_factory_set_launch (factory,
"( appsrc name=videosrc ! h264parse ! rtph264pay name=pay0 pt=96 "
" appsrc name=audiosrc ! audioconvert ! rtpL24pay name=pay1 pt=97 )");
/* notify when our media is ready, This is called whenever someone asks for
* the media and a new pipeline with our appsrc is created */
g_signal_connect (factory, "media-configure", (GCallback) media_configure,
NULL);
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
/* don't need the ref to the mounts 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;
}
<
/* GStreamer
* Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.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