Gstreamer daemon design
Clone this wiki locally
The GStreamer Daemon, called gstd, is a multi-threaded application for controlling audio and video streaming using D-Bus messages. GStreamer Daemon is written in Vala to simplify gobject management. The Vala GStreamer binding is used to simplify access to the GStreamer library. Although GStreamer Daemon was first used in embedded devices, there are no dependencies beyond GStreamer and D-Bus, and access to a Vala compiler if you want to modify the code.
Table of Contents
A system that uses GStreamer Daemon needs to include D-Bus Daemon, GStreamer libraries, and one or more D-Bus aware applications that are exchanging messages and signals with GStreamer Daemon.
GStreamer Daemon registers a service on D-Bus named com.ridgerun.gstreamer.gstd. A GStreamer Daemon command line parameter allows the messages to flow over either the system bus or the session bus. Clients use this same service name and bus to connect to GStreamer Daemon. There is support for two classes: Factory and Pipeline. GStreamer Daemon registers a factory object with D-Bus, with the path /com/ridgerun/gstreamer/gstd/factory. The factory is used to create pipelines, which will create a dynamice D-Bus pipeline object that is used to control the pipeline.
The GStreamer Daemon interacts with the rest of the Linux system via several external interfaces.
When you start gstd, you can pass additional information on the command line. The standard GStreamer command line parameters are supported.
In addition, a few GStreamer Daemon specific command line parameters are supported as can be seen in the src/main.vala' source file.
D-Bus messages are used to create GStreamer pipelines, control the various pipelines, monitor the pipelines, and finally destroy a pipeline when it is no longer needed. Multiple applications can exchange D-Bus messages with gstd to interact with multiple pipelines (or even a single pipeline). For example, an audio stream may be started at a device using a graphical interface with touch screen support. Then the user moves to a different location and uses a web browser to interact with the device to adjust the volume. The user could even use an IR remote to control the audio playback. There is an extensive set of gstd supported D-Bus messages.
Like gst-launch, the first steps is to create a GStreamer pipeline. These created pipelines will naturally use GStreamer source and sink elements that can be viewed as a gstd external interface. Examples include reading audio or video data from a file, streaming over a network interface, sending audio data to the Linux ALSA subsystem, etc.
GStreamer Daemon is a relatively simple application, around 700 lines of Vala code plus 250 lines of XML encoded messages. The main gstd parts include the main program, gstd factory, gstd pipeline, with helper modules for Posix signal handling, and a watchdog facility.
gstd make extensive use of the Vala bindings for GStreamer and D-Bus. The use of Vala and library bindings greatly simplifies the code, but can make it hard to follow for a first time Vala user.
A couple points for the uninitiated:
- All D-Bus messages are defined in the XML files, with the XML file used by the D-Bus binding to map a received message to an API invocation. For example, in main.vala, you will see conn.register_object() to register the factory. In the com.ridgerun.gstreamer.gstd.FactoryInterface.xml file, you will find the Create D-Bus method definition, along with the parameter list. In gstd-factory.vala, you will find the string Create(string description), which matches the XML definition. The D-Bus Vala binding causes the factory Create() function to be call when the Create D-Bus method is received by gstd.
- The standard glib main loop is used for handing all events. First handlers of events of interest are registered (in this case Factory D-Bus method calls), then the main loop is run forever. This is a common approach for event driven GUI style application development.
There is a main program, main.vala, that handles processing the command line arguments, interacts with the D-Bus daemon to receive gstd factory messages,creates a factory object and associates it as the handler of the received gstd factory messages, and runs the main loop forever.
When one of the gstd factory D-Bus messages (or more accurately, D-Bus method calls) is received, it is processed by the gstd Factory object.
Using the D-Bus Vala binding, the factory XML describes the format of all the D-Bus messages. There is a one-to-one correspondence between the D-Bus message and a factory method.
Currently gstd supports up to 20 simultaneous pipelines. A pipeline is created by passing a gst-launch style string description of the pipeline. The object path of created pipeline is returned. The pipeline is not started (left in the NULL GStreamer state).
In response to the create pipeline request, the gstd factory creates a pipeline object and adds it to the list of existing pipelines. The format for the pipeline object D-Bus path is /com/ridgerun/gstreamer/gstd/pipe with an appended integer.
An existing pipeline can be destroyed by including the D-Bus object path of the pipeline to be destroyed in the factory Destroy method call. The pipeline entry in the list of existing pipeline is removed, causing the pipeline object to be unreferenced, and thus destroyed. See the description in the pipeline factory section on what happens to a pipeline object when it is destroyed.
Anoter D-Bus method call, DestroyAll, removes all pipelines and frees the related resources.
The D-Bus object path of all entries in the list of existing pipelines are returned (as strings), separated by commas.
Each time the gstd factory receives a D-Bus Create method call, a new pipeline object is created. Once a pipeline exists, the pipeline can be controlled using D-Bus pipeline method calls.
Using the D-Bus Vala binding and the pipeline XML description, there is a one-to-one correspondence between the D-Bus message and a pipeline method.
In a similar way, all the pipeline D-Bus methods are mapped directly to GStreamer concepts and functionality. The only unique notion is there are both synchronous and asynchronous methods for play, pause, and null. The asynchronous methods are useful to make graphical user interfaces more responsive.
The gstd pipeline registers for gst bus signals. When one is received, the related information is sent on D-Bus to com.ridgerun.gstreamer.gstd.PipelineInterface messages.