mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 18:50:48 +00:00
354 lines
15 KiB
Text
354 lines
15 KiB
Text
README
|
|
------
|
|
|
|
(Last updated on Fri 30 jan 2009, version 0.10.1.1)
|
|
|
|
This HOWTO describes the basic usage of the GStreamer RTSP libraries and how you
|
|
can build simple server applications with it.
|
|
|
|
* General
|
|
|
|
The server relies heavily on the RTSP infrastructure of GStreamer. This includes
|
|
all of the media acquisition, decoding, encoding, payloading and UDP/TCP
|
|
streaming. We use the gstrtpbin element for all the session management. Most of
|
|
the RTSP message parsing and construction in the server is done using the RTSP
|
|
library that comes with gst-plugins-base.
|
|
|
|
The result is that the server is rather small (a few 1000 lines of code) and easy
|
|
to understand and extend. In its current state of development, things change
|
|
fast, API and ABI are unstable. We encourage people to use it for their various
|
|
use cases and participate by suggesting changes/features.
|
|
|
|
Most of the server is built as a library containing a bunch of GObject objects
|
|
that provide reasonable default functionality but has a fair amount of hooks
|
|
to override the default behaviour.
|
|
|
|
The server currently integrates with the glib mainloop nicely. It is also a
|
|
heavy user of multiple threads. It's currently not meant to be used in
|
|
high-load scenarios and you should probably not put it on a public IP address.
|
|
|
|
* Initialisation
|
|
|
|
You need to initialize GStreamer before using any of the RTSP server functions.
|
|
|
|
#include <gst/gst.h>
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
gst_init (&argc, &argv);
|
|
|
|
...
|
|
}
|
|
|
|
The server itself currently does not have any specific initialisation function
|
|
but that might change in the future.
|
|
|
|
|
|
* Creating the server
|
|
|
|
The first thing you want to do is create a new GstRTSPServer object. This object
|
|
will handle all the new client connections to your server once it is added to a
|
|
GMainLoop. You can create a new server object like this:
|
|
|
|
#include <gst/rtsp-server/rtsp-server.h>
|
|
|
|
GstRTSPServer *server;
|
|
|
|
server = gst_rtsp_server_new ();
|
|
|
|
The server will by default listen on port 8554 for new connections. This can be
|
|
changed by calling gst_rtsp_server_set_port() or with the 'port' GObject
|
|
property. This makes it possible to run multiple server instances listening on
|
|
multiple ports on one machine.
|
|
|
|
We can make the server start listening on its default port by attaching it to a
|
|
mainloop. The following example shows how this is done and will start a server
|
|
on the default 8554 port. For any request we make, we will get a NOT_FOUND
|
|
error code because we need to configure more things before the server becomes
|
|
useful.
|
|
|
|
#include <gst/gst.h>
|
|
#include <gst/rtsp-server/rtsp-server.h>
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
GstRTSPServer *server;
|
|
GMainLoop *loop;
|
|
|
|
gst_init (&argc, &argv);
|
|
|
|
server = gst_rtsp_server_new ();
|
|
|
|
/* make a mainloop for the default context */
|
|
loop = g_main_loop_new (NULL, FALSE);
|
|
|
|
/* attach the server to the default maincontext */
|
|
gst_rtsp_server_attach (server, NULL);
|
|
|
|
/* start serving */
|
|
g_main_loop_run (loop);
|
|
}
|
|
|
|
The server manages two other objects: GstRTSPSessionPool and
|
|
GstRTSPMediaMapping.
|
|
|
|
The GstRTSPSessionPool is an object that keeps track of all the active sessions
|
|
in the server. A session will usually be kept for each client that performed a
|
|
SETUP request for a certain media stream. It contains the configuration that
|
|
the client negotiated with the server to receive the particular stream, ie. the
|
|
transport used and port pairs for UDP along with the state of the streaming.
|
|
The default implementation of the session pool is usually sufficient but
|
|
alternative implementation can be used by the server.
|
|
|
|
The GstRTSPMediaMapping object is more interesting and needs more configuration
|
|
before the server object is useful. This object manages the mapping from a
|
|
request URL to a specific stream and its configuration. We explain in the next
|
|
topic how to configure this object.
|
|
|
|
|
|
* Making url mappings
|
|
|
|
Next we need to define what media is attached to a particular URL. What we want
|
|
to achieve is that when the user asks our server for a specific URL, say /test,
|
|
that we create (or reuse) a GStreamer pipeline that produces one or more RTP
|
|
streams.
|
|
|
|
The object that can create such pipeline is called a GstRTSPMediaFactory object.
|
|
The default implementation of GstRTSPMediaFactory allows you to easily create
|
|
GStreamer pipelines using the gst-launch syntax. It possible to create a
|
|
GstRTSPMediaFactory subclass that uses different methods for constructing
|
|
pipelines.
|
|
|
|
The default GstRTSPMediaFactory can be configured with a gst-launch line that
|
|
produces a toplevel bin (use '(' and ')' around the pipeline description to
|
|
force a toplevel GstBin instead of the default GstPipeline toplevel element).
|
|
The pipeline description should contain elements named payN, one for each
|
|
stream (ex. pay0, pay1, ...). Also, for increased compatibility each stream
|
|
should have a different payload type which can be configured on the payloader.
|
|
|
|
The following code snippet illustrates how to create a media factory that
|
|
creates an RTP feed of an H264 encoded test video signal.
|
|
|
|
GstRTSPMediaFactory *factory;
|
|
|
|
factory = gst_rtsp_media_factory_new ();
|
|
|
|
gst_rtsp_media_factory_set_launch (factory,
|
|
"( videotestsrc ! x264enc ! rtph264pay pt=96 name=pay0 )");
|
|
|
|
Now that we have the media factory, we can attach it to a specific url. To do
|
|
this we get the default GstRTSPMediaMapping from our server and add the url to
|
|
factory mapping to it like this:
|
|
|
|
GstRTSPMediaMapping *mapping;
|
|
|
|
...create server..create factory..
|
|
|
|
/* get the default mapping from the server */
|
|
mapping = gst_rtsp_server_get_media_mapping (server);
|
|
|
|
/* attach the video test signal to the "/test" URL */
|
|
gst_rtsp_media_mapping_add_factory (mapping, "/test", factory);
|
|
g_object_unref (mapping);
|
|
|
|
When starting the server now and directing an RTP client to the URL (like with
|
|
vlc, mplayer or gstreamer):
|
|
|
|
rtsp://localhost:8554/test
|
|
|
|
a test signal will be streamed to the client. The full example code can be
|
|
found in the examples/test-readme.c file.
|
|
|
|
|
|
* more on GstRTSPMediaFactory
|
|
|
|
The GstRTSPMediaFactory is responsible for creating and caching GstRTSPMedia
|
|
objects.
|
|
|
|
A freshly created GstRTSPMedia object from the factory initialy only contains a
|
|
GstElement containing the elements to produce the RTP streams for the media and
|
|
a GArray of GstRTSPMediaStream objects describing the payloader and its source
|
|
pad. The media is unprepared in this state.
|
|
|
|
Usually the url will determine what kind of pipeline should be created. You can
|
|
for example use query parameters to configure certain parts of the pipeline or
|
|
select encoders and payloaders based on some url pattern.
|
|
|
|
When dealing with a live stream from, for example, a webcam, it can be
|
|
interesting to share the pipeline with multiple clients. This must be done when
|
|
only one instance of the video capture element can be used at a time. In this
|
|
case, the shared property of GstRTSPMedia must be used to instruct the default
|
|
GstRTSPMediaFactory implementation to cache the media.
|
|
|
|
When all objects created from a factory can be shared, you can set the shared
|
|
property directly on the factory.
|
|
|
|
* more on GstRTSPMedia
|
|
|
|
After creating the GstRTSPMedia object from the factory, it can be prepared
|
|
with gst_rtsp_media_prepare(). This method will put those objects in a
|
|
GstPipeline and will construct and link the streaming elements and the
|
|
gstrtpbin session manager object.
|
|
|
|
The _prepare() method will then preroll the pipeline in order to figure out the
|
|
caps on the payloaders. After the GstRTSPMedia prerolled it will be in the
|
|
prepared state and can be used for creating SDP files or for streaming to
|
|
clients.
|
|
|
|
The prepare method will also create 2 UDP ports for each stream that can be
|
|
used for sending and receiving RTP/RTCP from clients. These port numbers will
|
|
have to be negotiated with the client in the SETUP requests.
|
|
|
|
When preparing a GstRTSPMedia, a multifdsink is also constructed for streaming
|
|
the stream over TCP when requested.
|
|
|
|
|
|
* the GstRTSPClient object
|
|
|
|
When a server detects a new client connection on its port, it will call its
|
|
accept_client vmethod. The default implementation of this function will create
|
|
a new GstRTCPClient object, will configure the session pool and media mapper
|
|
objects in it and will then call the accept function of the client.
|
|
|
|
The default GstRTSPClient will accept the connection and will attach a watch to
|
|
the server mainloop. In RTSP it is usual to keep the connection
|
|
open between multiple RTSP requests. The client watch will be dispatched by the
|
|
server mainloop when a new GstRTSPMessage is received, which will then be
|
|
handled and a response will be sent.
|
|
|
|
The GstRTSPClient object remains alive for as long as a client has a TCP
|
|
connection open with the server. Since is possible for a client to open and close
|
|
the TCP connection between requests, we cannot store the state related
|
|
to the configured RTSP session in the GstRTSPClient object. This server state
|
|
is instead stored in the GstRTSPSession object.
|
|
|
|
|
|
* GstRTSPSession
|
|
|
|
This object contains state about a specific RTSP session identified with a
|
|
session id. This state contains the configured streams and their associated
|
|
transports.
|
|
|
|
When a GstRTSPClient performs a SETUP request, the server will allocate a new
|
|
GstRTSPSession with a unique session id from the GstRTSPSessionPool. The pool
|
|
maintains a list of all existing sessions and makes sure that no session id is
|
|
used multiple times. The session id is sent to the client so that the client
|
|
can refer to its previously configured state by sending the session id in
|
|
further requests.
|
|
|
|
A client will then use the session id to configure one or more streams,
|
|
identified by their url. This information is kept in a GstRTSPSessionMedia
|
|
structure that is refered to from the GstRTSPSession.
|
|
|
|
|
|
* GstRTSPSessionMedia and GstRTSPSessionStream
|
|
|
|
A GstRTSPSessionMedia is identified by a URL and is referenced by a
|
|
GstRTSPSession. It is created as soon as a client performs a SETUP operation on
|
|
a particular URL. It will contain a link to the GstRTSPMedia object associated
|
|
with the URL along with the state of the media and the configured transports
|
|
for each of the streams in the media.
|
|
|
|
Each SETUP request performed by the client will configure a
|
|
GstRTSPSessionStream object linked to by the GstRTSPSessionMedia structure.
|
|
It will contain the transport information needed to send this stream to the
|
|
client. The GstRTSPSessionStream also contains a link to the GstRTSPMediaStream
|
|
object that generates the actual data to be streamed to the client.
|
|
|
|
Note how GstRTSPMedia and GstRTSPMediaStream (the providers of the data to
|
|
stream) are decoupled from GstRTSPSessionMedia and GstRTSPSessionStream (the
|
|
configuration of how to send this stream to a client) in order to be able to
|
|
send the data of one GstRTSPMedia to multiple clients.
|
|
|
|
|
|
* media control
|
|
|
|
After a client has configured the transports for a GstRTSPMedia and its
|
|
GstRTSPMediaStreams, the client can play/pause/stop the stream.
|
|
|
|
The GstRTSPMedia object was prepared in the DESCRIBE call (or during SETUP when
|
|
the client skipped the DESCRIBE request). As seen earlier, this configures a
|
|
couple of multiudpsink and udpsrc elements to respectively send and receive the
|
|
media to clients.
|
|
|
|
When a client performs a PLAY request, its configured destination UDP ports are
|
|
added to the GstRTSPMediaStream target destinations, at which point data will
|
|
be sent to the client. The corresponding GstRTSPMedia object will be set to the
|
|
PLAYING state if it was not allready in order to send the data to the
|
|
destination.
|
|
|
|
The server needs to prepare an RTP-Info header field in the PLAY response,
|
|
which consists of the sequence number and the RTP timestamp of the next RTP
|
|
packet. In order to achive this, the server queries the payloaders for this
|
|
information when it prerolled the pipeline.
|
|
|
|
When a client performs a PAUSE request, the destination UDP ports are removed
|
|
from the GstRTSPMediaStream object and the GstRTSPMedia object is set to PAUSED
|
|
if no other destinations are configured anymore.
|
|
|
|
|
|
* seeking
|
|
|
|
A seek is performed when a client sends a Range header in the PLAY request.
|
|
This only works when not dealing with shared (live) streams.
|
|
|
|
The server performs a GStreamer flushing seek on the media, waits for the
|
|
pipeline to preroll again and then responds to the client after collecting the
|
|
new RTP sequence number and timestamp from the payloaders.
|
|
|
|
|
|
* session management
|
|
|
|
The server has to react to clients that suddenly disappear because of network
|
|
problems or otherwise. It needs to make sure that it can reasonable free the
|
|
resources that are used by the various objects in use for streaming when the
|
|
client appears to be gone.
|
|
|
|
Each of the GstRTSPSession objects managed by a GstRTSPSessionPool has
|
|
therefore a last_access field that contains the timestamp of when activity from
|
|
a client was last recorded.
|
|
|
|
Various ways exist to detect activity from a client:
|
|
|
|
- RTSP keepalive requests. When a client is receiving RTP data, the RTSP TCP
|
|
connection is largely unused. It is the client responsability to
|
|
periodically send keep-alive requests over the TCP channel.
|
|
|
|
Whenever a keep-alive request is received by the server (any request that
|
|
contains a session id, usually an OPTION or GET_PARAMETER request) the
|
|
last_access of the session is updated.
|
|
|
|
- Since it is not required for a client to keep the RTSP TCP connection open
|
|
while streaming, gst-rtsp-server also detects activity from clients by
|
|
looking at the RTCP messages it receives.
|
|
|
|
When an RTCP message is received from a client, the server looks in its list
|
|
of active ports if this message originates from a known host/port pair that
|
|
is currently active in a GstRTSPSession. If this is the case, the session is
|
|
kept alive.
|
|
|
|
Since the server does not know anything about the port number that will be
|
|
used by the client to send RTCP, this method does not always work. Later
|
|
RTSP RFCs will include support for negotiating this port number with the
|
|
server. Most clients however use the same port number for sending and
|
|
receiving RTCP exactly for this reason.
|
|
|
|
If there was no activity in a particular session for a long time (by default 60
|
|
seconds), the sessionpool will destroy the session along with all related
|
|
objects and media as if a TEARDOWN happened from the client.
|
|
|
|
|
|
* TEARDOWN
|
|
|
|
A TEARDOWN request will first location the GstRTSPSessionMedia of the URL. It
|
|
will then remove all transports from the streams, making sure that streaming
|
|
stops to the client. It will then remove the GstRTSPSessionMedia and
|
|
GstRTSPSessionStream structures. Finally the GstRTSPSession is released back
|
|
into the pool.
|
|
|
|
When there are no more references to the GstRTSPMedia, the media pipeline is
|
|
shut down and destroyed.
|
|
|
|
|