Application development manual

This commit is contained in:
Mathieu Duponchelle 2016-06-04 08:55:52 +02:00
parent 70b736f436
commit f0206f71a9
51 changed files with 7079 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
images/bin-element.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
images/clocks.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
images/communication.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
images/filter-element.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
images/hello-world.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/linked-elements.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
images/mime-world.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
images/simple-player.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
images/sink-element.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
images/src-element.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
images/thread-buffering.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

21
manual-advanced.md Normal file
View file

@ -0,0 +1,21 @@
---
title: Advanced GStreamer concepts
...
# Advanced GStreamer concepts
In this part we will cover the more advanced features of GStreamer. With
the basics you learned in the previous part you should be able to create
a *simple* application. However, GStreamer provides much more candy than
just the basics of playing back audio files. In this chapter, you will
learn more of the low-level features and internals of GStreamer.
Some parts of this part will serve mostly as an explanation of how
GStreamer works internally; they are not actually needed for actual
application development. This includes chapters such as the ones
covering scheduling, autoplugging and synchronization. Other chapters,
however, discuss more advanced ways of pipeline-application interaction,
and can turn out to be very useful for certain applications. This
includes the chapters on metadata, querying and events, interfaces,
dynamic parameters and pipeline data manipulation.

18
manual-appendices.md Normal file
View file

@ -0,0 +1,18 @@
---
title: Appendices
...
# Appendices
By now, you've learned all about the internals of GStreamer and
application programming using the GStreamer framework. This part will go
into some random bits that are useful to know if you're going to use
GStreamer for serious application programming. It will touch upon things
related to integration with popular desktop environments that we run on
(GNOME, KDE, OS X, Windows), it will shortly explain how applications
included with GStreamer can help making your life easier, and some
information on debugging.
In addition, we also provide a porting guide which will explain easily
how to port GStreamer-0.10 applications to GStreamer-1.0.

188
manual-autoplugging.md Normal file
View file

@ -0,0 +1,188 @@
---
title: Autoplugging
...
# Autoplugging
In [Your first application](manual-helloworld.md), you've learned to
build a simple media player for Ogg/Vorbis files. By using alternative
elements, you are able to build media players for other media types,
such as Ogg/Speex, MP3 or even video formats. However, you would rather
want to build an application that can automatically detect the media
type of a stream and automatically generate the best possible pipeline
by looking at all available elements in a system. This process is called
autoplugging, and GStreamer contains high-quality autopluggers. If
you're looking for an autoplugger, don't read any further and go to
[Playback Components](manual-playback-components.md). This chapter will
explain the *concept* of autoplugging and typefinding. It will explain
what systems GStreamer includes to dynamically detect the type of a
media stream, and how to generate a pipeline of decoder elements to
playback this media. The same principles can also be used for
transcoding. Because of the full dynamicity of this concept, GStreamer
can be automatically extended to support new media types without needing
any adaptations to its autopluggers.
We will first introduce the concept of Media types as a dynamic and
extendible way of identifying media streams. After that, we will
introduce the concept of typefinding to find the type of a media stream.
Lastly, we will explain how autoplugging and the GStreamer registry can
be used to setup a pipeline that will convert media from one mediatype
to another, for example for media decoding.
# Media types as a way to identify streams
We have previously introduced the concept of capabilities as a way for
elements (or, rather, pads) to agree on a media type when streaming data
from one element to the next (see [Capabilities of a
pad](manual-pads.md#capabilities-of-a-pad)). We have explained that a
capability is a combination of a media type and a set of properties. For
most container formats (those are the files that you will find on your
hard disk; Ogg, for example, is a container format), no properties are
needed to describe the stream. Only a media type is needed. A full list
of media types and accompanying properties can be found in [the Plugin
Writer's
Guide](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/section-types-definitions.html).
An element must associate a media type to its source and sink pads when
it is loaded into the system. GStreamer knows about the different
elements and what type of data they expect and emit through the
GStreamer registry. This allows for very dynamic and extensible element
creation as we will see.
In [Your first application](manual-helloworld.md), we've learned to
build a music player for Ogg/Vorbis files. Let's look at the media types
associated with each pad in this pipeline. [The Hello world pipeline
with media types](#the-hello-world-pipeline-with-media-types) shows what
media type belongs to each pad in this pipeline.
![The Hello world pipeline with media types](images/mime-world.png
"fig:")
Now that we have an idea how GStreamer identifies known media streams,
we can look at methods GStreamer uses to setup pipelines for media
handling and for media type detection.
# Media stream type detection
Usually, when loading a media stream, the type of the stream is not
known. This means that before we can choose a pipeline to decode the
stream, we first need to detect the stream type. GStreamer uses the
concept of typefinding for this. Typefinding is a normal part of a
pipeline, it will read data for as long as the type of a stream is
unknown. During this period, it will provide data to all plugins that
implement a typefinder. When one of the typefinders recognizes the
stream, the typefind element will emit a signal and act as a passthrough
module from that point on. If no type was found, it will emit an error
and further media processing will stop.
Once the typefind element has found a type, the application can use this
to plug together a pipeline to decode the media stream. This will be
discussed in the next section.
Plugins in GStreamer can, as mentioned before, implement typefinder
functionality. A plugin implementing this functionality will submit a
media type, optionally a set of file extensions commonly used for this
media type, and a typefind function. Once this typefind function inside
the plugin is called, the plugin will see if the data in this media
stream matches a specific pattern that marks the media type identified
by that media type. If it does, it will notify the typefind element of
this fact, telling which mediatype was recognized and how certain we are
that this stream is indeed that mediatype. Once this run has been
completed for all plugins implementing a typefind functionality, the
typefind element will tell the application what kind of media stream it
thinks to have recognized.
The following code should explain how to use the typefind element. It
will print the detected media type, or tell that the media type was not
found. The next section will introduce more useful behaviours, such as
plugging together a decoding pipeline.
```
#include <gst/gst.h>
[.. my_bus_callback goes here ..]
static gboolean
idle_exit_loop (gpointer data)
{
g_main_loop_quit ((GMainLoop *) data);
/* once */
return FALSE;
}
static void
cb_typefound (GstElement *typefind,
guint probability,
GstCaps *caps,
gpointer data)
{
GMainLoop *loop = data;
gchar *type;
type = gst_caps_to_string (caps);
g_print ("Media type %s found, probability %d%%\n", type, probability);
g_free (type);
/* since we connect to a signal in the pipeline thread context, we need
* to set an idle handler to exit the main loop in the mainloop context.
* Normally, your app should not need to worry about such things. */
g_idle_add (idle_exit_loop, loop);
}
gint
main (gint argc,
gchar *argv[])
{
GMainLoop *loop;
GstElement *pipeline, *filesrc, *typefind, *fakesink;
GstBus *bus;
/* init GStreamer */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* check args */
if (argc != 2) {
g_print ("Usage: %s <filename>\n", argv[0]);
return -1;
}
/* create a new pipeline to hold the elements */
pipeline = gst_pipeline_new ("pipe");
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, my_bus_callback, NULL);
gst_object_unref (bus);
/* create file source and typefind element */
filesrc = gst_element_factory_make ("filesrc", "source");
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
typefind = gst_element_factory_make ("typefind", "typefinder");
g_signal_connect (typefind, "have-type", G_CALLBACK (cb_typefound), loop);
fakesink = gst_element_factory_make ("fakesink", "sink");
/* setup */
gst_bin_add_many (GST_BIN (pipeline), filesrc, typefind, fakesink, NULL);
gst_element_link_many (filesrc, typefind, fakesink, NULL);
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
g_main_loop_run (loop);
/* unset */
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
```
Once a media type has been detected, you can plug an element (e.g. a
demuxer or decoder) to the source pad of the typefind element, and
decoding of the media stream will start right after.
# Dynamically autoplugging a pipeline
See [Playback Components](manual-playback-components.md) for using the
high level object that you can use to dynamically construct pipelines.

148
manual-bins.md Normal file
View file

@ -0,0 +1,148 @@
---
title: Bins
...
# Bins
A bin is a container element. You can add elements to a bin. Since a bin
is an element itself, a bin can be handled in the same way as any other
element. Therefore, the whole previous chapter
([Elements](manual-elements.md)) applies to bins as well.
# What are bins
Bins allow you to combine a group of linked elements into one logical
element. You do not deal with the individual elements anymore but with
just one element, the bin. We will see that this is extremely powerful
when you are going to construct complex pipelines since it allows you to
break up the pipeline in smaller chunks.
The bin will also manage the elements contained in it. It will perform
state changes on the elements as well as collect and forward bus
messages.
![Visualisation of a bin with some elements in
it](images/bin-element.png "fig:")
There is one specialized type of bin available to the GStreamer
programmer:
- A pipeline: a generic container that manages the synchronization and
bus messages of the contained elements. The toplevel bin has to be a
pipeline, every application thus needs at least one of these.
# Creating a bin
Bins are created in the same way that other elements are created, i.e.
using an element factory. There are also convenience functions available
(`gst_bin_new ()` and `gst_pipeline_new ()`). To add elements to a bin
or remove elements from a bin, you can use `gst_bin_add ()` and
`gst_bin_remove ()`. Note that the bin that you add an element to will
take ownership of that element. If you destroy the bin, the element will
be dereferenced with it. If you remove an element from a bin, it will be
dereferenced automatically.
```
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElement *bin, *pipeline, *source, *sink;
/* init */
gst_init (&argc, &argv);
/* create */
pipeline = gst_pipeline_new ("my_pipeline");
bin = gst_bin_new ("my_bin");
source = gst_element_factory_make ("fakesrc", "source");
sink = gst_element_factory_make ("fakesink", "sink");
/* First add the elements to the bin */
gst_bin_add_many (GST_BIN (bin), source, sink, NULL);
/* add the bin to the pipeline */
gst_bin_add (GST_BIN (pipeline), bin);
/* link the elements */
gst_element_link (source, sink);
[..]
}
```
There are various functions to lookup elements in a bin. The most
commonly used are `gst_bin_get_by_name ()` and `gst_bin_get_by_interface
()`. You can also iterate over all elements that a bin contains using
the function `gst_bin_iterate_elements ()`. See the API references of
[`GstBin`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstBin.html)
for details.
# Custom bins
The application programmer can create custom bins packed with elements
to perform a specific task. This allows you, for example, to write an
Ogg/Vorbis decoder with just the following lines of code:
```
int
main (int argc,
char *argv[])
{
GstElement *player;
/* init */
gst_init (&argc, &argv);
/* create player */
player = gst_element_factory_make ("oggvorbisplayer", "player");
/* set the source audio file */
g_object_set (player, "location", "helloworld.ogg", NULL);
/* start playback */
gst_element_set_state (GST_ELEMENT (player), GST_STATE_PLAYING);
[..]
}
```
(This is a silly example of course, there already exists a much more
powerful and versatile custom bin like this: the playbin element.)
Custom bins can be created with a plugin or from the application. You
will find more information about creating custom bin in the [Plugin
Writers
Guide](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/index.html).
Examples of such custom bins are the playbin and uridecodebin elements
from[gst-plugins-base](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/index.html).
# Bins manage states of their children
Bins manage the state of all elements contained in them. If you set a
bin (or a pipeline, which is a special top-level type of bin) to a
certain target state using `gst_element_set_state ()`, it will make sure
all elements contained within it will also be set to this state. This
means it's usually only necessary to set the state of the top-level
pipeline to start up the pipeline or shut it down.
The bin will perform the state changes on all its children from the sink
element to the source element. This ensures that the downstream element
is ready to receive data when the upstream element is brought to PAUSED
or PLAYING. Similarly when shutting down, the sink elements will be set
to READY or NULL first, which will cause the upstream elements to
receive a FLUSHING error and stop the streaming threads before the
elements are set to the READY or NULL state.
Note, however, that if elements are added to a bin or pipeline that's
already running, , e.g. from within a "pad-added" signal callback, its
state will not automatically be brought in line with the current state
or target state of the bin or pipeline it was added to. Instead, you
have to need to set it to the desired target state yourself using
`gst_element_set_state ()` or `gst_element_sync_state_with_parent ()`
when adding elements to an already-running pipeline.

393
manual-buffering.md Normal file
View file

@ -0,0 +1,393 @@
---
title: Buffering
...
# Buffering
The purpose of buffering is to accumulate enough data in a pipeline so
that playback can occur smoothly and without interruptions. It is
typically done when reading from a (slow) and non-live network source
but can also be used for live sources.
GStreamer provides support for the following use cases:
- Buffering up to a specific amount of data, in memory, before
starting playback so that network fluctuations are minimized. See
[Stream buffering](#stream-buffering).
- Download of the network file to a local disk with fast seeking in
the downloaded data. This is similar to the quicktime/youtube
players. See [Download buffering](#download-buffering).
- Caching of (semi)-live streams to a local, on disk, ringbuffer with
seeking in the cached area. This is similar to tivo-like
timeshifting. See [Timeshift buffering](#timeshift-buffering).
GStreamer can provide the application with progress reports about the
current buffering state as well as let the application decide on how to
buffer and when the buffering stops.
In the most simple case, the application has to listen for BUFFERING
messages on the bus. If the percent indicator inside the BUFFERING
message is smaller than 100, the pipeline is buffering. When a message
is received with 100 percent, buffering is complete. In the buffering
state, the application should keep the pipeline in the PAUSED state.
When buffering completes, it can put the pipeline (back) in the PLAYING
state.
What follows is an example of how the message handler could deal with
the BUFFERING messages. We will see more advanced methods in [Buffering
strategies](#buffering-strategies).
```
[...]
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_BUFFERING:{
gint percent;
/* no state management needed for live pipelines */
if (is_live)
break;
gst_message_parse_buffering (message, &percent);
if (percent == 100) {
/* a 100% message means buffering is done */
buffering = FALSE;
/* if the desired state is playing, go back */
if (target_state == GST_STATE_PLAYING) {
gst_element_set_state (pipeline, GST_STATE_PLAYING);
}
} else {
/* buffering busy */
if (!buffering && target_state == GST_STATE_PLAYING) {
/* we were not buffering but PLAYING, PAUSE the pipeline. */
gst_element_set_state (pipeline, GST_STATE_PAUSED);
}
buffering = TRUE;
}
break;
case ...
[...]
```
# Stream buffering
```
+---------+ +---------+ +-------+
| httpsrc | | buffer | | demux |
| src - sink src - sink ....
+---------+ +---------+ +-------+
```
In this case we are reading from a slow network source into a buffer
element (such as queue2).
The buffer element has a low and high watermark expressed in bytes. The
buffer uses the watermarks as follows:
- The buffer element will post BUFFERING messages until the high
watermark is hit. This instructs the application to keep the
pipeline PAUSED, which will eventually block the srcpad from pushing
while data is prerolled in the sinks.
- When the high watermark is hit, a BUFFERING message with 100% will
be posted, which instructs the application to continue playback.
- When during playback, the low watermark is hit, the queue will start
posting BUFFERING messages again, making the application PAUSE the
pipeline again until the high watermark is hit again. This is called
the rebuffering stage.
- During playback, the queue level will fluctuate between the high and
the low watermark as a way to compensate for network irregularities.
This buffering method is usable when the demuxer operates in push mode.
Seeking in the stream requires the seek to happen in the network source.
It is mostly desirable when the total duration of the file is not known,
such as in live streaming or when efficient seeking is not
possible/required.
The problem is configuring a good low and high watermark. Here are some
ideas:
- It is possible to measure the network bandwidth and configure the
low/high watermarks in such a way that buffering takes a fixed
amount of time.
The queue2 element in GStreamer core has the max-size-time property
that, together with the use-rate-estimate property, does exactly
that. Also the playbin buffer-duration property uses the rate
estimate to scale the amount of data that is buffered.
- Based on the codec bitrate, it is also possible to set the
watermarks in such a way that a fixed amount of data is buffered
before playback starts. Normally, the buffering element doesn't know
about the bitrate of the stream but it can get this with a query.
- Start with a fixed amount of bytes, measure the time between
rebuffering and increase the queue size until the time between
rebuffering is within the application's chosen limits.
The buffering element can be inserted anywhere in the pipeline. You
could, for example, insert the buffering element before a decoder. This
would make it possible to set the low/high watermarks based on time.
The buffering flag on playbin, performs buffering on the parsed data.
Another advantage of doing the buffering at a later stage is that you
can let the demuxer operate in pull mode. When reading data from a slow
network drive (with filesrc) this can be an interesting way to buffer.
# Download buffering
```
+---------+ +---------+ +-------+
| httpsrc | | buffer | | demux |
| src - sink src - sink ....
+---------+ +----|----+ +-------+
V
file
```
If we know the server is streaming a fixed length file to the client,
the application can choose to download the entire file on disk. The
buffer element will provide a push or pull based srcpad to the demuxer
to navigate in the downloaded file.
This mode is only suitable when the client can determine the length of
the file on the server.
In this case, buffering messages will be emitted as usual when the
requested range is not within the downloaded area + buffersize. The
buffering message will also contain an indication that incremental
download is being performed. This flag can be used to let the
application control the buffering in a more intelligent way, using the
BUFFERING query, for example. See [Buffering
strategies](#buffering-strategies).
# Timeshift buffering
```
+---------+ +---------+ +-------+
| httpsrc | | buffer | | demux |
| src - sink src - sink ....
+---------+ +----|----+ +-------+
V
file-ringbuffer
```
In this mode, a fixed size ringbuffer is kept to download the server
content. This allows for seeking in the buffered data. Depending on the
size of the ringbuffer one can seek further back in time.
This mode is suitable for all live streams. As with the incremental
download mode, buffering messages are emitted along with an indication
that timeshifting download is in progress.
# Live buffering
In live pipelines we usually introduce some fixed latency between the
capture and the playback elements. This latency can be introduced by a
queue (such as a jitterbuffer) or by other means (in the audiosink).
Buffering messages can be emitted in those live pipelines as well and
serve as an indication to the user of the latency buffering. The
application usually does not react to these buffering messages with a
state change.
# Buffering strategies
What follows are some ideas for implementing different buffering
strategies based on the buffering messages and buffering query.
## No-rebuffer strategy
We would like to buffer enough data in the pipeline so that playback
continues without interruptions. What we need to know to implement this
is know the total remaining playback time in the file and the total
remaining download time. If the buffering time is less than the playback
time, we can start playback without interruptions.
We have all this information available with the DURATION, POSITION and
BUFFERING queries. We need to periodically execute the buffering query
to get the current buffering status. We also need to have a large enough
buffer to hold the complete file, worst case. It is best to use this
buffering strategy with download buffering (see [Download
buffering](#download-buffering)).
This is what the code would look like:
```
#include <gst/gst.h>
GstState target_state;
static gboolean is_live;
static gboolean is_buffering;
static gboolean
buffer_timeout (gpointer data)
{
GstElement *pipeline = data;
GstQuery *query;
gboolean busy;
gint percent;
gint64 estimated_total;
gint64 position, duration;
guint64 play_left;
query = gst_query_new_buffering (GST_FORMAT_TIME);
if (!gst_element_query (pipeline, query))
return TRUE;
gst_query_parse_buffering_percent (query, &busy, &percent);
gst_query_parse_buffering_range (query, NULL, NULL, NULL, &estimated_total);
if (estimated_total == -1)
estimated_total = 0;
/* calculate the remaining playback time */
if (!gst_element_query_position (pipeline, GST_FORMAT_TIME, &position))
position = -1;
if (!gst_element_query_duration (pipeline, GST_FORMAT_TIME, &duration))
duration = -1;
if (duration != -1 && position != -1)
play_left = GST_TIME_AS_MSECONDS (duration - position);
else
play_left = 0;
g_message ("play_left %" G_GUINT64_FORMAT", estimated_total %" G_GUINT64_FORMAT
", percent %d", play_left, estimated_total, percent);
/* we are buffering or the estimated download time is bigger than the
* remaining playback time. We keep buffering. */
is_buffering = (busy || estimated_total * 1.1 > play_left);
if (!is_buffering)
gst_element_set_state (pipeline, target_state);
return is_buffering;
}
static void
on_message_buffering (GstBus *bus, GstMessage *message, gpointer user_data)
{
GstElement *pipeline = user_data;
gint percent;
/* no state management needed for live pipelines */
if (is_live)
return;
gst_message_parse_buffering (message, &percent);
if (percent < 100) {
/* buffering busy */
if (!is_buffering) {
is_buffering = TRUE;
if (target_state == GST_STATE_PLAYING) {
/* we were not buffering but PLAYING, PAUSE the pipeline. */
gst_element_set_state (pipeline, GST_STATE_PAUSED);
}
}
}
}
static void
on_message_async_done (GstBus *bus, GstMessage *message, gpointer user_data)
{
GstElement *pipeline = user_data;
if (!is_buffering)
gst_element_set_state (pipeline, target_state);
else
g_timeout_add (500, buffer_timeout, pipeline);
}
gint
main (gint argc,
gchar *argv[])
{
GstElement *pipeline;
GMainLoop *loop;
GstBus *bus;
GstStateChangeReturn ret;
/* init GStreamer */
gst_init (&amp;argc, &amp;argv);
loop = g_main_loop_new (NULL, FALSE);
/* make sure we have a URI */
if (argc != 2) {
g_print ("Usage: %s &lt;URI&gt;\n", argv[0]);
return -1;
}
/* set up */
pipeline = gst_element_factory_make ("playbin", "pipeline");
g_object_set (G_OBJECT (pipeline), "uri", argv[1], NULL);
g_object_set (G_OBJECT (pipeline), "flags", 0x697 , NULL);
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_signal_watch (bus);
g_signal_connect (bus, "message::buffering",
(GCallback) on_message_buffering, pipeline);
g_signal_connect (bus, "message::async-done",
(GCallback) on_message_async_done, pipeline);
gst_object_unref (bus);
is_buffering = FALSE;
target_state = GST_STATE_PLAYING;
ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
switch (ret) {
case GST_STATE_CHANGE_SUCCESS:
is_live = FALSE;
break;
case GST_STATE_CHANGE_FAILURE:
g_warning ("failed to PAUSE");
return -1;
case GST_STATE_CHANGE_NO_PREROLL:
is_live = TRUE;
break;
default:
break;
}
/* now run */
g_main_loop_run (loop);
/* also clean up */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
g_main_loop_unref (loop);
return 0;
}
```
See how we set the pipeline to the PAUSED state first. We will receive
buffering messages during the preroll state when buffering is needed.
When we are prerolled (on\_message\_async\_done) we see if buffering is
going on, if not, we start playback. If buffering was going on, we start
a timeout to poll the buffering state. If the estimated time to download
is less than the remaining playback time, we start playback.

18
manual-building.md Normal file
View file

@ -0,0 +1,18 @@
---
title: Building an Application
...
# Building an Application
In these chapters, we will discuss the basic concepts of GStreamer and
the most-used objects, such as elements, pads and buffers. We will use a
visual representation of these objects so that we can visualize the more
complex pipelines you will learn to build later on. You will get a first
glance at the GStreamer API, which should be enough for building
elementary applications. Later on in this part, you will also learn to
build a basic command-line application.
Note that this part will give a look into the low-level API and concepts
of GStreamer. Once you're going to build applications, you might want to
use higher-level APIs. Those will be discussed later on in this manual.

242
manual-bus.md Normal file
View file

@ -0,0 +1,242 @@
---
title: Bus
...
# Bus
A bus is a simple system that takes care of forwarding messages from the
streaming threads to an application in its own thread context. The
advantage of a bus is that an application does not need to be
thread-aware in order to use GStreamer, even though GStreamer itself is
heavily threaded.
Every pipeline contains a bus by default, so applications do not need to
create a bus or anything. The only thing applications should do is set a
message handler on a bus, which is similar to a signal handler to an
object. When the mainloop is running, the bus will periodically be
checked for new messages, and the callback will be called when any
message is available.
# How to use a bus
There are two different ways to use a bus:
- Run a GLib/Gtk+ main loop (or iterate the default GLib main context
yourself regularly) and attach some kind of watch to the bus. This
way the GLib main loop will check the bus for new messages and
notify you whenever there are messages.
Typically you would use `gst_bus_add_watch ()` or
`gst_bus_add_signal_watch ()` in this case.
To use a bus, attach a message handler to the bus of a pipeline
using `gst_bus_add_watch ()`. This handler will be called whenever
the pipeline emits a message to the bus. In this handler, check the
signal type (see next section) and do something accordingly. The
return value of the handler should be TRUE to keep the handler
attached to the bus, return FALSE to remove it.
- Check for messages on the bus yourself. This can be done using
`gst_bus_peek ()` and/or `gst_bus_poll ()`.
<!-- end list -->
```
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
my_bus_callback (GstBus *bus,
GstMessage *message,
gpointer data)
{
g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR: {
GError *err;
gchar *debug;
gst_message_parse_error (message, &err, &debug);
g_print ("Error: %s\n", err->message);
g_error_free (err);
g_free (debug);
g_main_loop_quit (loop);
break;
}
case GST_MESSAGE_EOS:
/* end-of-stream */
g_main_loop_quit (loop);
break;
default:
/* unhandled message */
break;
}
/* we want to be notified again the next time there is a message
* on the bus, so returning TRUE (FALSE means we want to stop watching
* for messages on the bus and our callback should not be called again)
*/
return TRUE;
}
gint
main (gint argc,
gchar *argv[])
{
GstElement *pipeline;
GstBus *bus;
guint bus_watch_id;
/* init */
gst_init (&argc, &argv);
/* create pipeline, add handler */
pipeline = gst_pipeline_new ("my_pipeline");
/* adds a watch for new message on our pipeline's message bus to
* the default GLib main context, which is the main context that our
* GLib main loop is attached to below
*/
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, my_bus_callback, NULL);
gst_object_unref (bus);
[..]
/* create a mainloop that runs/iterates the default GLib main context
* (context NULL), in other words: makes the context check if anything
* it watches for has happened. When a message has been posted on the
* bus, the default main context will automatically call our
* my_bus_callback() function to notify us of that message.
* The main loop will be run until someone calls g_main_loop_quit()
*/
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
/* clean up */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
g_source_remove (bus_watch_id);
g_main_loop_unref (loop);
return 0;
}
```
It is important to know that the handler will be called in the thread
context of the mainloop. This means that the interaction between the
pipeline and application over the bus is *asynchronous*, and thus not
suited for some real-time purposes, such as cross-fading between audio
tracks, doing (theoretically) gapless playback or video effects. All
such things should be done in the pipeline context, which is easiest by
writing a GStreamer plug-in. It is very useful for its primary purpose,
though: passing messages from pipeline to application. The advantage of
this approach is that all the threading that GStreamer does internally
is hidden from the application and the application developer does not
have to worry about thread issues at all.
Note that if you're using the default GLib mainloop integration, you
can, instead of attaching a watch, connect to the “message” signal on
the bus. This way you don't have to `switch()` on all possible message
types; just connect to the interesting signals in form of
“message::\<type\>”, where \<type\> is a specific message type (see
the next section for an explanation of message types).
The above snippet could then also be written as:
```
GstBus *bus;
[..]
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline);
gst_bus_add_signal_watch (bus);
g_signal_connect (bus, "message::error", G_CALLBACK (cb_message_error), NULL);
g_signal_connect (bus, "message::eos", G_CALLBACK (cb_message_eos), NULL);
[..]
```
If you aren't using GLib mainloop, the asynchronous message signals
won't be available by default. You can however install a custom sync
handler that wakes up the custom mainloop and that uses
`gst_bus_async_signal_func ()` to emit the signals. (see also
[documentation](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstBus.html)
for details)
# Message types
GStreamer has a few pre-defined message types that can be passed over
the bus. The messages are extensible, however. Plug-ins can define
additional messages, and applications can decide to either have specific
code for those or ignore them. All applications are strongly recommended
to at least handle error messages by providing visual feedback to the
user.
All messages have a message source, type and timestamp. The message
source can be used to see which element emitted the message. For some
messages, for example, only the ones emitted by the top-level pipeline
will be interesting to most applications (e.g. for state-change
notifications). Below is a list of all messages and a short explanation
of what they do and how to parse message-specific content.
- Error, warning and information notifications: those are used by
elements if a message should be shown to the user about the state of
the pipeline. Error messages are fatal and terminate the
data-passing. The error should be repaired to resume pipeline
activity. Warnings are not fatal, but imply a problem nevertheless.
Information messages are for non-problem notifications. All those
messages contain a `GError` with the main error type and message,
and optionally a debug string. Both can be extracted using
`gst_message_parse_error
()`, `_parse_warning ()` and `_parse_info ()`. Both error and debug
strings should be freed after use.
- End-of-stream notification: this is emitted when the stream has
ended. The state of the pipeline will not change, but further media
handling will stall. Applications can use this to skip to the next
song in their playlist. After end-of-stream, it is also possible to
seek back in the stream. Playback will then continue automatically.
This message has no specific arguments.
- Tags: emitted when metadata was found in the stream. This can be
emitted multiple times for a pipeline (e.g. once for descriptive
metadata such as artist name or song title, and another one for
stream-information, such as samplerate and bitrate). Applications
should cache metadata internally. `gst_message_parse_tag
()` should be used to parse the taglist, which should be
`gst_tag_list_unref ()`'ed when no longer needed.
- State-changes: emitted after a successful state change.
`gst_message_parse_state_changed ()` can be used to parse the old
and new state of this transition.
- Buffering: emitted during caching of network-streams. One can
manually extract the progress (in percent) from the message by
extracting the “buffer-percent” property from the structure returned
by `gst_message_get_structure
()`. See also [Buffering](manual-buffering.md).
- Element messages: these are special messages that are unique to
certain elements and usually represent additional features. The
element's documentation should mention in detail which element
messages a particular element may send. As an example, the 'qtdemux'
QuickTime demuxer element may send a 'redirect' element message on
certain occasions if the stream contains a redirect instruction.
- Application-specific messages: any information on those can be
extracted by getting the message structure (see above) and reading
its fields. Usually these messages can safely be ignored.
Application messages are primarily meant for internal use in
applications in case the application needs to marshal information
from some thread into the main thread. This is particularly useful
when the application is making use of element signals (as those
signals will be emitted in the context of the streaming thread).

132
manual-checklist-element.md Normal file
View file

@ -0,0 +1,132 @@
---
title: Things to check when writing an application
...
# Things to check when writing an application
This chapter contains a fairly random selection of things that can be
useful to keep in mind when writing GStreamer-based applications. It's
up to you how much you're going to use the information provided here. We
will shortly discuss how to debug pipeline problems using GStreamer
applications. Also, we will touch upon how to acquire knowledge about
plugins and elements and how to test simple pipelines before building
applications around them.
# Good programming habits
- Always add a `GstBus` handler to your pipeline. Always report errors
in your application, and try to do something with warnings and
information messages, too.
- Always check return values of GStreamer functions. Especially, check
return values of `gst_element_link ()` and `gst_element_set_state
()`.
- Dereference return values of all functions returning a non-base
type, such as `gst_element_get_pad ()`. Also, always free non-const
string returns, such as `gst_object_get_name ()`.
- Always use your pipeline object to keep track of the current state
of your pipeline. Don't keep private variables in your application.
Also, don't update your user interface if a user presses the “play”
button. Instead, listen for the “state-changed” message on the
`GstBus` and only update the user interface whenever this message is
received.
- Report all bugs that you find in GStreamer bugzilla at
[http://bugzilla.gnome.org/](http://bugzilla.gnome.org).
# Debugging
Applications can make use of the extensive GStreamer debugging system to
debug pipeline problems. Elements will write output to this system to
log what they're doing. It's not used for error reporting, but it is
very useful for tracking what an element is doing exactly, which can
come in handy when debugging application issues (such as failing seeks,
out-of-sync media, etc.).
Most GStreamer-based applications accept the commandline option
`--gst-debug=LIST` and related family members. The list consists of a
comma-separated list of category/level pairs, which can set the
debugging level for a specific debugging category. For example,
`--gst-debug=oggdemux:5` would turn on debugging for the Ogg demuxer
element. You can use wildcards as well. A debugging level of 0 will turn
off all debugging, and a level of 9 will turn on all debugging.
Intermediate values only turn on some debugging (based on message
severity; 2, for example, will only display errors and warnings). Here's
a list of all available options:
- `--gst-debug-help` will print available debug categories and exit.
- `--gst-debug-level=LEVEL` will set the default debug level (which
can range from 0 (no output) to 9 (everything)).
- `--gst-debug=LIST` takes a comma-separated list of
category\_name:level pairs to set specific levels for the individual
categories. Example: `GST_AUTOPLUG:5,avidemux:3`. Alternatively, you
can also set the `GST_DEBUG` environment variable, which has the
same effect.
- `--gst-debug-no-color` will disable color debugging. You can also
set the GST\_DEBUG\_NO\_COLOR environment variable to 1 if you want
to disable colored debug output permanently. Note that if you are
disabling color purely to avoid messing up your pager output, try
using `less -R`.
- `--gst-debug-color-mode=MODE` will change debug log coloring mode.
MODE can be one of the following: `on`, `off`, `auto`, `disable`,
`unix`. You can also set the GST\_DEBUG\_COLOR\_MODE environment
variable if you want to change colored debug output permanently.
Note that if you are disabling color purely to avoid messing up your
pager output, try using `less -R`.
- `--gst-debug-disable` disables debugging altogether.
- `--gst-plugin-spew` enables printout of errors while loading
GStreamer plugins.
# Conversion plugins
GStreamer contains a bunch of conversion plugins that most applications
will find useful. Specifically, those are videoscalers (videoscale),
colorspace convertors (videoconvert), audio format convertors and
channel resamplers (audioconvert) and audio samplerate convertors
(audioresample). Those convertors don't do anything when not required,
they will act in passthrough mode. They will activate when the hardware
doesn't support a specific request, though. All applications are
recommended to use those elements.
# Utility applications provided with GStreamer
GStreamer comes with a default set of command-line utilities that can
help in application development. We will discuss only `gst-launch` and
`gst-inspect` here.
## `gst-launch`
`gst-launch` is a simple script-like commandline application that can be
used to test pipelines. For example, the command `gst-launch
audiotestsrc ! audioconvert !
audio/x-raw,channels=2 ! alsasink` will run a pipeline which generates a
sine-wave audio stream and plays it to your ALSA audio card.
`gst-launch` also allows the use of threads (will be used automatically
as required or as queue elements are inserted in the pipeline) and bins
(using brackets, so “(” and “)”). You can use dots to imply padnames on
elements, or even omit the padname to automatically select a pad. Using
all this, the pipeline `gst-launch filesrc location=file.ogg ! oggdemux
name=d
d. ! queue ! theoradec ! videoconvert ! xvimagesink
d. ! queue ! vorbisdec ! audioconvert ! audioresample ! alsasink
` will play an Ogg file containing a Theora video-stream and a Vorbis
audio-stream. You can also use autopluggers such as decodebin on the
commandline. See the manual page of `gst-launch` for more information.
## `gst-inspect`
`gst-inspect` can be used to inspect all properties, signals, dynamic
parameters and the object hierarchy of an element. This can be very
useful to see which `GObject` properties or which signals (and using
what arguments) an element supports. Run `gst-inspect fakesrc` to get an
idea of what it does. See the manual page of `gst-inspect` for more
information.

201
manual-clocks.md Normal file
View file

@ -0,0 +1,201 @@
---
title: Clocks and synchronization in GStreamer
...
# Clocks and synchronization in GStreamer
When playing complex media, each sound and video sample must be played
in a specific order at a specific time. For this purpose, GStreamer
provides a synchronization mechanism.
GStreamer provides support for the following use cases:
- Non-live sources with access faster than playback rate. This is the
case where one is reading media from a file and playing it back in a
synchronized fashion. In this case, multiple streams need to be
synchronized, like audio, video and subtitles.
- Capture and synchronized muxing/mixing of media from multiple live
sources. This is a typical use case where you record audio and video
from a microphone/camera and mux it into a file for storage.
- Streaming from (slow) network streams with buffering. This is the
typical web streaming case where you access content from a streaming
server with http.
- Capture from live source and and playback to live source with
configurable latency. This is used when, for example, capture from a
camera, apply an effect and display the result. It is also used when
streaming low latency content over a network with UDP.
- Simultaneous live capture and playback from prerecorded content.
This is used in audio recording cases where you play a previously
recorded audio and record new samples, the purpose is to have the
new audio perfectly in sync with the previously recorded data.
GStreamer uses a `GstClock` object, buffer timestamps and a SEGMENT
event to synchronize streams in a pipeline as we will see in the next
sections.
# Clock running-time
In a typical computer, there are many sources that can be used as a time
source, e.g., the system time, soundcards, CPU performance counters, ...
For this reason, there are many `GstClock` implementations available in
GStreamer. The clock time doesn't always start from 0 or from some known
value. Some clocks start counting from some known start date, other
clocks start counting since last reboot, etc...
A `GstClock` returns the **absolute-time** according to that clock with
`gst_clock_get_time ()`. The absolute-time (or clock time) of a clock is
monotonically increasing. From the absolute-time is a **running-time**
calculated, which is simply the difference between a previous snapshot
of the absolute-time called the **base-time**. So:
running-time = absolute-time - base-time
A GStreamer `GstPipeline` object maintains a `GstClock` object and a
base-time when it goes to the PLAYING state. The pipeline gives a handle
to the selected `GstClock` to each element in the pipeline along with
selected base-time. The pipeline will select a base-time in such a way
that the running-time reflects the total time spent in the PLAYING
state. As a result, when the pipeline is PAUSED, the running-time stands
still.
Because all objects in the pipeline have the same clock and base-time,
they can thus all calculate the running-time according to the pipeline
clock.
# Buffer running-time
To calculate a buffer running-time, we need a buffer timestamp and the
SEGMENT event that preceeded the buffer. First we can convert the
SEGMENT event into a `GstSegment` object and then we can use the
`gst_segment_to_running_time ()` function to perform the calculation of
the buffer running-time.
Synchronization is now a matter of making sure that a buffer with a
certain running-time is played when the clock reaches the same
running-time. Usually this task is done by sink elements. Sink also have
to take into account the latency configured in the pipeline and add this
to the buffer running-time before synchronizing to the pipeline clock.
Non-live sources timestamp buffers with a running-time starting from 0.
After a flushing seek, they will produce buffers again from a
running-time of 0.
Live sources need to timestamp buffers with a running-time matching the
pipeline running-time when the first byte of the buffer was captured.
# Buffer stream-time
The buffer stream-time, also known as the position in the stream, is
calculated from the buffer timestamps and the preceding SEGMENT event.
It represents the time inside the media as a value between 0 and the
total duration of the media.
The stream-time is used in:
- Report the current position in the stream with the POSITION query.
- The position used in the seek events and queries.
- The position used to synchronize controlled values.
The stream-time is never used to synchronize streams, this is only done
with the running-time.
# Time overview
Here is an overview of the various timelines used in GStreamer.
The image below represents the different times in the pipeline when
playing a 100ms sample and repeating the part between 50ms and 100ms.
![GStreamer clock and various times](images/clocks.png "fig:")
You can see how the running-time of a buffer always increments
monotonically along with the clock-time. Buffers are played when their
running-time is equal to the clock-time - base-time. The stream-time
represents the position in the stream and jumps backwards when
repeating.
# Clock providers
A clock provider is an element in the pipeline that can provide a
`GstClock` object. The clock object needs to report an absolute-time
that is monotonically increasing when the element is in the PLAYING
state. It is allowed to pause the clock while the element is PAUSED.
Clock providers exist because they play back media at some rate, and
this rate is not necessarily the same as the system clock rate. For
example, a soundcard may playback at 44,1 kHz, but that doesn't mean
that after *exactly* 1 second *according to the system clock*, the
soundcard has played back 44.100 samples. This is only true by
approximation. In fact, the audio device has an internal clock based on
the number of samples played that we can expose.
If an element with an internal clock needs to synchronize, it needs to
estimate when a time according to the pipeline clock will take place
according to the internal clock. To estimate this, it needs to slave its
clock to the pipeline clock.
If the pipeline clock is exactly the internal clock of an element, the
element can skip the slaving step and directly use the pipeline clock to
schedule playback. This can be both faster and more accurate. Therefore,
generally, elements with an internal clock like audio input or output
devices will be a clock provider for the pipeline.
When the pipeline goes to the PLAYING state, it will go over all
elements in the pipeline from sink to source and ask each element if
they can provide a clock. The last element that can provide a clock will
be used as the clock provider in the pipeline. This algorithm prefers a
clock from an audio sink in a typical playback pipeline and a clock from
source elements in a typical capture pipeline.
There exist some bus messages to let you know about the clock and clock
providers in the pipeline. You can see what clock is selected in the
pipeline by looking at the NEW\_CLOCK message on the bus. When a clock
provider is removed from the pipeline, a CLOCK\_LOST message is posted
and the application should go to PAUSED and back to PLAYING to select a
new clock.
# Latency
The latency is the time it takes for a sample captured at timestamp X to
reach the sink. This time is measured against the clock in the pipeline.
For pipelines where the only elements that synchronize against the clock
are the sinks, the latency is always 0 since no other element is
delaying the buffer.
For pipelines with live sources, a latency is introduced, mostly because
of the way a live source works. Consider an audio source, it will start
capturing the first sample at time 0. If the source pushes buffers with
44100 samples at a time at 44100Hz it will have collected the buffer at
second 1. Since the timestamp of the buffer is 0 and the time of the
clock is now \>= 1 second, the sink will drop this buffer because it is
too late. Without any latency compensation in the sink, all buffers will
be dropped.
## Latency compensation
Before the pipeline goes to the PLAYING state, it will, in addition to
selecting a clock and calculating a base-time, calculate the latency in
the pipeline. It does this by doing a LATENCY query on all the sinks in
the pipeline. The pipeline then selects the maximum latency in the
pipeline and configures this with a LATENCY event.
All sink elements will delay playback by the value in the LATENCY event.
Since all sinks delay with the same amount of time, they will be
relative in sync.
## Dynamic Latency
Adding/removing elements to/from a pipeline or changing element
properties can change the latency in a pipeline. An element can request
a latency change in the pipeline by posting a LATENCY message on the
bus. The application can then decide to query and redistribute a new
latency or not. Changing the latency in a pipeline might cause visual or
audible glitches and should therefore only be done by the application
when it is allowed.

70
manual-compiling.md Normal file
View file

@ -0,0 +1,70 @@
---
title: Compiling
...
# Compiling
This section talks about the different things you can do when building
and shipping your applications and plugins.
# Embedding static elements in your application
The [Plugin Writer's
Guide](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/index.html)
describes in great detail how to write elements for the GStreamer
framework. In this section, we will solely discuss how to embed such
elements statically in your application. This can be useful for
application-specific elements that have no use elsewhere in GStreamer.
Dynamically loaded plugins contain a structure that's defined using
`GST_PLUGIN_DEFINE ()`. This structure is loaded when the plugin is
loaded by the GStreamer core. The structure contains an initialization
function (usually called `plugin_init`) that will be called right after
that. It's purpose is to register the elements provided by the plugin
with the GStreamer framework. If you want to embed elements directly in
your application, the only thing you need to do is to replace
`GST_PLUGIN_DEFINE ()` with a call to `gst_plugin_register_static ()`.
As soon as you call `gst_plugin_register_static ()`, the elements will
from then on be available like any other element, without them having to
be dynamically loadable libraries. In the example below, you would be
able to call `gst_element_factory_make
("my-element-name", "some-name")` to create an instance of the element.
```
/*
* Here, you would write the actual plugin code.
*/
[..]
static gboolean
register_elements (GstPlugin *plugin)
{
return gst_element_register (plugin, "my-element-name",
GST_RANK_NONE, MY_PLUGIN_TYPE);
}
static
my_code_init (void)
{
...
gst_plugin_register_static (
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"my-private-plugins",
"Private elements of my application",
register_elements,
VERSION,
"LGPL",
"my-application-source",
"my-application",
"http://www.my-application.net/")
...
}
```

79
manual-data.md Normal file
View file

@ -0,0 +1,79 @@
---
title: Buffers and Events
...
# Buffers and Events
The data flowing through a pipeline consists of a combination of buffers
and events. Buffers contain the actual media data. Events contain
control information, such as seeking information and end-of-stream
notifiers. All this will flow through the pipeline automatically when
it's running. This chapter is mostly meant to explain the concept to
you; you don't need to do anything for this.
# Buffers
Buffers contain the data that will flow through the pipeline you have
created. A source element will typically create a new buffer and pass it
through a pad to the next element in the chain. When using the GStreamer
infrastructure to create a media pipeline you will not have to deal with
buffers yourself; the elements will do that for you.
A buffer consists, amongst others, of:
- Pointers to memory objects. Memory objects encapsulate a region in
the memory.
- A timestamp for the buffer.
- A refcount that indicates how many elements are using this buffer.
This refcount will be used to destroy the buffer when no element has
a reference to it.
- Buffer flags.
The simple case is that a buffer is created, memory allocated, data put
in it, and passed to the next element. That element reads the data, does
something (like creating a new buffer and decoding into it), and
unreferences the buffer. This causes the data to be free'ed and the
buffer to be destroyed. A typical video or audio decoder works like
this.
There are more complex scenarios, though. Elements can modify buffers
in-place, i.e. without allocating a new one. Elements can also write to
hardware memory (such as from video-capture sources) or memory allocated
from the X-server (using XShm). Buffers can be read-only, and so on.
# Events
Events are control particles that are sent both up- and downstream in a
pipeline along with buffers. Downstream events notify fellow elements of
stream states. Possible events include seeking, flushes, end-of-stream
notifications and so on. Upstream events are used both in
application-element interaction as well as element-element interaction
to request changes in stream state, such as seeks. For applications,
only upstream events are important. Downstream events are just explained
to get a more complete picture of the data concept.
Since most applications seek in time units, our example below does so
too:
```
static void
seek_to_time (GstElement *element,
guint64 time_ns)
{
GstEvent *event;
event = gst_event_new_seek (1.0, GST_FORMAT_TIME,
GST_SEEK_FLAG_NONE,
GST_SEEK_METHOD_SET, time_ns,
GST_SEEK_TYPE_NONE, G_GUINT64_CONSTANT (0));
gst_element_send_event (element, event);
}
```
The function `gst_element_seek ()` is a shortcut for this. This is
mostly just to show how it all works.

1404
manual-dataaccess.md Normal file

File diff suppressed because it is too large Load diff

102
manual-dparams.md Normal file
View file

@ -0,0 +1,102 @@
---
title: Dynamic Controllable Parameters
...
# Dynamic Controllable Parameters
# Getting Started
The controller subsystem offers a lightweight way to adjust gobject
properties over stream-time. Normally these properties are changed using
`g_object_set()`. Timing those calls reliably so that the changes affect
certain stream times is close to impossible. The controller takes time
into account. It works by attaching control-sources to properties using
control-bindings. Control-sources provide values for a given time-stamp
that are usually in the range of 0.0 to 1.0. Control-bindings map the
control-value to a gobject property they are bound to - converting the
type and scaling to the target property value range. At run-time the
elements continuously pull values changes for the current stream-time to
update the gobject properties. GStreamer includes a few different
control-sources and control-bindings already, but applications can
define their own by sub-classing from the respective base classes.
Most parts of the controller mechanism is implemented in GstObject. Also
the base classes for control-sources and control-bindings are included
in the core library. The existing implementations are contained within
the `gstcontroller` library. You need to include the header in your
application's source file:
```
...
#include <gst/gst.h>
#include <gst/controller/gstinterpolationcontrolsource.h>
#include <gst/controller/gstdirectcontrolbinding.h>
...
```
Your application should link to the shared library
`gstreamer-controller`. One can get the required flag for compiler and
linker by using pkg-config for gstreamer-controller-1.0.
# Setting up parameter control
If we have our pipeline set up and want to control some parameters, we
first need to create a control-source. Lets use an interpolation
control-source:
```
csource = gst_interpolation_control_source_new ();
g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
```
Now we need to attach the control-source to the gobject property. This
is done with a control-binding. One control source can be attached to
several object properties (even in different objects) using separate
control-bindings.
```
gst_object_add_control_binding (object, gst_direct_control_binding_new (object, "prop1", csource));
```
This type control-source takes new property values from a list of
time-stamped parameter changes. The source can e.g. fill gaps by
smoothing parameter changes This behavior can be configured by setting
the mode property of the control-source. Other control sources e.g.
produce a stream of values by calling `sin()` function. They have
parameters to control e.g. the frequency. As control-sources are
GstObjects too, one can attach control-sources to these properties too.
Now we can set some control points. These are time-stamped gdouble
values and are usually in the range of 0.0 to 1.0. A value of 1.0 is
later mapped to the maximum value in the target properties value range.
The values become active when the timestamp is reached. They still stay
in the list. If e.g. the pipeline runs a loop (using a segmented seek),
the control-curve gets repeated as
well.
```
GstTimedValueControlSource *tv_csource = (GstTimedValueControlSource *)csource;
gst_timed_value_control_source_set (tv_csource, 0 * GST_SECOND, 0.0);
gst_timed_value_control_source_set (tv_csource, 1 * GST_SECOND, 1.0);
```
Now everything is ready to play. If the control-source is e.g. bound to
a volume property, we will head a fade-in over 1 second. One word of
caution, the volume element that comes with gstreamer has a value range
of 0.0 to 4.0 on its volume property. If the above control-source is
attached to the property the volume will ramp up to 400%\!
One final note - the controller subsystem has a built-in live-mode. Even
though a property has a control-source assigned one can change the
GObject property through the `g_object_set()`. This is highly useful
when binding the GObject properties to GUI widgets. When the user
adjusts the value with the widget, one can set the GObject property and
this remains active until the next programmed control-source value
overrides it. This also works with smoothed parameters. It does not work
for control-sources that constantly update the property (e.g. the
lfo\_control\_source).

451
manual-elements.md Normal file
View file

@ -0,0 +1,451 @@
---
title: Elements
...
# Elements
The most important object in GStreamer for the application programmer is
the
[`GstElement`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElement.html)
object. An element is the basic building block for a media pipeline. All
the different high-level components you will use are derived from
`GstElement`. Every decoder, encoder, demuxer, video or audio output is
in fact a `GstElement`
# What are elements?
For the application programmer, elements are best visualized as black
boxes. On the one end, you might put something in, the element does
something with it and something else comes out at the other side. For a
decoder element, for example, you'd put in encoded data, and the element
would output decoded data. In the next chapter (see [Pads and
capabilities](manual-pads.md)), you will learn more about data input
and output in elements, and how you can set that up in your application.
## Source elements
Source elements generate data for use by a pipeline, for example reading
from disk or from a sound card. [Visualisation of a source
element](#visualisation-of-a-source-element) shows how we will visualise
a source element. We always draw a source pad to the right of the
element.
![Visualisation of a source element](images/src-element.png "fig:")
Source elements do not accept data, they only generate data. You can see
this in the figure because it only has a source pad (on the right). A
source pad can only generate data.
## Filters, convertors, demuxers, muxers and codecs
Filters and filter-like elements have both input and outputs pads. They
operate on data that they receive on their input (sink) pads, and will
provide data on their output (source) pads. Examples of such elements
are a volume element (filter), a video scaler (convertor), an Ogg
demuxer or a Vorbis decoder.
Filter-like elements can have any number of source or sink pads. A video
demuxer, for example, would have one sink pad and several (1-N) source
pads, one for each elementary stream contained in the container format.
Decoders, on the other hand, will only have one source and sink pads.
![Visualisation of a filter element](images/filter-element.png "fig:")
[Visualisation of a filter element](#visualisation-of-a-filter-element)
shows how we will visualise a filter-like element. This specific element
has one source and one sink element. Sink pads, receiving input data,
are depicted at the left of the element; source pads are still on the
right.
![Visualisation of a filter element with more than one output
pad](images/filter-element-multi.png "fig:")
[Visualisation of a filter element with more than one output
pad](#visualisation-of-a-filter-element-with----more-than-one-output-pad)
shows another filter-like element, this one having more than one output
(source) pad. An example of one such element could, for example, be an
Ogg demuxer for an Ogg stream containing both audio and video. One
source pad will contain the elementary video stream, another will
contain the elementary audio stream. Demuxers will generally fire
signals when a new pad is created. The application programmer can then
handle the new elementary stream in the signal handler.
## Sink elements
Sink elements are end points in a media pipeline. They accept data but
do not produce anything. Disk writing, soundcard playback, and video
output would all be implemented by sink elements. [Visualisation of a
sink element](#visualisation-of-a-sink-element) shows a sink element.
![Visualisation of a sink element](images/sink-element.png "fig:")
# Creating a `GstElement`
The simplest way to create an element is to use
[`gst_element_factory_make
()`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElementFactory.html#gst-element-factory-make).
This function takes a factory name and an element name for the newly
created element. The name of the element is something you can use later
on to look up the element in a bin, for example. The name will also be
used in debug output. You can pass `NULL` as the name argument to get a
unique, default name.
When you don't need the element anymore, you need to unref it using
[`gst_object_unref
()`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstObject.html#gst-object-unref).
This decreases the reference count for the element by 1. An element has
a refcount of 1 when it gets created. An element gets destroyed
completely when the refcount is decreased to 0.
The following example \[1\] shows how to create an element named
*source* from the element factory named *fakesrc*. It checks if the
creation succeeded. After checking, it unrefs the element.
```
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElement *element;
/* init GStreamer */
gst_init (&argc, &argv);
/* create element */
element = gst_element_factory_make ("fakesrc", "source");
if (!element) {
g_print ("Failed to create element of type 'fakesrc'\n");
return -1;
}
gst_object_unref (GST_OBJECT (element));
return 0;
}
```
`gst_element_factory_make` is actually a shorthand for a combination of
two functions. A
[`GstElement`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElement.html)
object is created from a factory. To create the element, you have to get
access to a
[`GstElementFactory`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElementFactory.html)
object using a unique factory name. This is done with
[`gst_element_factory_find
()`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElementFactory.html#gst-element-factory-find).
The following code fragment is used to get a factory that can be used to
create the *fakesrc* element, a fake data source. The function
[`gst_element_factory_create
()`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElementFactory.html#gst-element-factory-create)
will use the element factory to create an element with the given name.
```
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElementFactory *factory;
GstElement * element;
/* init GStreamer */
gst_init (&argc, &argv);
/* create element, method #2 */
factory = gst_element_factory_find ("fakesrc");
if (!factory) {
g_print ("Failed to find factory of type 'fakesrc'\n");
return -1;
}
element = gst_element_factory_create (factory, "source");
if (!element) {
g_print ("Failed to create element, even though its factory exists!\n");
return -1;
}
gst_object_unref (GST_OBJECT (element));
return 0;
}
```
# Using an element as a `GObject`
A
[`GstElement`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElement.html)
can have several properties which are implemented using standard
`GObject` properties. The usual `GObject` methods to query, set and get
property values and `GParamSpecs` are therefore supported.
Every `GstElement` inherits at least one property from its parent
`GstObject`: the "name" property. This is the name you provide to the
functions `gst_element_factory_make ()` or `gst_element_factory_create
()`. You can get and set this property using the functions
`gst_object_set_name` and `gst_object_get_name` or use the `GObject`
property mechanism as shown below.
```
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElement *element;
gchar *name;
/* init GStreamer */
gst_init (&argc, &argv);
/* create element */
element = gst_element_factory_make ("fakesrc", "source");
/* get name */
g_object_get (G_OBJECT (element), "name", &name, NULL);
g_print ("The name of the element is '%s'.\n", name);
g_free (name);
gst_object_unref (GST_OBJECT (element));
return 0;
}
```
Most plugins provide additional properties to provide more information
about their configuration or to configure the element. `gst-inspect` is
a useful tool to query the properties of a particular element, it will
also use property introspection to give a short explanation about the
function of the property and about the parameter types and ranges it
supports. See [gst-inspect](manual-checklist-element.md#gst-inspect) in
the appendix for details about `gst-inspect`.
For more information about `GObject` properties we recommend you read
the [GObject
manual](http://developer.gnome.org/gobject/stable/rn01.html) and an
introduction to [The Glib Object
system](http://developer.gnome.org/gobject/stable/pt01.html).
A
[`GstElement`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElement.html)
also provides various `GObject` signals that can be used as a flexible
callback mechanism. Here, too, you can use `gst-inspect` to see which
signals a specific element supports. Together, signals and properties
are the most basic way in which elements and applications interact.
# More about element factories
In the previous section, we briefly introduced the
[`GstElementFactory`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstElementFactory.html)
object already as a way to create instances of an element. Element
factories, however, are much more than just that. Element factories are
the basic types retrieved from the GStreamer registry, they describe all
plugins and elements that GStreamer can create. This means that element
factories are useful for automated element instancing, such as what
autopluggers do, and for creating lists of available elements.
## Getting information about an element using a factory
Tools like `gst-inspect` will provide some generic information about an
element, such as the person that wrote the plugin, a descriptive name
(and a shortname), a rank and a category. The category can be used to
get the type of the element that can be created using this element
factory. Examples of categories include `Codec/Decoder/Video` (video
decoder), `Codec/Encoder/Video` (video encoder), `Source/Video` (a video
generator), `Sink/Video` (a video output), and all these exist for audio
as well, of course. Then, there's also `Codec/Demuxer` and `Codec/Muxer`
and a whole lot more. `gst-inspect` will give a list of all factories,
and `gst-inspect <factory-name>` will list all of the above information,
and a lot more.
```
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElementFactory *factory;
/* init GStreamer */
gst_init (&argc, &argv);
/* get factory */
factory = gst_element_factory_find ("fakesrc");
if (!factory) {
g_print ("You don't have the 'fakesrc' element installed!\n");
return -1;
}
/* display information */
g_print ("The '%s' element is a member of the category %s.\n"
"Description: %s\n",
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS),
gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_DESCRIPTION));
return 0;
}
```
You can use `gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY)`
to get a list of all the element factories that GStreamer knows about.
## Finding out what pads an element can contain
Perhaps the most powerful feature of element factories is that they
contain a full description of the pads that the element can generate,
and the capabilities of those pads (in layman words: what types of media
can stream over those pads), without actually having to load those
plugins into memory. This can be used to provide a codec selection list
for encoders, or it can be used for autoplugging purposes for media
players. All current GStreamer-based media players and autopluggers work
this way. We'll look closer at these features as we learn about `GstPad`
and `GstCaps` in the next chapter: [Pads and
capabilities](manual-pads.md)
# Linking elements
By linking a source element with zero or more filter-like elements and
finally a sink element, you set up a media pipeline. Data will flow
through the elements. This is the basic concept of media handling in
GStreamer.
![Visualisation of three linked elements](images/linked-elements.png
"fig:")
By linking these three elements, we have created a very simple chain of
elements. The effect of this will be that the output of the source
element (“element1”) will be used as input for the filter-like element
(“element2”). The filter-like element will do something with the data
and send the result to the final sink element (“element3”).
Imagine the above graph as a simple Ogg/Vorbis audio decoder. The source
is a disk source which reads the file from disc. The second element is a
Ogg/Vorbis audio decoder. The sink element is your soundcard, playing
back the decoded audio data. We will use this simple graph to construct
an Ogg/Vorbis player later in this manual.
In code, the above graph is written like this:
```
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElement *pipeline;
GstElement *source, *filter, *sink;
/* init */
gst_init (&argc, &argv);
/* create pipeline */
pipeline = gst_pipeline_new ("my-pipeline");
/* create elements */
source = gst_element_factory_make ("fakesrc", "source");
filter = gst_element_factory_make ("identity", "filter");
sink = gst_element_factory_make ("fakesink", "sink");
/* must add elements to pipeline before linking them */
gst_bin_add_many (GST_BIN (pipeline), source, filter, sink, NULL);
/* link */
if (!gst_element_link_many (source, filter, sink, NULL)) {
g_warning ("Failed to link elements!");
}
[..]
}
```
For more specific behaviour, there are also the functions
`gst_element_link ()` and `gst_element_link_pads ()`. You can also
obtain references to individual pads and link those using various
`gst_pad_link_* ()` functions. See the API references for more details.
Important: you must add elements to a bin or pipeline *before* linking
them, since adding an element to a bin will disconnect any already
existing links. Also, you cannot directly link elements that are not in
the same bin or pipeline; if you want to link elements or pads at
different hierarchy levels, you will need to use ghost pads (more about
ghost pads later, see [Ghost pads](manual-pads.md#ghost-pads)).
# Element States
After being created, an element will not actually perform any actions
yet. You need to change elements state to make it do something.
GStreamer knows four element states, each with a very specific meaning.
Those four states are:
- `GST_STATE_NULL`: this is the default state. No resources are
allocated in this state, so, transitioning to it will free all
resources. The element must be in this state when its refcount
reaches 0 and it is freed.
- `GST_STATE_READY`: in the ready state, an element has allocated all
of its global resources, that is, resources that can be kept within
streams. You can think about opening devices, allocating buffers and
so on. However, the stream is not opened in this state, so the
stream positions is automatically zero. If a stream was previously
opened, it should be closed in this state, and position, properties
and such should be reset.
- `GST_STATE_PAUSED`: in this state, an element has opened the stream,
but is not actively processing it. An element is allowed to modify a
stream's position, read and process data and such to prepare for
playback as soon as state is changed to PLAYING, but it is *not*
allowed to play the data which would make the clock run. In summary,
PAUSED is the same as PLAYING but without a running clock.
Elements going into the PAUSED state should prepare themselves for
moving over to the PLAYING state as soon as possible. Video or audio
outputs would, for example, wait for data to arrive and queue it so
they can play it right after the state change. Also, video sinks can
already play the first frame (since this does not affect the clock
yet). Autopluggers could use this same state transition to already
plug together a pipeline. Most other elements, such as codecs or
filters, do not need to explicitly do anything in this state,
however.
- `GST_STATE_PLAYING`: in the PLAYING state, an element does exactly
the same as in the PAUSED state, except that the clock now runs.
You can change the state of an element using the function
`gst_element_set_state ()`. If you set an element to another state,
GStreamer will internally traverse all intermediate states. So if you
set an element from NULL to PLAYING, GStreamer will internally set the
element to READY and PAUSED in between.
When moved to `GST_STATE_PLAYING`, pipelines will process data
automatically. They do not need to be iterated in any form. Internally,
GStreamer will start threads that take this task on to them. GStreamer
will also take care of switching messages from the pipeline's thread
into the application's own thread, by using a
[`GstBus`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstBus.html).
See [Bus](manual-bus.md) for details.
When you set a bin or pipeline to a certain target state, it will
usually propagate the state change to all elements within the bin or
pipeline automatically, so it's usually only necessary to set the state
of the top-level pipeline to start up the pipeline or shut it down.
However, when adding elements dynamically to an already-running
pipeline, e.g. from within a "pad-added" signal callback, you need to
set it to the desired target state yourself using `gst_element_set_state
()` or `gst_element_sync_state_with_parent ()`.
1. The code for this example is automatically extracted from the
documentation and built under `tests/examples/manual` in the
GStreamer tarball.

88
manual-gstreamer.md Normal file
View file

@ -0,0 +1,88 @@
---
title: What is GStreamer?
...
# What is GStreamer?
GStreamer is a framework for creating streaming media applications. The
fundamental design comes from the video pipeline at Oregon Graduate
Institute, as well as some ideas from DirectShow.
GStreamer's development framework makes it possible to write any type of
streaming multimedia application. The GStreamer framework is designed to
make it easy to write applications that handle audio or video or both.
It isn't restricted to audio and video, and can process any kind of data
flow. The pipeline design is made to have little overhead above what the
applied filters induce. This makes GStreamer a good framework for
designing even high-end audio applications which put high demands on
latency.
One of the most obvious uses of GStreamer is using it to build a media
player. GStreamer already includes components for building a media
player that can support a very wide variety of formats, including MP3,
Ogg/Vorbis, MPEG-1/2, AVI, Quicktime, mod, and more. GStreamer, however,
is much more than just another media player. Its main advantages are
that the pluggable components can be mixed and matched into arbitrary
pipelines so that it's possible to write a full-fledged video or audio
editing application.
The framework is based on plugins that will provide the various codec
and other functionality. The plugins can be linked and arranged in a
pipeline. This pipeline defines the flow of the data. Pipelines can also
be edited with a GUI editor and saved as XML so that pipeline libraries
can be made with a minimum of effort.
The GStreamer core function is to provide a framework for plugins, data
flow and media type handling/negotiation. It also provides an API to
write applications using the various plugins.
Specifically, GStreamer provides
- an API for multimedia applications
- a plugin architecture
- a pipeline architecture
- a mechanism for media type handling/negotiation
- a mechanism for synchronization
- over 250 plug-ins providing more than 1000 elements
- a set of tools
GStreamer plug-ins could be classified into
- protocols handling
- sources: for audio and video (involves protocol plugins)
- formats: parsers, formaters, muxers, demuxers, metadata, subtitles
- codecs: coders and decoders
- filters: converters, mixers, effects, ...
- sinks: for audio and video (involves protocol plugins)
![Gstreamer overview](images/gstreamer-overview.png "fig:")
GStreamer is packaged into
- gstreamer: the core package
- gst-plugins-base: an essential exemplary set of elements
- gst-plugins-good: a set of good-quality plug-ins under LGPL
- gst-plugins-ugly: a set of good-quality plug-ins that might pose
distribution problems
- gst-plugins-bad: a set of plug-ins that need more quality
- gst-libav: a set of plug-ins that wrap libav for decoding and
encoding
- a few others packages

249
manual-helloworld.md Normal file
View file

@ -0,0 +1,249 @@
---
title: Your first application
...
# Your first application
This chapter will summarize everything you've learned in the previous
chapters. It describes all aspects of a simple GStreamer application,
including initializing libraries, creating elements, packing elements
together in a pipeline and playing this pipeline. By doing all this, you
will be able to build a simple Ogg/Vorbis audio player.
# Hello world
We're going to create a simple first application, a simple Ogg/Vorbis
command-line audio player. For this, we will use only standard GStreamer
components. The player will read a file specified on the command-line.
Let's get started\!
We've learned, in [Initializing GStreamer](manual-init.md), that the
first thing to do in your application is to initialize GStreamer by
calling `gst_init ()`. Also, make sure that the application includes
`gst/gst.h` so all function names and objects are properly defined. Use
`#include
<gst/gst.h>` to do that.
Next, you'll want to create the different elements using
`gst_element_factory_make ()`. For an Ogg/Vorbis audio player, we'll
need a source element that reads files from a disk. GStreamer includes
this element under the name “filesrc”. Next, we'll need something to
parse the file and decode it into raw audio. GStreamer has two elements
for this: the first parses Ogg streams into elementary streams (video,
audio) and is called “oggdemux”. The second is a Vorbis audio decoder,
it's conveniently called “vorbisdec”. Since “oggdemux” creates dynamic
pads for each elementary stream, you'll need to set a “pad-added” event
handler on the “oggdemux” element, like you've learned in [Dynamic (or
sometimes) pads](manual-pads.md#dynamic-or-sometimes-pads), to link the
Ogg demuxer and the Vorbis decoder elements together. At last, we'll
also need an audio output element, we will use “autoaudiosink”, which
automatically detects your audio device.
The last thing left to do is to add all elements into a container
element, a `GstPipeline`, and wait until we've played the whole song.
We've previously learned how to add elements to a container bin in
[Bins](manual-bins.md), and we've learned about element states in
[Element States](manual-elements.md#element-states). We will also
attach a message handler to the pipeline bus so we can retrieve errors
and detect the end-of-stream.
Let's now add all the code together to get our very first audio player:
```
#include <gst/gst.h>
#include <glib.h>
static gboolean
bus_call (GstBus *bus,
GstMessage *msg,
gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:
g_print ("End of stream\n");
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ERROR: {
gchar *debug;
GError *error;
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
g_main_loop_quit (loop);
break;
}
default:
break;
}
return TRUE;
}
static void
on_pad_added (GstElement *element,
GstPad *pad,
gpointer data)
{
GstPad *sinkpad;
GstElement *decoder = (GstElement *) data;
/* We can now link this pad with the vorbis-decoder sink pad */
g_print ("Dynamic pad created, linking demuxer/decoder\n");
sinkpad = gst_element_get_static_pad (decoder, "sink");
gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
}
int
main (int argc,
char *argv[])
{
GMainLoop *loop;
GstElement *pipeline, *source, *demuxer, *decoder, *conv, *sink;
GstBus *bus;
guint bus_watch_id;
/* Initialisation */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* Check input arguments */
if (argc != 2) {
g_printerr ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]);
return -1;
}
/* Create gstreamer elements */
pipeline = gst_pipeline_new ("audio-player");
source = gst_element_factory_make ("filesrc", "file-source");
demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer");
decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder");
conv = gst_element_factory_make ("audioconvert", "converter");
sink = gst_element_factory_make ("autoaudiosink", "audio-output");
if (!pipeline || !source || !demuxer || !decoder || !conv || !sink) {
g_printerr ("One element could not be created. Exiting.\n");
return -1;
}
/* Set up the pipeline */
/* we set the input filename to the source element */
g_object_set (G_OBJECT (source), "location", argv[1], NULL);
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
/* we add all elements into the pipeline */
/* file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output */
gst_bin_add_many (GST_BIN (pipeline),
source, demuxer, decoder, conv, sink, NULL);
/* we link the elements together */
/* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output */
gst_element_link (source, demuxer);
gst_element_link_many (decoder, conv, sink, NULL);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder);
/* note that the demuxer will be linked to the decoder dynamically.
The reason is that Ogg may contain various streams (for example
audio and video). The source pad(s) will be created at run time,
by the demuxer when it detects the amount and nature of streams.
Therefore we connect a callback function which will be executed
when the "pad-added" is emitted.*/
/* Set the pipeline to "playing" state*/
g_print ("Now playing: %s\n", argv[1]);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* Iterate */
g_print ("Running...\n");
g_main_loop_run (loop);
/* Out of the main loop, clean up nicely */
g_print ("Returned, stopping playback\n");
gst_element_set_state (pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (pipeline));
g_source_remove (bus_watch_id);
g_main_loop_unref (loop);
return 0;
}
```
We now have created a complete pipeline. We can visualise the pipeline
as follows:
![The "hello world" pipeline](images/hello-world.png "fig:")
# Compiling and Running helloworld.c
To compile the helloworld example, use: `gcc -Wall
helloworld.c -o helloworld
$(pkg-config --cflags --libs gstreamer-1.0)`. GStreamer makes use of
`pkg-config` to get compiler and linker flags needed to compile this
application.
If you're running a non-standard installation (ie. you've installed
GStreamer from source yourself instead of using pre-built packages),
make sure the `PKG_CONFIG_PATH` environment variable is set to the
correct location (`$libdir/pkgconfig`).
In the unlikely case that you are using an uninstalled GStreamer setup
(ie. gst-uninstalled), you will need to use libtool to build the hello
world program, like this: `libtool --mode=link gcc -Wall
helloworld.c -o helloworld
$(pkg-config --cflags --libs gstreamer-1.0)`.
You can run this example application with `./helloworld
file.ogg`. Substitute `file.ogg` with your favourite Ogg/Vorbis file.
# Conclusion
This concludes our first example. As you see, setting up a pipeline is
very low-level but powerful. You will see later in this manual how you
can create a more powerful media player with even less effort using
higher-level interfaces. We will discuss all that in [Higher-level
interfaces for GStreamer applications](manual-highlevel.md). We will
first, however, go more in-depth into more advanced GStreamer internals.
It should be clear from the example that we can very easily replace the
“filesrc” element with some other element that reads data from a
network, or some other data source element that is better integrated
with your desktop environment. Also, you can use other decoders and
parsers/demuxers to support other media types. You can use another audio
sink if you're not running Linux, but Mac OS X, Windows or FreeBSD, or
you can instead use a filesink to write audio files to disk instead of
playing them back. By using an audio card source, you can even do audio
capture instead of playback. All this shows the reusability of GStreamer
elements, which is its greatest advantage.

17
manual-highlevel.md Normal file
View file

@ -0,0 +1,17 @@
---
title: Higher-level interfaces for GStreamer applications
...
# Higher-level interfaces for GStreamer applications
In the previous two parts, you have learned many of the internals and
their corresponding low-level interfaces into GStreamer application
programming. Many people will, however, not need so much control (and as
much code), but will prefer to use a standard playback interface that
does most of the difficult internals for them. In this chapter, we will
introduce you into the concept of autopluggers, playback managing
elements and other such things. Those higher-level interfaces are
intended to simplify GStreamer-based application programming. They do,
however, also reduce the flexibility. It is up to the application
developer to choose which interface he will want to use.

94
manual-index.md Normal file
View file

@ -0,0 +1,94 @@
---
title: GStreamer Application Development Manual
short-description: Complete walkthrough for building an application using GStreamer
...
# GStreamer Application Development Manual
# Foreword
GStreamer is an extremely powerful and versatile framework for creating
streaming media applications. Many of the virtues of the GStreamer
framework come from its modularity: GStreamer can seamlessly incorporate
new plugin modules. But because modularity and power often come at a
cost of greater complexity, writing new applications is not always easy.
This guide is intended to help you understand the GStreamer framework
(version 1.9.0.1) so you can develop applications based on it. The first
chapters will focus on development of a simple audio player, with much
effort going into helping you understand GStreamer concepts. Later
chapters will go into more advanced topics related to media playback,
but also at other forms of media processing (capture, editing, etc.).
# Introduction
## Who should read this manual?
This book is about GStreamer from an application developer's point of
view; it describes how to write a GStreamer application using the
GStreamer libraries and tools. For an explanation about writing plugins,
we suggest the [Plugin Writers Guide](pwg-index.md).
Also check out the other documentation available on the [GStreamer web
site](http://gstreamer.freedesktop.org/documentation/).
## Preliminary reading
In order to understand this manual, you need to have a basic
understanding of the *C language*.
Since GStreamer adheres to the GObject programming model, this guide
also assumes that you understand the basics of
[GObject](http://library.gnome.org/devel/gobject/stable/) and
[glib](http://library.gnome.org/devel/glib/stable/) programming.
Especially,
- GObject instantiation
- GObject properties (set/get)
- GObject casting
- GObject referecing/dereferencing
- glib memory management
- glib signals and callbacks
- glib main loop
## Structure of this manual
To help you navigate through this guide, it is divided into several
large parts. Each part addresses a particular broad topic concerning
GStreamer appliction development. The parts of this guide are laid out
in the following order:
[About GStreamer](manual-introduction.md) gives you an overview of
GStreamer, it's design principles and foundations.
[Building an Application](manual-building.md) covers the basics of
GStreamer application programming. At the end of this part, you should
be able to build your own audio player using GStreamer
In [Advanced GStreamer concepts](manual-advanced.md), we will move on to
advanced subjects which make GStreamer stand out of its competitors. We
will discuss application-pipeline interaction using dynamic parameters
and interfaces, we will discuss threading and threaded pipelines,
scheduling and clocks (and synchronization). Most of those topics are
not just there to introduce you to their API, but primarily to give a
deeper insight in solving application programming problems with
GStreamer and understanding their concepts.
Next, in [Higher-level interfaces for GStreamer
applications](manual-highlevel.md), we will go into higher-level
programming APIs for GStreamer. You don't exactly need to know all the
details from the previous parts to understand this, but you will need to
understand basic GStreamer concepts nevertheless. We will, amongst
others, discuss XML, playbin and autopluggers.
Finally in [Appendices](manual-appendices.md), you will find some random
information on integrating with GNOME, KDE, OS X or Windows, some
debugging help and general tips to improve and simplify GStreamer
programming.

118
manual-init.md Normal file
View file

@ -0,0 +1,118 @@
---
title: Initializing GStreamer
...
# Initializing GStreamer
When writing a GStreamer application, you can simply include `gst/gst.h`
to get access to the library functions. Besides that, you will also need
to initialize the GStreamer library.
# Simple initialization
Before the GStreamer libraries can be used, `gst_init` has to be called
from the main application. This call will perform the necessary
initialization of the library as well as parse the GStreamer-specific
command line options.
A typical program \[1\] would have code to initialize GStreamer that
looks like this:
```
#include <stdio.h>
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
const gchar *nano_str;
guint major, minor, micro, nano;
gst_init (&argc, &argv);
gst_version (&major, &minor, &micro, &nano);
if (nano == 1)
nano_str = "(CVS)";
else if (nano == 2)
nano_str = "(Prerelease)";
else
nano_str = "";
printf ("This program is linked against GStreamer %d.%d.%d %s\n",
major, minor, micro, nano_str);
return 0;
}
```
Use the `GST_VERSION_MAJOR`, `GST_VERSION_MINOR` and `GST_VERSION_MICRO`
macros to get the GStreamer version you are building against, or use the
function `gst_version` to get the version your application is linked
against. GStreamer currently uses a scheme where versions with the same
major and minor versions are API-/ and ABI-compatible.
It is also possible to call the `gst_init` function with two `NULL`
arguments, in which case no command line options will be parsed by
GStreamer.
# The GOption interface
You can also use a GOption table to initialize your own parameters as
shown in the next example:
```
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
gboolean silent = FALSE;
gchar *savefile = NULL;
GOptionContext *ctx;
GError *err = NULL;
GOptionEntry entries[] = {
{ "silent", 's', 0, G_OPTION_ARG_NONE, &silent,
"do not output status information", NULL },
{ "output", 'o', 0, G_OPTION_ARG_STRING, &savefile,
"save xml representation of pipeline to FILE and exit", "FILE" },
{ NULL }
};
ctx = g_option_context_new ("- Your application");
g_option_context_add_main_entries (ctx, entries, NULL);
g_option_context_add_group (ctx, gst_init_get_option_group ());
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
g_print ("Failed to initialize: %s\n", err->message);
g_clear_error (&err);
g_option_context_free (ctx);
return 1;
}
g_option_context_free (ctx);
printf ("Run me with --help to see the Application options appended.\n");
return 0;
}
```
As shown in this fragment, you can use a
[GOption](http://developer.gnome.org/glib/stable/glib-Commandline-option-parser.html)
table to define your application-specific command line options, and pass
this table to the GLib initialization function along with the option
group returned from the function `gst_init_get_option_group`. Your
application options will be parsed in addition to the standard GStreamer
options.
1. The code for this example is automatically extracted from the
documentation and built under `tests/examples/manual` in the
GStreamer tarball.

64
manual-interfaces.md Normal file
View file

@ -0,0 +1,64 @@
---
title: Interfaces
...
# Interfaces
In [Using an element as a
GObject](manual-elements.md#using-an-element-as-a-gobject), you have
learned how to use `GObject` properties as a simple way to do
interaction between applications and elements. This method suffices for
the simple'n'straight settings, but fails for anything more complicated
than a getter and setter. For the more complicated use cases, GStreamer
uses interfaces based on the GObject
[`GTypeInterface`](http://library.gnome.org/devel/gobject/stable/gtype-non-instantiable-classed.html)
type.
Most of the interfaces handled here will not contain any example code.
See the API references for details. Here, we will just describe the
scope and purpose of each interface.
# The URI interface
In all examples so far, we have only supported local files through the
“filesrc” element. GStreamer, obviously, supports many more location
sources. However, we don't want applications to need to know any
particular element implementation details, such as element names for
particular network source types and so on. Therefore, there is a URI
interface, which can be used to get the source element that supports a
particular URI type. There is no strict rule for URI naming, but in
general we follow naming conventions that others use, too. For example,
assuming you have the correct plugins installed, GStreamer supports
“file:///\<path\>/\<file\>”, “http://\<host\>/\<path\>/\<file\>”,
“mms://\<host\>/\<path\>/\<file\>”, and so on.
In order to get the source or sink element supporting a particular URI,
use `gst_element_make_from_uri ()`, with the URI type being either
`GST_URI_SRC` for a source element, or `GST_URI_SINK` for a sink
element.
You can convert filenames to and from URIs using GLib's
`g_filename_to_uri ()` and `g_uri_to_filename ()`.
# The Color Balance interface
The colorbalance interface is a way to control video-related properties
on an element, such as brightness, contrast and so on. It's sole reason
for existence is that, as far as its authors know, there's no way to
dynamically register properties using `GObject`.
The colorbalance interface is implemented by several plugins, including
xvimagesink and the Video4linux2 elements.
# The Video Overlay interface
The Video Overlay interface was created to solve the problem of
embedding video streams in an application window. The application
provides an window handle to the element implementing this interface to
draw on, and the element will then use this window handle to draw on
rather than creating a new toplevel window. This is useful to embed
video in video players.
This interface is implemented by, amongst others, the Video4linux2
elements and by ximagesink, xvimagesink and sdlvideosink.

222
manual-intgration.md Normal file
View file

@ -0,0 +1,222 @@
---
title: Integration
...
# Integration
GStreamer tries to integrate closely with operating systems (such as
Linux and UNIX-like operating systems, OS X or Windows) and desktop
environments (such as GNOME or KDE). In this chapter, we'll mention some
specific techniques to integrate your application with your operating
system or desktop environment of choice.
# Linux and UNIX-like operating systems
GStreamer provides a basic set of elements that are useful when
integrating with Linux or a UNIX-like operating system.
- For audio input and output, GStreamer provides input and output
elements for several audio subsystems. Amongst others, GStreamer
includes elements for ALSA (alsasrc, alsasink), OSS (osssrc,
osssink) Pulesaudio (pulsesrc, pulsesink) and Sun audio
(sunaudiosrc, sunaudiomixer, sunaudiosink).
- For video input, GStreamer contains source elements for Video4linux2
(v4l2src, v4l2element, v4l2sink).
- For video output, GStreamer provides elements for output to
X-windows (ximagesink), Xv-windows (xvimagesink; for
hardware-accelerated video), direct-framebuffer (dfbimagesink) and
openGL image contexts (glsink).
# GNOME desktop
GStreamer has been the media backend of the
[GNOME](http://www.gnome.org/) desktop since GNOME-2.2 onwards.
Nowadays, a whole bunch of GNOME applications make use of GStreamer for
media-processing, including (but not limited to)
[Rhythmbox](http://www.rhythmbox.org/),
[Videos](https://wiki.gnome.org/Apps/Videos) and [Sound
Juicer](https://wiki.gnome.org/Apps/SoundJuicer).
Most of these GNOME applications make use of some specific techniques to
integrate as closely as possible with the GNOME desktop:
- GNOME applications usually call `gtk_init ()` to parse command-line
options and initialize GTK. GStreamer applications would normally
call `gst_init ()` to do the same for GStreamer. This would mean
that only one of the two can parse command-line options. To work
around this issue, GStreamer can provide a GLib `GOptionGroup` which
can be passed to `gnome_program_init ()`. The following example
requires GTK 2.6 or newer (previous GTK versions do not support
command line parsing via GOption yet)
```
#include <gtk/gtk.h>
#include <gst/gst.h>
static gchar **cmd_filenames = NULL;
static GOptionEntries cmd_options[] = {
/* here you can add command line options for your application. Check
* the GOption section in the GLib API reference for a more elaborate
* example of how to add your own command line options here */
/* at the end we have a special option that collects all remaining
* command line arguments (like filenames) for us. If you don't
* need this, you can safely remove it */
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &cmd_filenames,
"Special option that collects any remaining arguments for us" },
/* mark the end of the options array with a NULL option */
{ NULL, }
};
/* this should usually be defined in your config.h */
#define VERSION "0.0.1"
gint
main (gint argc, gchar **argv)
{
GOptionContext *context;
GOptionGroup *gstreamer_group, *gtk_group;
GError *err = NULL;
context = g_option_context_new ("gtk-demo-app");
/* get command line options from GStreamer and add them to the group */
gstreamer_group = gst_init_get_option_group ();
g_option_context_add_group (context, gstreamer_group);
gtk_group = gtk_get_option_group (TRUE);
g_option_context_add_group (context, gtk_group);
/* add our own options. If you are using gettext for translation of your
* strings, use GETTEXT_PACKAGE here instead of NULL */
g_option_context_add_main_entries (context, cmd_options, NULL);
/* now parse the commandline options, note that this already
* calls gtk_init() and gst_init() */
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
g_print ("Error initializing: %s\n", err->message);
g_clear_error (&err);
g_option_context_free (ctx);
exit (1);
}
g_option_context_free (ctx);
/* any filenames we got passed on the command line? parse them! */
if (cmd_filenames != NULL) {
guint i, num;
num = g_strv_length (cmd_filenames);
for (i = 0; i < num; ++i) {
/* do something with the filename ... */
g_print ("Adding to play queue: %s\n", cmd_filenames[i]);
}
g_strfreev (cmd_filenames);
cmd_filenames = NULL;
}
[..]
}
```
- GNOME uses Pulseaudio for audio, use the pulsesrc and pulsesink
elements to have access to all the features.
- GStreamer provides data input/output elements for use with the GIO
VFS system. These elements are called “giosrc” and “giosink”. The
deprecated GNOME-VFS system is supported too but shouldn't be used
for any new applications.
# KDE desktop
GStreamer has been proposed for inclusion in KDE-4.0. Currently,
GStreamer is included as an optional component, and it's used by several
KDE applications, including [AmaroK](http://amarok.kde.org/),
[KMPlayer](http://www.xs4all.nl/~jjvrieze/kmplayer.html) and
[Kaffeine](http://kaffeine.sourceforge.net/).
Although not yet as complete as the GNOME integration bits, there are
already some KDE integration specifics available. This list will
probably grow as GStreamer starts to be used in KDE-4.0:
- AmaroK contains a kiosrc element, which is a source element that
integrates with the KDE VFS subsystem KIO.
# OS X
GStreamer provides native video and audio output elements for OS X. It
builds using the standard development tools for OS X.
# Windows
> **Warning**
>
> Note: this section is out of date. GStreamer-1.0 has much better
> support for win32 than previous versions though and should usually
> compile and work out-of-the-box both using MSYS/MinGW or Microsoft
> compilers. The [GStreamer web site](http://gstreamer.freedesktop.org)
> and the [mailing list
> archives](http://news.gmane.org/gmane.comp.video.gstreamer.devel) are
> a good place to check the latest win32-related news.
GStreamer builds using Microsoft Visual C .NET 2003 and using Cygwin.
## Building GStreamer under Win32
There are different makefiles that can be used to build GStreamer with
the usual Microsoft compiling tools.
The Makefile is meant to be used with the GNU make program and the free
version of the Microsoft compiler
(<http://msdn.microsoft.com/visualc/vctoolkit2003/>). You also have to
modify your system environment variables to use it from the
command-line. You will also need a working Platform SDK for Windows that
is available for free from Microsoft.
The projects/makefiles will generate automatically some source files
needed to compile GStreamer. That requires that you have installed on
your system some GNU tools and that they are available in your system
PATH.
The GStreamer project depends on other libraries, namely :
- GLib
- libxml2
- libintl
- libiconv
Work is being done to provide pre-compiled GStreamer-1.0 libraries as a
packages for win32. Check the [GStreamer web
site](http://gstreamer.freedesktop.org) and check our [mailing
list](http://news.gmane.org/gmane.comp.video.gstreamer.devel) for the
latest developments in this respect.
> **Note**
>
> GNU tools needed that you can find on
> <http://gnuwin32.sourceforge.net/>
>
> - GNU flex (tested with 2.5.4)
>
> - GNU bison (tested with 1.35)
>
> and <http://www.mingw.org/>
>
> - GNU make (tested with 3.80)
>
> the generated files from the -auto makefiles will be available soon
> separately on the net for convenience (people who don't want to
> install GNU tools).
## Installation on the system
FIXME: This section needs be updated for GStreamer-1.0.

109
manual-intro-basics.md Normal file
View file

@ -0,0 +1,109 @@
---
title: Foundations
...
# Foundations
This chapter of the guide introduces the basic concepts of GStreamer.
Understanding these concepts will be important in reading any of the
rest of this guide, all of them assume understanding of these basic
concepts.
# Elements
An *element* is the most important class of objects in GStreamer. You
will usually create a chain of elements linked together and let data
flow through this chain of elements. An element has one specific
function, which can be the reading of data from a file, decoding of this
data or outputting this data to your sound card (or anything else). By
chaining together several such elements, you create a *pipeline* that
can do a specific task, for example media playback or capture. GStreamer
ships with a large collection of elements by default, making the
development of a large variety of media applications possible. If
needed, you can also write new elements. That topic is explained in
great deal in the *GStreamer Plugin Writer's Guide*.
# Pads
*Pads* are element's input and output, where you can connect other
elements. They are used to negotiate links and data flow between
elements in GStreamer. A pad can be viewed as a “plug” or “port” on an
element where links may be made with other elements, and through which
data can flow to or from those elements. Pads have specific data
handling capabilities: a pad can restrict the type of data that flows
through it. Links are only allowed between two pads when the allowed
data types of the two pads are compatible. Data types are negotiated
between pads using a process called *caps negotiation*. Data types are
described as a `GstCaps`.
An analogy may be helpful here. A pad is similar to a plug or jack on a
physical device. Consider, for example, a home theater system consisting
of an amplifier, a DVD player, and a (silent) video projector. Linking
the DVD player to the amplifier is allowed because both devices have
audio jacks, and linking the projector to the DVD player is allowed
because both devices have compatible video jacks. Links between the
projector and the amplifier may not be made because the projector and
amplifier have different types of jacks. Pads in GStreamer serve the
same purpose as the jacks in the home theater system.
For the most part, all data in GStreamer flows one way through a link
between elements. Data flows out of one element through one or more
*source pads*, and elements accept incoming data through one or more
*sink pads*. Source and sink elements have only source and sink pads,
respectively. Data usually means buffers (described by the
[`GstBuffer`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/gstreamer-GstBuffer.html)
object) and events (described by the
[`GstEvent`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/gstreamer-GstEvent.html)
object).
# Bins and pipelines
A *bin* is a container for a collection of elements. Since bins are
subclasses of elements themselves, you can mostly control a bin as if it
were an element, thereby abstracting away a lot of complexity for your
application. You can, for example change state on all elements in a bin
by changing the state of that bin itself. Bins also forward bus messages
from their contained children (such as error messages, tag messages or
EOS messages).
A *pipeline* is a top-level bin. It provides a bus for the application
and manages the synchronization for its children. As you set it to
PAUSED or PLAYING state, data flow will start and media processing will
take place. Once started, pipelines will run in a separate thread until
you stop them or the end of the data stream is reached.
![GStreamer pipeline for a simple ogg player](images/simple-player.png
"fig:")
# Communication
GStreamer provides several mechanisms for communication and data
exchange between the *application* and the *pipeline*.
- *buffers* are objects for passing streaming data between elements in
the pipeline. Buffers always travel from sources to sinks
(downstream).
- *events* are objects sent between elements or from the application
to elements. Events can travel upstream and downstream. Downstream
events can be synchronised to the data flow.
- *messages* are objects posted by elements on the pipeline's message
bus, where they will be held for collection by the application.
Messages can be intercepted synchronously from the streaming thread
context of the element posting the message, but are usually handled
asynchronously by the application from the application's main
thread. Messages are used to transmit information such as errors,
tags, state changes, buffering state, redirects etc. from elements
to the application in a thread-safe way.
- *queries* allow applications to request information such as duration
or current playback position from the pipeline. Queries are always
answered synchronously. Elements can also use queries to request
information from their peer elements (such as the file size or
duration). They can be used both ways within a pipeline, but
upstream queries are more common.
![GStreamer pipeline with different communication
flows](images/communication.png "fig:")

9
manual-introduction.md Normal file
View file

@ -0,0 +1,9 @@
---
title: About GStreamer
...
# About GStreamer
This part gives you an overview of the technologies described in this
book.

93
manual-licensing.md Normal file
View file

@ -0,0 +1,93 @@
---
title: Licensing advisory
...
# Licensing advisory
# How to license the applications you build with GStreamer
The licensing of GStreamer is no different from a lot of other libraries
out there like GTK+ or glibc: we use the LGPL. What complicates things
with regards to GStreamer is its plugin-based design and the heavily
patented and proprietary nature of many multimedia codecs. While patents
on software are currently only allowed in a small minority of world
countries (the US and Australia being the most important of those), the
problem is that due to the central place the US hold in the world
economy and the computing industry, software patents are hard to ignore
wherever you are. Due to this situation, many companies, including major
GNU/Linux distributions, get trapped in a situation where they either
get bad reviews due to lacking out-of-the-box media playback
capabilities (and attempts to educate the reviewers have met with little
success so far), or go against their own - and the free software
movement's - wish to avoid proprietary software. Due to competitive
pressure, most choose to add some support. Doing that through pure free
software solutions would have them risk heavy litigation and punishment
from patent owners. So when the decision is made to include support for
patented codecs, it leaves them the choice of either using special
proprietary applications, or try to integrate the support for these
codecs through proprietary plugins into the multimedia infrastructure
provided by GStreamer. Faced with one of these two evils the GStreamer
community of course prefer the second option.
The problem which arises is that most free software and open source
applications developed use the GPL as their license. While this is
generally a good thing, it creates a dilemma for people who want to put
together a distribution. The dilemma they face is that if they include
proprietary plugins in GStreamer to support patented formats in a way
that is legal for them, they do risk running afoul of the GPL license of
the applications. We have gotten some conflicting reports from lawyers
on whether this is actually a problem, but the official stance of the
FSF is that it is a problem. We view the FSF as an authority on this
matter, so we are inclined to follow their interpretation of the GPL
license.
So what does this mean for you as an application developer? Well, it
means you have to make an active decision on whether you want your
application to be used together with proprietary plugins or not. What
you decide here will also influence the chances of commercial
distributions and Unix vendors shipping your application. The GStreamer
community suggest you license your software using a license that will
allow proprietary plugins to be bundled with GStreamer and your
applications, in order to make sure that as many vendors as possible go
with GStreamer instead of less free solutions. This in turn we hope and
think will let GStreamer be a vehicle for wider use of free formats like
the Xiph.org formats.
If you do decide that you want to allow for non-free plugins to be used
with your application you have a variety of choices. One of the simplest
is using licenses like LGPL, MPL or BSD for your application instead of
the GPL. Or you can add an exception clause to your GPL license stating
that you except GStreamer plugins from the obligations of the GPL.
A good example of such a GPL exception clause would be, using the Totem
video player project as an example: The authors of the Totem video
player project hereby grants permission for non-GPL-compatible GStreamer
plugins to be used and distributed together with GStreamer and Totem.
This permission goes above and beyond the permissions granted by the GPL
license Totem is covered by.
Our suggestion among these choices is to use the LGPL license, as it is
what resembles the GPL most and it makes it a good licensing fit with
the major GNU/Linux desktop projects like GNOME and KDE. It also allows
you to share code more openly with projects that have compatible
licenses. Obviously, pure GPL code without the above-mentioned clause is
not usable in your application as such. By choosing the LGPL, there is
no need for an exception clause and thus code can be shared more freely.
I have above outlined the practical reasons for why the GStreamer
community suggests you allow non-free plugins to be used with your
applications. We feel that in the multimedia arena, the free software
community is still not strong enough to set the agenda and that blocking
non-free plugins to be used in our infrastructure hurts us more than it
hurts the patent owners and their ilk.
This view is not shared by everyone. The Free Software Foundation urges
you to use an unmodified GPL for your applications, so as to push back
against the temptation to use non-free plug-ins. They say that since not
everyone else has the strength to reject them because they are
unethical, they ask your help to give them a legal reason to do so.
This advisory is part of a bigger advisory with a FAQ which you can find
on the [GStreamer
website](http://gstreamer.freedesktop.org/documentation/licensing.html)

183
manual-metadata.md Normal file
View file

@ -0,0 +1,183 @@
---
title: Metadata
...
# Metadata
GStreamer makes a clear distinction between two types of metadata, and
has support for both types. The first is stream tags, which describe the
content of a stream in a non-technical way. Examples include the author
of a song, the title of that very same song or the album it is a part
of. The other type of metadata is stream-info, which is a somewhat
technical description of the properties of a stream. This can include
video size, audio samplerate, codecs used and so on. Tags are handled
using the GStreamer tagging system. Stream-info can be retrieved from a
`GstPad` by getting the current (negotiated) `GstCaps` for that pad.
# Metadata reading
Stream information can most easily be read by reading it from a
`GstPad`. This has already been discussed before in [Using capabilities
for metadata](manual-pads.md#using-capabilities-for-metadata).
Therefore, we will skip it here. Note that this requires access to all
pads of which you want stream information.
Tag reading is done through a bus in GStreamer, which has been discussed
previously in [Bus](manual-bus.md). You can listen for
`GST_MESSAGE_TAG` messages and handle them as you wish.
Note, however, that the `GST_MESSAGE_TAG` message may be fired multiple
times in the pipeline. It is the application's responsibility to put all
those tags together and display them to the user in a nice, coherent
way. Usually, using `gst_tag_list_merge ()` is a good enough way of
doing this; make sure to empty the cache when loading a new song, or
after every few minutes when listening to internet radio. Also, make
sure you use `GST_TAG_MERGE_PREPEND` as merging mode, so that a new
title (which came in later) has a preference over the old one for
display.
The following example will extract tags from a file and print them:
```
/* compile with:
* gcc -o tags tags.c `pkg-config --cflags --libs gstreamer-1.0` */
#include <gst/gst.h>
static void
print_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data)
{
int i, num;
num = gst_tag_list_get_tag_size (list, tag);
for (i = 0; i < num; ++i) {
const GValue *val;
/* Note: when looking for specific tags, use the gst_tag_list_get_xyz() API,
* we only use the GValue approach here because it is more generic */
val = gst_tag_list_get_value_index (list, tag, i);
if (G_VALUE_HOLDS_STRING (val)) {
g_print ("\t%20s : %s\n", tag, g_value_get_string (val));
} else if (G_VALUE_HOLDS_UINT (val)) {
g_print ("\t%20s : %u\n", tag, g_value_get_uint (val));
} else if (G_VALUE_HOLDS_DOUBLE (val)) {
g_print ("\t%20s : %g\n", tag, g_value_get_double (val));
} else if (G_VALUE_HOLDS_BOOLEAN (val)) {
g_print ("\t%20s : %s\n", tag,
(g_value_get_boolean (val)) ? "true" : "false");
} else if (GST_VALUE_HOLDS_BUFFER (val)) {
GstBuffer *buf = gst_value_get_buffer (val);
guint buffer_size = gst_buffer_get_size (buf);
g_print ("\t%20s : buffer of size %u\n", tag, buffer_size);
} else if (GST_VALUE_HOLDS_DATE_TIME (val)) {
GstDateTime *dt = g_value_get_boxed (val);
gchar *dt_str = gst_date_time_to_iso8601_string (dt);
g_print ("\t%20s : %s\n", tag, dt_str);
g_free (dt_str);
} else {
g_print ("\t%20s : tag of type '%s'\n", tag, G_VALUE_TYPE_NAME (val));
}
}
}
static void
on_new_pad (GstElement * dec, GstPad * pad, GstElement * fakesink)
{
GstPad *sinkpad;
sinkpad = gst_element_get_static_pad (fakesink, "sink");
if (!gst_pad_is_linked (sinkpad)) {
if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)
g_error ("Failed to link pads!");
}
gst_object_unref (sinkpad);
}
int
main (int argc, char ** argv)
{
GstElement *pipe, *dec, *sink;
GstMessage *msg;
gchar *uri;
gst_init (&argc, &argv);
if (argc < 2)
g_error ("Usage: %s FILE or URI", argv[0]);
if (gst_uri_is_valid (argv[1])) {
uri = g_strdup (argv[1]);
} else {
uri = gst_filename_to_uri (argv[1], NULL);
}
pipe = gst_pipeline_new ("pipeline");
dec = gst_element_factory_make ("uridecodebin", NULL);
g_object_set (dec, "uri", uri, NULL);
gst_bin_add (GST_BIN (pipe), dec);
sink = gst_element_factory_make ("fakesink", NULL);
gst_bin_add (GST_BIN (pipe), sink);
g_signal_connect (dec, "pad-added", G_CALLBACK (on_new_pad), sink);
gst_element_set_state (pipe, GST_STATE_PAUSED);
while (TRUE) {
GstTagList *tags = NULL;
msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe),
GST_CLOCK_TIME_NONE,
GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_TAG | GST_MESSAGE_ERROR);
if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_TAG) /* error or async_done */
break;
gst_message_parse_tag (msg, &tags);
g_print ("Got tags from element %s:\n", GST_OBJECT_NAME (msg->src));
gst_tag_list_foreach (tags, print_one_tag, NULL);
g_print ("\n");
gst_tag_list_unref (tags);
gst_message_unref (msg);
}
if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
GError *err = NULL;
gst_message_parse_error (msg, &err, NULL);
g_printerr ("Got error: %s\n", err->message);
g_error_free (err);
}
gst_message_unref (msg);
gst_element_set_state (pipe, GST_STATE_NULL);
gst_object_unref (pipe);
g_free (uri);
return 0;
}
```
# Tag writing
Tag writing is done using the
[`GstTagSetter`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstTagSetter.html)
interface. All that's required is a tag-set-supporting element in your
pipeline. In order to see if any of the elements in your pipeline
supports tag writing, you can use the function
`gst_bin_iterate_all_by_interface (pipeline,
GST_TYPE_TAG_SETTER)`. On the resulting element, usually an encoder or
muxer, you can use `gst_tag_setter_merge
()` (with a taglist) or `gst_tag_setter_add
()` (with individual tags) to set tags on it.
A nice extra feature in GStreamer tag support is that tags are preserved
in pipelines. This means that if you transcode one file containing tags
into another media type, and that new media type supports tags too, then
the tags will be handled as part of the data stream and be merged into
the newly written media file, too.

95
manual-motivation.md Normal file
View file

@ -0,0 +1,95 @@
---
title: Design principles
...
# Design principles
# Clean and powerful
GStreamer provides a clean interface to:
- The application programmer who wants to build a media pipeline. The
programmer can use an extensive set of powerful tools to create
media pipelines without writing a single line of code. Performing
complex media manipulations becomes very easy.
- The plugin programmer. Plugin programmers are provided a clean and
simple API to create self-contained plugins. An extensive debugging
and tracing mechanism has been integrated. GStreamer also comes with
an extensive set of real-life plugins that serve as examples too.
# Object oriented
GStreamer adheres to GObject, the GLib 2.0 object model. A programmer
familiar with GLib 2.0 or GTK+ will be comfortable with GStreamer.
GStreamer uses the mechanism of signals and object properties.
All objects can be queried at runtime for their various properties and
capabilities.
GStreamer intends to be similar in programming methodology to GTK+. This
applies to the object model, ownership of objects, reference counting,
etc.
# Extensible
All GStreamer Objects can be extended using the GObject inheritance
methods.
All plugins are loaded dynamically and can be extended and upgraded
independently.
# Allow binary-only plugins
Plugins are shared libraries that are loaded at runtime. Since all the
properties of the plugin can be set using the GObject properties, there
is no need (and in fact no way) to have any header files installed for
the plugins.
Special care has been taken to make plugins completely self-contained.
All relevant aspects of plugins can be queried at run-time.
# High performance
High performance is obtained by:
- using GLib's `GSlice` allocator
- extremely light-weight links between plugins. Data can travel the
pipeline with minimal overhead. Data passing between plugins only
involves a pointer dereference in a typical pipeline.
- providing a mechanism to directly work on the target memory. A
plugin can for example directly write to the X server's shared
memory space. Buffers can also point to arbitrary memory, such as a
sound card's internal hardware buffer.
- refcounting and copy on write minimize usage of memcpy. Sub-buffers
efficiently split buffers into manageable pieces.
- dedicated streaming threads, with scheduling handled by the kernel.
- allowing hardware acceleration by using specialized plugins.
- using a plugin registry with the specifications of the plugins so
that the plugin loading can be delayed until the plugin is actually
used.
# Clean core/plugins separation
The core of GStreamer is essentially media-agnostic. It only knows about
bytes and blocks, and only contains basic elements. The core of
GStreamer is functional enough to even implement low-level system tools,
like cp.
All of the media handling functionality is provided by plugins external
to the core. These tell the core how to handle specific types of media.
# Provide a framework for codec experimentation
GStreamer also wants to be an easy framework where codec developers can
experiment with different algorithms, speeding up the development of
open and free multimedia codecs like those developed by the [Xiph.Org
Foundation](http://www.xiph.org) (such as Theora and Vorbis).

543
manual-pads.md Normal file
View file

@ -0,0 +1,543 @@
---
title: Pads and capabilities
...
# Pads and capabilities
As we have seen in [Elements](manual-elements.md), the pads are the
element's interface to the outside world. Data streams from one
element's source pad to another element's sink pad. The specific type of
media that the element can handle will be exposed by the pad's
capabilities. We will talk more on capabilities later in this chapter
(see [Capabilities of a pad](#capabilities-of-a-pad)).
# Pads
A pad type is defined by two properties: its direction and its
availability. As we've mentioned before, GStreamer defines two pad
directions: source pads and sink pads. This terminology is defined from
the view of within the element: elements receive data on their sink pads
and generate data on their source pads. Schematically, sink pads are
drawn on the left side of an element, whereas source pads are drawn on
the right side of an element. In such graphs, data flows from left to
right. \[1\]
Pad directions are very simple compared to pad availability. A pad can
have any of three availabilities: always, sometimes and on request. The
meaning of those three types is exactly as it says: always pads always
exist, sometimes pad exist only in certain cases (and can disappear
randomly), and on-request pads appear only if explicitly requested by
applications.
## Dynamic (or sometimes) pads
Some elements might not have all of their pads when the element is
created. This can happen, for example, with an Ogg demuxer element. The
element will read the Ogg stream and create dynamic pads for each
contained elementary stream (vorbis, theora) when it detects such a
stream in the Ogg stream. Likewise, it will delete the pad when the
stream ends. This principle is very useful for demuxer elements, for
example.
Running gst-inspect oggdemux will show that the element has only one
pad: a sink pad called 'sink'. The other pads are “dormant”. You can see
this in the pad template because there is an “Exists: Sometimes”
property. Depending on the type of Ogg file you play, the pads will be
created. We will see that this is very important when you are going to
create dynamic pipelines. You can attach a signal handler to an element
to inform you when the element has created a new pad from one of its
“sometimes” pad templates. The following piece of code is an example
of how to do this:
```
#include <gst/gst.h>
static void
cb_new_pad (GstElement *element,
GstPad *pad,
gpointer data)
{
gchar *name;
name = gst_pad_get_name (pad);
g_print ("A new pad %s was created\n", name);
g_free (name);
/* here, you would setup a new pad link for the newly created pad */
[..]
}
int
main (int argc,
char *argv[])
{
GstElement *pipeline, *source, *demux;
GMainLoop *loop;
/* init */
gst_init (&argc, &argv);
/* create elements */
pipeline = gst_pipeline_new ("my_pipeline");
source = gst_element_factory_make ("filesrc", "source");
g_object_set (source, "location", argv[1], NULL);
demux = gst_element_factory_make ("oggdemux", "demuxer");
/* you would normally check that the elements were created properly */
/* put together a pipeline */
gst_bin_add_many (GST_BIN (pipeline), source, demux, NULL);
gst_element_link_pads (source, "src", demux, "sink");
/* listen for newly created pads */
g_signal_connect (demux, "pad-added", G_CALLBACK (cb_new_pad), NULL);
/* start the pipeline */
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
[..]
}
```
It is not uncommon to add elements to the pipeline only from within the
"pad-added" callback. If you do this, don't forget to set the state of
the newly-added elements to the target state of the pipeline using
`gst_element_set_state ()` or `gst_element_sync_state_with_parent ()`.
## Request pads
An element can also have request pads. These pads are not created
automatically but are only created on demand. This is very useful for
multiplexers, aggregators and tee elements. Aggregators are elements
that merge the content of several input streams together into one output
stream. Tee elements are the reverse: they are elements that have one
input stream and copy this stream to each of their output pads, which
are created on request. Whenever an application needs another copy of
the stream, it can simply request a new output pad from the tee element.
The following piece of code shows how you can request a new output pad
from a “tee” element:
```
static void
some_function (GstElement *tee)
{
GstPad * pad;
gchar *name;
pad = gst_element_get_request_pad (tee, "src%d");
name = gst_pad_get_name (pad);
g_print ("A new pad %s was created\n", name);
g_free (name);
/* here, you would link the pad */
[..]
/* and, after doing that, free our reference */
gst_object_unref (GST_OBJECT (pad));
}
```
The `gst_element_get_request_pad ()` method can be used to get a pad
from the element based on the name of the pad template. It is also
possible to request a pad that is compatible with another pad template.
This is very useful if you want to link an element to a multiplexer
element and you need to request a pad that is compatible. The method
`gst_element_get_compatible_pad ()` can be used to request a compatible
pad, as shown in the next example. It will request a compatible pad from
an Ogg multiplexer from any input.
```
static void
link_to_multiplexer (GstPad *tolink_pad,
GstElement *mux)
{
GstPad *pad;
gchar *srcname, *sinkname;
srcname = gst_pad_get_name (tolink_pad);
pad = gst_element_get_compatible_pad (mux, tolink_pad);
gst_pad_link (tolinkpad, pad);
sinkname = gst_pad_get_name (pad);
gst_object_unref (GST_OBJECT (pad));
g_print ("A new pad %s was created and linked to %s\n", sinkname, srcname);
g_free (sinkname);
g_free (srcname);
}
```
# Capabilities of a pad
Since the pads play a very important role in how the element is viewed
by the outside world, a mechanism is implemented to describe the data
that can flow or currently flows through the pad by using capabilities.
Here, we will briefly describe what capabilities are and how to use
them, enough to get an understanding of the concept. For an in-depth
look into capabilities and a list of all capabilities defined in
GStreamer, see the [Plugin Writers
Guide](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/index.html).
Capabilities are attached to pad templates and to pads. For pad
templates, it will describe the types of media that may stream over a
pad created from this template. For pads, it can either be a list of
possible caps (usually a copy of the pad template's capabilities), in
which case the pad is not yet negotiated, or it is the type of media
that currently streams over this pad, in which case the pad has been
negotiated already.
## Dissecting capabilities
A pad's capabilities are described in a `GstCaps` object. Internally, a
[`GstCaps`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/gstreamer-GstCaps.html)
will contain one or more
[`GstStructure`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/gstreamer-GstStructure.html)
that will describe one media type. A negotiated pad will have
capabilities set that contain exactly *one* structure. Also, this
structure will contain only *fixed* values. These constraints are not
true for unnegotiated pads or pad templates.
As an example, below is a dump of the capabilities of the “vorbisdec”
element, which you will get by running `gst-inspect vorbisdec`. You will
see two pads: a source and a sink pad. Both of these pads are always
available, and both have capabilities attached to them. The sink pad
will accept vorbis-encoded audio data, with the media type
“audio/x-vorbis”. The source pad will be used to send raw (decoded)
audio samples to the next element, with a raw audio media type (in this
case, “audio/x-raw”). The source pad will also contain properties for
the audio samplerate and the amount of channels, plus some more that you
don't need to worry about for now.
```
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
audio/x-raw
format: F32LE
rate: [ 1, 2147483647 ]
channels: [ 1, 256 ]
SINK template: 'sink'
Availability: Always
Capabilities:
audio/x-vorbis
```
## Properties and values
Properties are used to describe extra information for capabilities. A
property consists of a key (a string) and a value. There are different
possible value types that can be used:
- Basic types, this can be pretty much any `GType` registered with
Glib. Those properties indicate a specific, non-dynamic value for
this property. Examples include:
- An integer value (`G_TYPE_INT`): the property has this exact
value.
- A boolean value (`G_TYPE_BOOLEAN`): the property is either TRUE
or FALSE.
- A float value (`G_TYPE_FLOAT`): the property has this exact
floating point value.
- A string value (`G_TYPE_STRING`): the property contains a UTF-8
string.
- A fraction value (`GST_TYPE_FRACTION`): contains a fraction
expressed by an integer numerator and denominator.
- Range types are `GType`s registered by GStreamer to indicate a range
of possible values. They are used for indicating allowed audio
samplerate values or supported video sizes. The two types defined in
GStreamer are:
- An integer range value (`GST_TYPE_INT_RANGE`): the property
denotes a range of possible integers, with a lower and an upper
boundary. The “vorbisdec” element, for example, has a rate
property that can be between 8000 and 50000.
- A float range value (`GST_TYPE_FLOAT_RANGE`): the property
denotes a range of possible floating point values, with a lower
and an upper boundary.
- A fraction range value (`GST_TYPE_FRACTION_RANGE`): the property
denotes a range of possible fraction values, with a lower and an
upper boundary.
- A list value (`GST_TYPE_LIST`): the property can take any value from
a list of basic values given in this list.
Example: caps that express that either a sample rate of 44100 Hz and
a sample rate of 48000 Hz is supported would use a list of integer
values, with one value being 44100 and one value being 48000.
- An array value (`GST_TYPE_ARRAY`): the property is an array of
values. Each value in the array is a full value on its own, too. All
values in the array should be of the same elementary type. This
means that an array can contain any combination of integers, lists
of integers, integer ranges together, and the same for floats or
strings, but it can not contain both floats and ints at the same
time.
Example: for audio where there are more than two channels involved
the channel layout needs to be specified (for one and two channel
audio the channel layout is implicit unless stated otherwise in the
caps). So the channel layout would be an array of integer enum
values where each enum value represents a loudspeaker position.
Unlike a `GST_TYPE_LIST`, the values in an array will be interpreted
as a whole.
# What capabilities are used for
Capabilities (short: caps) describe the type of data that is streamed
between two pads, or that one pad (template) supports. This makes them
very useful for various purposes:
- Autoplugging: automatically finding elements to link to a pad based
on its capabilities. All autopluggers use this method.
- Compatibility detection: when two pads are linked, GStreamer can
verify if the two pads are talking about the same media type. The
process of linking two pads and checking if they are compatible is
called “caps negotiation”.
- Metadata: by reading the capabilities from a pad, applications can
provide information about the type of media that is being streamed
over the pad, which is information about the stream that is
currently being played back.
- Filtering: an application can use capabilities to limit the possible
media types that can stream between two pads to a specific subset of
their supported stream types. An application can, for example, use
“filtered caps” to set a specific (fixed or non-fixed) video size
that should stream between two pads. You will see an example of
filtered caps later in this manual, in [Manually adding or removing
data from/to a
pipeline](manual-dataaccess.md#manually-adding-or-removing-data-fromto-a-pipeline).
You can do caps filtering by inserting a capsfilter element into
your pipeline and setting its “caps” property. Caps filters are
often placed after converter elements like audioconvert,
audioresample, videoconvert or videoscale to force those converters
to convert data to a specific output format at a certain point in a
stream.
## Using capabilities for metadata
A pad can have a set (i.e. one or more) of capabilities attached to it.
Capabilities (`GstCaps`) are represented as an array of one or more
`GstStructure`s, and each `GstStructure` is an array of fields where
each field consists of a field name string (e.g. "width") and a typed
value (e.g. `G_TYPE_INT` or `GST_TYPE_INT_RANGE`).
Note that there is a distinct difference between the *possible*
capabilities of a pad (ie. usually what you find as caps of pad
templates as they are shown in gst-inspect), the *allowed* caps of a pad
(can be the same as the pad's template caps or a subset of them,
depending on the possible caps of the peer pad) and lastly *negotiated*
caps (these describe the exact format of a stream or buffer and contain
exactly one structure and have no variable bits like ranges or lists,
ie. they are fixed caps).
You can get values of properties in a set of capabilities by querying
individual properties of one structure. You can get a structure from a
caps using `gst_caps_get_structure ()` and the number of structures in a
`GstCaps` using `gst_caps_get_size ()`.
Caps are called *simple caps* when they contain only one structure, and
*fixed caps* when they contain only one structure and have no variable
field types (like ranges or lists of possible values). Two other special
types of caps are *ANY caps* and *empty caps*.
Here is an example of how to extract the width and height from a set of
fixed video caps:
```
static void
read_video_props (GstCaps *caps)
{
gint width, height;
const GstStructure *str;
g_return_if_fail (gst_caps_is_fixed (caps));
str = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_int (str, "width", &width) ||
!gst_structure_get_int (str, "height", &height)) {
g_print ("No width/height available\n");
return;
}
g_print ("The video size of this set of capabilities is %dx%d\n",
width, height);
}
```
## Creating capabilities for filtering
While capabilities are mainly used inside a plugin to describe the media
type of the pads, the application programmer often also has to have
basic understanding of capabilities in order to interface with the
plugins, especially when using filtered caps. When you're using filtered
caps or fixation, you're limiting the allowed types of media that can
stream between two pads to a subset of their supported media types. You
do this using a `capsfilter` element in your pipeline. In order to do
this, you also need to create your own `GstCaps`. The easiest way to do
this is by using the convenience function `gst_caps_new_simple ()`:
```
static gboolean
link_elements_with_filter (GstElement *element1, GstElement *element2)
{
gboolean link_ok;
GstCaps *caps;
caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "I420",
"width", G_TYPE_INT, 384,
"height", G_TYPE_INT, 288,
"framerate", GST_TYPE_FRACTION, 25, 1,
NULL);
link_ok = gst_element_link_filtered (element1, element2, caps);
gst_caps_unref (caps);
if (!link_ok) {
g_warning ("Failed to link element1 and element2!");
}
return link_ok;
}
```
This will force the data flow between those two elements to a certain
video format, width, height and framerate (or the linking will fail if
that cannot be achieved in the context of the elements involved). Keep
in mind that when you use `
gst_element_link_filtered ()` it will automatically create a
`capsfilter` element for you and insert it into your bin or pipeline
between the two elements you want to connect (this is important if you
ever want to disconnect those elements because then you will have to
disconnect both elements from the capsfilter instead).
In some cases, you will want to create a more elaborate set of
capabilities to filter a link between two pads. Then, this function is
too simplistic and you'll want to use the method `gst_caps_new_full ()`:
```
static gboolean
link_elements_with_filter (GstElement *element1, GstElement *element2)
{
gboolean link_ok;
GstCaps *caps;
caps = gst_caps_new_full (
gst_structure_new ("video/x-raw",
"width", G_TYPE_INT, 384,
"height", G_TYPE_INT, 288,
"framerate", GST_TYPE_FRACTION, 25, 1,
NULL),
gst_structure_new ("video/x-bayer",
"width", G_TYPE_INT, 384,
"height", G_TYPE_INT, 288,
"framerate", GST_TYPE_FRACTION, 25, 1,
NULL),
NULL);
link_ok = gst_element_link_filtered (element1, element2, caps);
gst_caps_unref (caps);
if (!link_ok) {
g_warning ("Failed to link element1 and element2!");
}
return link_ok;
}
```
See the API references for the full API of
[`GstStructure`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/gstreamer-GstStructure.html)
and
[`GstCaps`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/gstreamer-GstCaps.html).
# Ghost pads
You can see from [Visualisation of a GstBin element without ghost
pads](#visualisation-of-a-gstbin-------element-without-ghost-pads) how a
bin has no pads of its own. This is where "ghost pads" come into play.
![Visualisation of a
[`GstBin`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstBin.html)
element without ghost pads](images/bin-element-noghost.png "fig:")
A ghost pad is a pad from some element in the bin that can be accessed
directly from the bin as well. Compare it to a symbolic link in UNIX
filesystems. Using ghost pads on bins, the bin also has a pad and can
transparently be used as an element in other parts of your code.
![Visualisation of a
[`GstBin`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstBin.html)
element with a ghost pad](images/bin-element-ghost.png "fig:")
[Visualisation of a GstBin element with a ghost
pad](#visualisation-of-a-gstbin-------element-with-a-ghost-pad) is a
representation of a ghost pad. The sink pad of element one is now also a
pad of the bin. Because ghost pads look and work like any other pads,
they can be added to any type of elements, not just to a `GstBin`, just
like ordinary pads.
A ghostpad is created using the function `gst_ghost_pad_new ()`:
```
#include <gst/gst.h>
int
main (int argc,
char *argv[])
{
GstElement *bin, *sink;
GstPad *pad;
/* init */
gst_init (&argc, &argv);
/* create element, add to bin */
sink = gst_element_factory_make ("fakesink", "sink");
bin = gst_bin_new ("mybin");
gst_bin_add (GST_BIN (bin), sink);
/* add ghostpad */
pad = gst_element_get_static_pad (sink, "sink");
gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
gst_object_unref (GST_OBJECT (pad));
[..]
}
```
In the above example, the bin now also has a pad: the pad called “sink”
of the given element. The bin can, from here on, be used as a substitute
for the sink element. You could, for example, link another element to
the bin.
1. In reality, there is no objection to data flowing from a source pad
to the sink pad of an element upstream (to the left of this element
in drawings). Data will, however, always flow from a source pad of
one element to the sink pad of another.

View file

@ -0,0 +1,416 @@
---
title: Playback Components
...
# Playback Components
GStreamer includes several higher-level components to simplify an
application developer's life. All of the components discussed here (for
now) are targetted at media playback. The idea of each of these
components is to integrate as closely as possible with a GStreamer
pipeline, but to hide the complexity of media type detection and several
other rather complex topics that have been discussed in [Advanced
GStreamer concepts](manual-advanced.md).
We currently recommend people to use either playbin (see
[Playbin](#playbin)) or decodebin (see [Decodebin](#decodebin)),
depending on their needs. Playbin is the recommended solution for
everything related to simple playback of media that should just work.
Decodebin is a more flexible autoplugger that could be used to add more
advanced features, such as playlist support, crossfading of audio tracks
and so on. Its programming interface is more low-level than that of
playbin, though.
# Playbin
Playbin is an element that can be created using the standard GStreamer
API (e.g. `gst_element_factory_make ()`). The factory is conveniently
called “playbin”. By being a `GstPipeline` (and thus a `GstElement`),
playbin automatically supports all of the features of this class,
including error handling, tag support, state handling, getting stream
positions, seeking, and so on.
Setting up a playbin pipeline is as simple as creating an instance of
the playbin element, setting a file location using the “uri” property on
playbin, and then setting the element to the `GST_STATE_PLAYING` state
(the location has to be a valid URI, so “\<protocol\>://\<location\>”,
e.g. file:///tmp/my.ogg or http://www.example.org/stream.ogg).
Internally, playbin will set up a pipeline to playback the media
location.
```
#include <gst/gst.h>
[.. my_bus_callback goes here ..]
gint
main (gint argc,
gchar *argv[])
{
GMainLoop *loop;
GstElement *play;
GstBus *bus;
/* init GStreamer */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* make sure we have a URI */
if (argc != 2) {
g_print ("Usage: %s <URI>\n", argv[0]);
return -1;
}
/* set up */
play = gst_element_factory_make ("playbin", "play");
g_object_set (G_OBJECT (play), "uri", argv[1], NULL);
bus = gst_pipeline_get_bus (GST_PIPELINE (play));
gst_bus_add_watch (bus, my_bus_callback, loop);
gst_object_unref (bus);
gst_element_set_state (play, GST_STATE_PLAYING);
/* now run */
g_main_loop_run (loop);
/* also clean up */
gst_element_set_state (play, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (play));
return 0;
}
```
Playbin has several features that have been discussed previously:
- Settable video and audio output (using the “video-sink” and
“audio-sink” properties).
- Mostly controllable and trackable as a `GstElement`, including error
handling, eos handling, tag handling, state handling (through the
`GstBus`), media position handling and seeking.
- Buffers network-sources, with buffer fullness notifications being
passed through the `GstBus`.
- Supports visualizations for audio-only media.
- Supports subtitles, both in the media as well as from separate
files. For separate subtitle files, use the “suburi” property.
- Supports stream selection and disabling. If your media has multiple
audio or subtitle tracks, you can dynamically choose which one to
play back, or decide to turn it off altogether (which is especially
useful to turn off subtitles). For each of those, use the
“current-text” and other related properties.
For convenience, it is possible to test “playbin” on the commandline,
using the command “gst-launch-1.0 playbin uri=file:///path/to/file”.
# Decodebin
Decodebin is the actual autoplugger backend of playbin, which was
discussed in the previous section. Decodebin will, in short, accept
input from a source that is linked to its sinkpad and will try to detect
the media type contained in the stream, and set up decoder routines for
each of those. It will automatically select decoders. For each decoded
stream, it will emit the “pad-added” signal, to let the client know
about the newly found decoded stream. For unknown streams (which might
be the whole stream), it will emit the “unknown-type” signal. The
application is then responsible for reporting the error to the user.
```
#include <gst/gst.h>
[.. my_bus_callback goes here ..]
GstElement *pipeline, *audio;
static void
cb_newpad (GstElement *decodebin,
GstPad *pad,
gpointer data)
{
GstCaps *caps;
GstStructure *str;
GstPad *audiopad;
/* only link once */
audiopad = gst_element_get_static_pad (audio, "sink");
if (GST_PAD_IS_LINKED (audiopad)) {
g_object_unref (audiopad);
return;
}
/* check media type */
caps = gst_pad_query_caps (pad, NULL);
str = gst_caps_get_structure (caps, 0);
if (!g_strrstr (gst_structure_get_name (str), "audio")) {
gst_caps_unref (caps);
gst_object_unref (audiopad);
return;
}
gst_caps_unref (caps);
/* link'n'play */
gst_pad_link (pad, audiopad);
g_object_unref (audiopad);
}
gint
main (gint argc,
gchar *argv[])
{
GMainLoop *loop;
GstElement *src, *dec, *conv, *sink;
GstPad *audiopad;
GstBus *bus;
/* init GStreamer */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* make sure we have input */
if (argc != 2) {
g_print ("Usage: %s <filename>\n", argv[0]);
return -1;
}
/* setup */
pipeline = gst_pipeline_new ("pipeline");
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, my_bus_callback, loop);
gst_object_unref (bus);
src = gst_element_factory_make ("filesrc", "source");
g_object_set (G_OBJECT (src), "location", argv[1], NULL);
dec = gst_element_factory_make ("decodebin", "decoder");
g_signal_connect (dec, "pad-added", G_CALLBACK (cb_newpad), NULL);
gst_bin_add_many (GST_BIN (pipeline), src, dec, NULL);
gst_element_link (src, dec);
/* create audio output */
audio = gst_bin_new ("audiobin");
conv = gst_element_factory_make ("audioconvert", "aconv");
audiopad = gst_element_get_static_pad (conv, "sink");
sink = gst_element_factory_make ("alsasink", "sink");
gst_bin_add_many (GST_BIN (audio), conv, sink, NULL);
gst_element_link (conv, sink);
gst_element_add_pad (audio,
gst_ghost_pad_new ("sink", audiopad));
gst_object_unref (audiopad);
gst_bin_add (GST_BIN (pipeline), audio);
/* run */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_main_loop_run (loop);
/* cleanup */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
```
Decodebin, similar to playbin, supports the following features:
- Can decode an unlimited number of contained streams to decoded
output pads.
- Is handled as a `GstElement` in all ways, including tag or error
forwarding and state handling.
Although decodebin is a good autoplugger, there's a whole lot of things
that it does not do and is not intended to do:
- Taking care of input streams with a known media type (e.g. a DVD, an
audio-CD or such).
- Selection of streams (e.g. which audio track to play in case of
multi-language media streams).
- Overlaying subtitles over a decoded video stream.
Decodebin can be easily tested on the commandline, e.g. by using the
command `gst-launch-1.0 filesrc location=file.ogg ! decodebin
! audioconvert ! audioresample ! autoaudiosink`.
# URIDecodebin
The uridecodebin element is very similar to decodebin, only that it
automatically plugs a source plugin based on the protocol of the URI
given.
Uridecodebin will also automatically insert buffering elements when the
uri is a slow network source. The buffering element will post BUFFERING
messages that the application needs to handle as explained in
[Buffering](manual-buffering.md). The following properties can be used
to configure the buffering method:
- The buffer-size property allows you to configure a maximum size in
bytes for the buffer element.
- The buffer-duration property allows you to configure a maximum size
in time for the buffer element. The time will be estimated based on
the bitrate of the network.
- With the download property you can enable the download buffering
method as described in [Download
buffering](manual-buffering.md#download-buffering). Setting this
option to TRUE will only enable download buffering for selected
formats such as quicktime, flash video, avi and webm.
- You can also enable buffering on the parsed/demuxed data with the
use-buffering property. This is interesting to enable buffering on
slower random access media such as a network file server.
URIDecodebin can be easily tested on the commandline, e.g. by using the
command `gst-launch-1.0 uridecodebin uri=file:///file.ogg !
! audioconvert ! audioresample ! autoaudiosink`.
# Playsink
The playsink element is a powerful sink element. It has request pads for
raw decoded audio, video and text and it will configure itself to play
the media streams. It has the following features:
- It exposes GstStreamVolume, GstVideoOverlay, GstNavigation and
GstColorBalance interfaces and automatically plugs software elements
to implement the interfaces when needed.
- It will automatically plug conversion elements.
- Can optionally render visualizations when there is no video input.
- Configurable sink elements.
- Configurable audio/video sync offset to fine-tune synchronization in
badly muxed files.
- Support for taking a snapshot of the last video frame.
Below is an example of how you can use playsink. We use a uridecodebin
element to decode into raw audio and video streams which we then link to
the playsink request pads. We only link the first audio and video pads,
you could use an input-selector to link all pads.
```
#include <gst/gst.h>
[.. my_bus_callback goes here ..]
GstElement *pipeline, *sink;
static void
cb_pad_added (GstElement *dec,
GstPad *pad,
gpointer data)
{
GstCaps *caps;
GstStructure *str;
const gchar *name;
GstPadTemplate *templ;
GstElementClass *klass;
/* check media type */
caps = gst_pad_query_caps (pad, NULL);
str = gst_caps_get_structure (caps, 0);
name = gst_structure_get_name (str);
klass = GST_ELEMENT_GET_CLASS (sink);
if (g_str_has_prefix (name, "audio")) {
templ = gst_element_class_get_pad_template (klass, "audio_sink");
} else if (g_str_has_prefix (name, "video")) {
templ = gst_element_class_get_pad_template (klass, "video_sink");
} else if (g_str_has_prefix (name, "text")) {
templ = gst_element_class_get_pad_template (klass, "text_sink");
} else {
templ = NULL;
}
if (templ) {
GstPad *sinkpad;
sinkpad = gst_element_request_pad (sink, templ, NULL, NULL);
if (!gst_pad_is_linked (sinkpad))
gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
}
}
gint
main (gint argc,
gchar *argv[])
{
GMainLoop *loop;
GstElement *dec;
GstBus *bus;
/* init GStreamer */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* make sure we have input */
if (argc != 2) {
g_print ("Usage: %s <uri>\n", argv[0]);
return -1;
}
/* setup */
pipeline = gst_pipeline_new ("pipeline");
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, my_bus_callback, loop);
gst_object_unref (bus);
dec = gst_element_factory_make ("uridecodebin", "source");
g_object_set (G_OBJECT (dec), "uri", argv[1], NULL);
g_signal_connect (dec, "pad-added", G_CALLBACK (cb_pad_added), NULL);
/* create audio output */
sink = gst_element_factory_make ("playsink", "sink");
gst_util_set_object_arg (G_OBJECT (sink), "flags",
"soft-colorbalance+soft-volume+vis+text+audio+video");
gst_bin_add_many (GST_BIN (pipeline), dec, sink, NULL);
/* run */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_main_loop_run (loop);
/* cleanup */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
```
This example will show audio and video depending on what you give it.
Try this example on an audio file and you will see that it shows
visualizations. You can change the visualization at runtime by changing
the vis-plugin property.

126
manual-porting-1.0.md Normal file
View file

@ -0,0 +1,126 @@
---
title: Porting 0.10 applications to 1.0
...
# Porting 0.10 applications to 1.0
This section outlines some of the changes necessary to port applications
from GStreamer-0.10 to GStreamer-1.0. For a comprehensive and up-to-date
list, see the separate [Porting
to 1.0](http://cgit.freedesktop.org/gstreamer/gstreamer/plain/docs/random/porting-to-1.0.txt)
document.
It should be possible to port simple applications to GStreamer-1.0 in
less than a day.
# List of changes
- All deprecated methods were removed. Recompile against 0.10 with
GST\_DISABLE\_DEPRECATED defined (such as by adding
-DGST\_DISABLE\_DEPRECATED to the compiler flags) and fix issues
before attempting to port to 1.0.
- "playbin2" has been renamed to "playbin", with similar API
- "decodebin2" has been renamed to "decodebin", with similar API. Note
that there is no longer a "new-decoded-pad" signal, just use
GstElement's "pad-added" signal instead (but don't forget to remove
the 'gboolean last' argument from your old signal callback functino
signature).
- the names of some "formatted" pad templates has been changed from
e.g. "src%d" to "src%u" or "src\_%u" or similar, since we don't want
to see negative numbers in pad names. This mostly affects
applications that create request pads from elements.
- some elements that used to have a single dynamic source pad have a
source pad now. Example: wavparse, id3demux, iceydemux, apedemux.
(This does not affect applications using decodebin or playbin).
- playbin now proxies the GstVideoOverlay (former GstXOverlay)
interface, so most applications can just remove the sync bus handler
where they would set the window ID, and instead just set the window
ID on playbin from the application thread before starting playback.
playbin also proxies the GstColorBalance and GstNavigation
interfaces, so applications that use this don't need to go fishing
for elements that may implement those any more, but can just use on
playbin unconditionally.
- multifdsink, tcpclientsink, tcpclientsrc, tcpserversrc the protocol
property is removed, use gdppay and gdpdepay.
- XML serialization was removed.
- Probes and pad blocking was merged into new pad probes.
- Position, duration and convert functions no longer use an inout
parameter for the destination format.
- Video and audio caps were simplified. audio/x-raw-int and
audio/x-raw-float are now all under the audio/x-raw media type.
Similarly, video/x-raw-rgb and video/x-raw-yuv are now video/x-raw.
- ffmpegcolorspace was removed and replaced with videoconvert.
- GstMixerInterface / GstTunerInterface were removed without
replacement.
- The GstXOverlay interface was renamed to GstVideoOverlay, and now
part of the video library in gst-plugins-base, as the interfaces
library no longer exists.
The name of the GstXOverlay "prepare-xwindow-id" message has changed
to "prepare-window-handle" (and GstXOverlay has been renamed to
GstVideoOverlay). Code that checks for the string directly should be
changed to use
gst\_is\_video\_overlay\_prepare\_window\_handle\_message(message)
instead.
- The GstPropertyProbe interface was removed. There is no replacement
for it in GStreamer 1.0.x and 1.2.x, but since version 1.4 there is
a more featureful replacement for device discovery and feature
querying provided by GstDeviceMonitor, GstDevice, and friends. See
the ["GStreamer Device Discovery and Device Probing"
documentation](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gstreamer-device-probing.html).
- gst\_uri\_handler\_get\_uri() and the get\_uri vfunc now return a
copy of the URI string
gst\_uri\_handler\_set\_uri() and the set\_uri vfunc now take an
additional GError argument so the handler can notify the caller why
it didn't accept a particular URI.
gst\_uri\_handler\_set\_uri() now checks if the protocol of the URI
passed is one of the protocols advertised by the uri handler, so
set\_uri vfunc implementations no longer need to check that as well.
- GstTagList is now an opaque mini object instead of being typedefed
to a GstStructure. While it was previously okay (and in some cases
required because of missing taglist API) to cast a GstTagList to a
GstStructure or use gst\_structure\_\* API on taglists, you can no
longer do that. Doing so will cause crashes.
Also, tag lists are refcounted now, and can therefore not be freely
modified any longer. Make sure to call
gst\_tag\_list\_make\_writable (taglist) before adding, removing or
changing tags in the taglist.
GST\_TAG\_IMAGE, GST\_TAG\_PREVIEW\_IMAGE, GST\_TAG\_ATTACHMENT:
many tags that used to be of type GstBuffer are now of type
GstSample (which is basically a struct containing a buffer alongside
caps and some other info).
- GstController has now been merged into GstObject. It does not exists
as an individual object anymore. In addition core contains a
GstControlSource base class and the GstControlBinding. The actual
control sources are in the controller library as before. The 2nd big
change is that control sources generate a sequence of gdouble values
and those are mapped to the property type and value range by
GstControlBindings.
The whole gst\_controller\_\* API is gone and now available in
simplified form under gst\_object\_\*. ControlSources are now
attached via GstControlBinding to properties. There are no GValue
arguments used anymore when programming control sources.

91
manual-porting.md Normal file
View file

@ -0,0 +1,91 @@
---
title: Porting 0.8 applications to 0.10
...
# Porting 0.8 applications to 0.10
This section of the appendix will discuss shortly what changes to
applications will be needed to quickly and conveniently port most
applications from GStreamer-0.8 to GStreamer-0.10, with references to
the relevant sections in this Application Development Manual where
needed. With this list, it should be possible to port simple
applications to GStreamer-0.10 in less than a day.
# List of changes
- Most functions returning an object or an object property have been
changed to return its own reference rather than a constant reference
of the one owned by the object itself. The reason for this change is
primarily thread safety. This means, effectively, that return values
of functions such as `gst_element_get_pad ()`, `gst_pad_get_name ()`
and many more like these have to be free'ed or unreferenced after
use. Check the API references of each function to know for sure
whether return values should be free'ed or not. It is important that
all objects derived from GstObject are ref'ed/unref'ed using
gst\_object\_ref() and gst\_object\_unref() respectively (instead of
g\_object\_ref/unref).
- Applications should no longer use signal handlers to be notified of
errors, end-of-stream and other similar pipeline events. Instead,
they should use the `GstBus`, which has been discussed in
[Bus](manual-bus.md). The bus will take care that the messages will
be delivered in the context of a main loop, which is almost
certainly the application's main thread. The big advantage of this
is that applications no longer need to be thread-aware; they don't
need to use `g_idle_add
()` in the signal handler and do the actual real work in the
idle-callback. GStreamer now does all that internally.
- Related to this, `gst_bin_iterate ()` has been removed. Pipelines
will iterate in their own thread, and applications can simply run a
`GMainLoop` (or call the mainloop of their UI toolkit, such as
`gtk_main
()`).
- State changes can be delayed (ASYNC). Due to the new fully threaded
nature of GStreamer-0.10, state changes are not always immediate, in
particular changes including the transition from READY to PAUSED
state. This means two things in the context of porting applications:
first of all, it is no longer always possible to do
`gst_element_set_state ()` and check for a return value of
GST\_STATE\_CHANGE\_SUCCESS, as the state change might be delayed
(ASYNC) and the result will not be known until later. You should
still check for GST\_STATE\_CHANGE\_FAILURE right away, it is just
no longer possible to assume that everything that is not SUCCESS
means failure. Secondly, state changes might not be immediate, so
your code needs to take that into account. You can wait for a state
change to complete if you use GST\_CLOCK\_TIME\_NONE as timeout
interval with `gst_element_get_state ()`.
- In 0.8, events and queries had to manually be sent to sinks in
pipelines (unless you were using playbin). This is no longer the
case in 0.10. In 0.10, queries and events can be sent to toplevel
pipelines, and the pipeline will do the dispatching internally for
you. This means less bookkeeping in your application. For a short
code example, see [Position tracking and
seeking](manual-queryevents.md). Related, seeking is now
threadsafe, and your video output will show the new video position's
frame while seeking, providing a better user experience.
- The `GstThread` object has been removed. Applications can now simply
put elements in a pipeline with optionally some “queue” elements in
between for buffering, and GStreamer will take care of creating
threads internally. It is still possible to have parts of a pipeline
run in different threads than others, by using the “queue” element.
See [Threads](manual-threads.md) for details.
- Filtered caps -\> capsfilter element (the pipeline syntax for
gst-launch has not changed though).
- libgstgconf-0.10.la does not exist. Use the “gconfvideosink” and
“gconfaudiosink” elements instead, which will do live-updates and
require no library linking.
- The “new-pad” and “state-change” signals on `GstElement` were
renamed to “pad-added” and “state-changed”.
- `gst_init_get_popt_table ()` has been removed in favour of the new
GOption command line option API that was added to GLib 2.6.
`gst_init_get_option_group ()` is the new GOption-based equivalent
to `gst_init_get_ptop_table ()`.

335
manual-programs.md Normal file
View file

@ -0,0 +1,335 @@
---
title: Programs
...
# Programs
# `gst-launch`
This is a tool that will construct pipelines based on a command-line
syntax.
A simple commandline looks like:
```
gst-launch filesrc location=hello.mp3 ! mad ! audioresample ! osssink
```
A more complex pipeline looks like:
```
gst-launch filesrc location=redpill.vob ! dvddemux name=demux \
demux.audio_00 ! queue ! a52dec ! audioconvert ! audioresample ! osssink \
demux.video_00 ! queue ! mpeg2dec ! videoconvert ! xvimagesink
```
You can also use the parser in you own code. GStreamer provides a
function gst\_parse\_launch () that you can use to construct a pipeline.
The following program lets you create an MP3 pipeline using the
gst\_parse\_launch () function:
```
#include <gst/gst.h>
int
main (int argc, char *argv[])
{
GstElement *pipeline;
GstElement *filesrc;
GstMessage *msg;
GstBus *bus;
GError *error = NULL;
gst_init (&argc, &argv);
if (argc != 2) {
g_print ("usage: %s <filename>\n", argv[0]);
return -1;
}
pipeline = gst_parse_launch ("filesrc name=my_filesrc ! mad ! osssink", &error);
if (!pipeline) {
g_print ("Parse error: %s\n", error->message);
exit (1);
}
filesrc = gst_bin_get_by_name (GST_BIN (pipeline), "my_filesrc");
g_object_set (filesrc, "location", argv[1], NULL);
g_object_unref (filesrc);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
bus = gst_element_get_bus (pipeline);
/* wait until we either get an EOS or an ERROR message. Note that in a real
* program you would probably not use gst_bus_poll(), but rather set up an
* async signal watch on the bus and run a main loop and connect to the
* bus's signals to catch certain messages or all messages */
msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS: {
g_print ("EOS\n");
break;
}
case GST_MESSAGE_ERROR: {
GError *err = NULL; /* error to show to users */
gchar *dbg = NULL; /* additional debug string for developers */
gst_message_parse_error (msg, &err, &dbg);
if (err) {
g_printerr ("ERROR: %s\n", err->message);
g_error_free (err);
}
if (dbg) {
g_printerr ("[Debug details: %s]\n", dbg);
g_free (dbg);
}
}
default:
g_printerr ("Unexpected message of type %d", GST_MESSAGE_TYPE (msg));
break;
}
gst_message_unref (msg);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
gst_object_unref (bus);
return 0;
}
```
Note how we can retrieve the filesrc element from the constructed bin
using the element name.
## Grammar Reference
The `gst-launch` syntax is processed by a flex/bison parser. This
section is intended to provide a full specification of the grammar; any
deviations from this specification is considered a bug.
### Elements
```
... mad ...
```
A bare identifier (a string beginning with a letter and containing only
letters, numbers, dashes, underscores, percent signs, or colons) will
create an element from a given element factory. In this example, an
instance of the "mad" MP3 decoding plugin will be created.
### Links
```
... !sink ...
```
An exclamation point, optionally having a qualified pad name (an the
name of the pad, optionally preceded by the name of the element) on both
sides, will link two pads. If the source pad is not specified, a source
pad from the immediately preceding element will be automatically chosen.
If the sink pad is not specified, a sink pad from the next element to be
constructed will be chosen. An attempt will be made to find compatible
pads. Pad names may be preceded by an element name, as in
`my_element_name.sink_pad`.
### Properties
```
... location="http://gstreamer.net" ...
```
The name of a property, optionally qualified with an element name, and a
value, separated by an equals sign, will set a property on an element.
If the element is not specified, the previous element is assumed.
Strings can optionally be enclosed in quotation marks. Characters in
strings may be escaped with the backtick (`\`). If the right-hand side
is all digits, it is considered to be an integer. If it is all digits
and a decimal point, it is a double. If it is "true", "false", "TRUE",
or "FALSE" it is considered to be boolean. Otherwise, it is parsed as a
string. The type of the property is determined later on in the parsing,
and the value is converted to the target type. This conversion is not
guaranteed to work, it relies on the g\_value\_convert routines. No
error message will be displayed on an invalid conversion, due to
limitations in the value convert API.
### Bins, Threads, and Pipelines
```
( ... )
```
A pipeline description between parentheses is placed into a bin. The
open paren may be preceded by a type name, as in `jackbin.( ... )` to
make a bin of a specified type. Square brackets make pipelines, and
curly braces make threads. The default toplevel bin type is a pipeline,
although putting the whole description within parentheses or braces can
override this default.
# `gst-inspect`
This is a tool to query a plugin or an element about its properties.
To query the information about the element mad, you would specify:
```
gst-inspect mad
```
Below is the output of a query for the osssink element:
```
Factory Details:
Rank: secondary (128)
Long-name: Audio Sink (OSS)
Klass: Sink/Audio
Description: Output to a sound card via OSS
Author: Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim.taymans@chello.be>
Plugin Details:
Name: ossaudio
Description: OSS (Open Sound System) support for GStreamer
Filename: /home/wim/gst/head/gst-plugins-good/sys/oss/.libs/libgstossaudio.so
Version: 1.0.0.1
License: LGPL
Source module: gst-plugins-good
Source release date: 2012-09-25 12:52 (UTC)
Binary package: GStreamer Good Plug-ins git
Origin URL: Unknown package origin
GObject
+----GInitiallyUnowned
+----GstObject
+----GstElement
+----GstBaseSink
+----GstAudioBaseSink
+----GstAudioSink
+----GstOssSink
Pad Templates:
SINK template: 'sink'
Availability: Always
Capabilities:
audio/x-raw
format: { S16LE, U16LE, S8, U8 }
layout: interleaved
rate: [ 1, 2147483647 ]
channels: 1
audio/x-raw
format: { S16LE, U16LE, S8, U8 }
layout: interleaved
rate: [ 1, 2147483647 ]
channels: 2
channel-mask: 0x0000000000000003
Element Flags:
no flags set
Element Implementation:
Has change_state() function: gst_audio_base_sink_change_state
Clocking Interaction:
element is supposed to provide a clock but returned NULL
Element has no indexing capabilities.
Element has no URI handling capabilities.
Pads:
SINK: 'sink'
Implementation:
Has chainfunc(): gst_base_sink_chain
Has custom eventfunc(): gst_base_sink_event
Has custom queryfunc(): gst_base_sink_sink_query
Has custom iterintlinkfunc(): gst_pad_iterate_internal_links_default
Pad Template: 'sink'
Element Properties:
name : The name of the object
flags: readable, writable
String. Default: "osssink0"
parent : The parent of the object
flags: readable, writable
Object of type "GstObject"
sync : Sync on the clock
flags: readable, writable
Boolean. Default: true
max-lateness : Maximum number of nanoseconds that a buffer can be late before it is dropped (-1 unlimited)
flags: readable, writable
Integer64. Range: -1 - 9223372036854775807 Default: -1
qos : Generate Quality-of-Service events upstream
flags: readable, writable
Boolean. Default: false
async : Go asynchronously to PAUSED
flags: readable, writable
Boolean. Default: true
ts-offset : Timestamp offset in nanoseconds
flags: readable, writable
Integer64. Range: -9223372036854775808 - 9223372036854775807 Default: 0
enable-last-sample : Enable the last-sample property
flags: readable, writable
Boolean. Default: false
last-sample : The last sample received in the sink
flags: readable
Boxed pointer of type "GstSample"
blocksize : Size in bytes to pull per buffer (0 = default)
flags: readable, writable
Unsigned Integer. Range: 0 - 4294967295 Default: 4096
render-delay : Additional render delay of the sink in nanoseconds
flags: readable, writable
Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0
throttle-time : The time to keep between rendered buffers
flags: readable, writable
Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0
buffer-time : Size of audio buffer in microseconds, this is the minimum latency that the sink reports
flags: readable, writable
Integer64. Range: 1 - 9223372036854775807 Default: 200000
latency-time : The minimum amount of data to write in each iteration in microseconds
flags: readable, writable
Integer64. Range: 1 - 9223372036854775807 Default: 10000
provide-clock : Provide a clock to be used as the global pipeline clock
flags: readable, writable
Boolean. Default: true
slave-method : Algorithm to use to match the rate of the masterclock
flags: readable, writable
Enum "GstAudioBaseSinkSlaveMethod" Default: 1, "skew"
(0): resample - GST_AUDIO_BASE_SINK_SLAVE_RESAMPLE
(1): skew - GST_AUDIO_BASE_SINK_SLAVE_SKEW
(2): none - GST_AUDIO_BASE_SINK_SLAVE_NONE
can-activate-pull : Allow pull-based scheduling
flags: readable, writable
Boolean. Default: false
alignment-threshold : Timestamp alignment threshold in nanoseconds
flags: readable, writable
Unsigned Integer64. Range: 1 - 18446744073709551614 Default: 40000000
drift-tolerance : Tolerance for clock drift in microseconds
flags: readable, writable
Integer64. Range: 1 - 9223372036854775807 Default: 40000
discont-wait : Window of time in nanoseconds to wait before creating a discontinuity
flags: readable, writable
Unsigned Integer64. Range: 0 - 18446744073709551614 Default: 1000000000
device : OSS device (usually /dev/dspN)
flags: readable, writable
String. Default: "/dev/dsp"
```
To query the information about a plugin, you would do:
```
gst-inspect gstelements
```

138
manual-queryevents.md Normal file
View file

@ -0,0 +1,138 @@
---
title: Position tracking and seeking
...
# Position tracking and seeking
So far, we've looked at how to create a pipeline to do media processing
and how to make it run. Most application developers will be interested
in providing feedback to the user on media progress. Media players, for
example, will want to show a slider showing the progress in the song,
and usually also a label indicating stream length. Transcoding
applications will want to show a progress bar on how much percent of the
task is done. GStreamer has built-in support for doing all this using a
concept known as *querying*. Since seeking is very similar, it will be
discussed here as well. Seeking is done using the concept of *events*.
# Querying: getting the position or length of a stream
Querying is defined as requesting a specific stream property related to
progress tracking. This includes getting the length of a stream (if
available) or getting the current position. Those stream properties can
be retrieved in various formats such as time, audio samples, video
frames or bytes. The function most commonly used for this is
`gst_element_query ()`, although some convenience wrappers are provided
as well (such as `gst_element_query_position ()` and
`gst_element_query_duration ()`). You can generally query the pipeline
directly, and it'll figure out the internal details for you, like which
element to query.
Internally, queries will be sent to the sinks, and “dispatched”
backwards until one element can handle it; that result will be sent back
to the function caller. Usually, that is the demuxer, although with live
sources (from a webcam), it is the source itself.
```
#include <gst/gst.h>
static gboolean
cb_print_position (GstElement *pipeline)
{
gint64 pos, len;
if (gst_element_query_position (pipeline, GST_FORMAT_TIME, &pos)
&& gst_element_query_duration (pipeline, GST_FORMAT_TIME, &len)) {
g_print ("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
GST_TIME_ARGS (pos), GST_TIME_ARGS (len));
}
/* call me again */
return TRUE;
}
gint
main (gint argc,
gchar *argv[])
{
GstElement *pipeline;
[..]
/* run pipeline */
g_timeout_add (200, (GSourceFunc) cb_print_position, pipeline);
g_main_loop_run (loop);
[..]
}
```
# Events: seeking (and more)
Events work in a very similar way as queries. Dispatching, for example,
works exactly the same for events (and also has the same limitations),
and they can similarly be sent to the toplevel pipeline and it will
figure out everything for you. Although there are more ways in which
applications and elements can interact using events, we will only focus
on seeking here. This is done using the seek-event. A seek-event
contains a playback rate, a seek offset format (which is the unit of the
offsets to follow, e.g. time, audio samples, video frames or bytes),
optionally a set of seeking-related flags (e.g. whether internal buffers
should be flushed), a seek method (which indicates relative to what the
offset was given), and seek offsets. The first offset (cur) is the new
position to seek to, while the second offset (stop) is optional and
specifies a position where streaming is supposed to stop. Usually it is
fine to just specify GST\_SEEK\_TYPE\_NONE and -1 as end\_method and end
offset. The behaviour of a seek is also wrapped in the `gst_element_seek
()`.
```
static void
seek_to_time (GstElement *pipeline,
gint64 time_nanoseconds)
{
if (!gst_element_seek (pipeline, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, time_nanoseconds,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
g_print ("Seek failed!\n");
}
}
```
Seeks with the GST\_SEEK\_FLAG\_FLUSH should be done when the pipeline
is in PAUSED or PLAYING state. The pipeline will automatically go to
preroll state until the new data after the seek will cause the pipeline
to preroll again. After the pipeline is prerolled, it will go back to
the state (PAUSED or PLAYING) it was in when the seek was executed. You
can wait (blocking) for the seek to complete with
`gst_element_get_state()` or by waiting for the ASYNC\_DONE message to
appear on the bus.
Seeks without the GST\_SEEK\_FLAG\_FLUSH should only be done when the
pipeline is in the PLAYING state. Executing a non-flushing seek in the
PAUSED state might deadlock because the pipeline streaming threads might
be blocked in the sinks.
It is important to realise that seeks will not happen instantly in the
sense that they are finished when the function `gst_element_seek ()`
returns. Depending on the specific elements involved, the actual seeking
might be done later in another thread (the streaming thread), and it
might take a short time until buffers from the new seek position will
reach downstream elements such as sinks (if the seek was non-flushing
then it might take a bit longer).
It is possible to do multiple seeks in short time-intervals, such as a
direct response to slider movement. After a seek, internally, the
pipeline will be paused (if it was playing), the position will be re-set
internally, the demuxers and decoders will decode from the new position
onwards and this will continue until all sinks have data again. If it
was playing originally, it will be set to playing again, too. Since the
new position is immediately available in a video output, you will see
the new frame, even if your pipeline is not in the playing state.

201
manual-quotes.md Normal file
View file

@ -0,0 +1,201 @@
---
title: Quotes from the Developers
...
# Quotes from the Developers
As well as being a cool piece of software, GStreamer is a lively
project, with developers from around the globe very actively
contributing. We often hang out on the \#gstreamer IRC channel on
irc.freenode.net: the following are a selection of amusing\[1\] quotes
from our conversations.
- 6 Mar 2006
When I opened my eyes I was in a court room. There were masters
McIlroy and Thompson sitting in the jury and master Kernighan too.
There were the GStreamer developers standing in the defendant's
place, accused of violating several laws of Unix philosophy and
customer lock-down via running on a proprietary pipeline, different
from that of the Unix systems. I heard Eric Raymond whispering "got
to add this case to my book.
*behdad's blog*
- 22 May 2007
*\<\_\_tim\>* Uraeus: amusing, isn't it?
*\<Uraeus\>* \_\_tim: I wrote that :)
*\<\_\_tim\>* Uraeus: of course you did; your refusal to surrender
to the oppressive regime of the third-person-singular-rule is so
unique in its persistence that it's hard to miss :)
- 12 Sep 2005
*\<wingo\>* we just need to get rid of that mmap stuff
*\<wingo\>* i think gnomevfssrc is faster for files even
*\<BBB\>* wingo, no
*\<BBB\>* and no
*\<wingo\>* good points ronald
- 23 Jun 2005
*\* wingo* back
*\* thomasvs* back
\--- You are now known as everybody
*\* everybody* back back
*\<everybody\>* now break it down
\--- You are now known as thomasvs
*\* bilboed* back
\--- bilboed is now known as john-sebastian
*\* john-sebastian* bach
\--- john-sebastian is now known as bilboed
\--- You are now known as scratch\_my
*\* scratch\_my* back
\--- bilboed is now known as Illbe
\--- You are now known as thomasvs
*\* Illbe* back
\--- Illbe is now known as bilboed
- 20 Apr 2005
*thomas*: jrb, somehow his screenshotsrc grabs whatever X is showing
and makes it available as a stream of frames
*jrb*: thomas: so, is the point that the screenshooter takes a
video? but won't the dialog be in the video? oh, nevermind. I'll
just send mail...
*thomas*: jrb, well, it would shoot first and ask questions later
- 2 Nov 2004
*zaheerm*: wtay: unfair u fixed the bug i was using as a feature\!
- 14 Oct 2004
*\* zaheerm* wonders how he can break gstreamer today :)
*ensonic*: zaheerm, spider is always a good starting point
- 14 Jun 2004
*teuf*: ok, things work much better when I don't write incredibly
stupid and buggy code
*thaytan*: I find that too
- 23 Nov 2003
*Uraeus*: ah yes, the sleeping part, my mind is not multitasking so
I was still thinking about exercise
*dolphy*: Uraeus: your mind is multitasking
*dolphy*: Uraeus: you just miss low latency patches
- 14 Sep 2002
\--- *wingo-party* is now known as *wingo*
\* *wingo* holds head
- 4 Jun 2001
*taaz:* you witchdoctors and your voodoo mpeg2 black magic...
*omega\_:* um. I count three, no four different cults there \<g\>
*ajmitch:* hehe
*omega\_:* witchdoctors, voodoo, black magic,
*omega\_:* and mpeg
- 16 Feb 2001
*wtay:* I shipped a few commerical products to \>40000 people now
but GStreamer is way more exciting...
- 16 Feb 2001
\* *tool-man* is a gstreamer groupie
- 14 Jan 2001
*Omega:* did you run ldconfig? maybe it talks to init?
*wtay:* not sure, don't think so... I did run gstreamer-register
though :-)
*Omega:* ah, that did it then ;-)
*wtay:* right
*Omega:* probably not, but in case GStreamer starts turning into an
OS, someone please let me know?
- 9 Jan 2001
*wtay:* me tar, you rpm?
*wtay:* hehe, forgot "zan"
*Omega:* ?
*wtay:* me tar"zan", you ...
- 7 Jan 2001
*Omega:* that means probably building an agreggating,
cache-massaging queue to shove N buffers across all at once, forcing
cache transfer.
*wtay:* never done that before...
*Omega:* nope, but it's easy to do in gstreamer \<g\>
*wtay:* sure, I need to rewrite cp with gstreamer too, someday :-)
- 7 Jan 2001
*wtay:* GStreamer; always at least one developer is awake...
- 5/6 Jan 2001
*wtay:* we need to cut down the time to create an mp3 player down to
seconds...
*richardb:* :)
*Omega:* I'm wanting to something more interesting soon, I did the
"draw an mp3 player in 15sec" back in October '99.
*wtay:* by the time Omega gets his hands on the editor, you'll see a
complete audio mixer in the editor :-)
*richardb:* Well, it clearly has the potential...
*Omega:* Working on it... ;-)
- 28 Dec 2000
*MPAA:* We will sue you now, you have violated our IP rights\!
*wtay:* hehehe
*MPAA:* How dare you laugh at us? We have lawyers\! We have
Congressmen\! We have *LARS*\!
*wtay:* I'm so sorry your honor
*MPAA:* Hrumph.
\* *wtay* bows before thy
<!-- end list -->
1. No guarantee of sense of humour compatibility is given.

387
manual-threads.md Normal file
View file

@ -0,0 +1,387 @@
---
title: Threads
...
# Threads
GStreamer is inherently multi-threaded, and is fully thread-safe. Most
threading internals are hidden from the application, which should make
application development easier. However, in some cases, applications may
want to have influence on some parts of those. GStreamer allows
applications to force the use of multiple threads over some parts of a
pipeline. See [When would you want to force a
thread?](#when-would-you-want-to-force-a-thread).
GStreamer can also notify you when threads are created so that you can
configure things such as the thread priority or the threadpool to use.
See [Configuring Threads in
GStreamer](#configuring-threads-in-gstreamer).
# Scheduling in GStreamer
Each element in the GStreamer pipeline decides how it is going to be
scheduled. Elements can choose if their pads are to be scheduled
push-based or pull-based. An element can, for example, choose to start a
thread to start pulling from the sink pad or/and start pushing on the
source pad. An element can also choose to use the upstream or downstream
thread for its data processing in push and pull mode respectively.
GStreamer does not pose any restrictions on how the element chooses to
be scheduled. See the Plugin Writer Guide for more details.
What will happen in any case is that some elements will start a thread
for their data processing, called the “streaming threads”. The streaming
threads, or `GstTask` objects, are created from a `GstTaskPool` when the
element needs to make a streaming thread. In the next section we see how
we can receive notifications of the tasks and pools.
# Configuring Threads in GStreamer
A STREAM\_STATUS message is posted on the bus to inform you about the
status of the streaming threads. You will get the following information
from the message:
- When a new thread is about to be created, you will be notified of
this with a GST\_STREAM\_STATUS\_TYPE\_CREATE type. It is then
possible to configure a `GstTaskPool` in the `GstTask`. The custom
taskpool will provide custom threads for the task to implement the
streaming threads.
This message needs to be handled synchronously if you want to
configure a custom taskpool. If you don't configure the taskpool on
the task when this message returns, the task will use its default
pool.
- When a thread is entered or left. This is the moment where you could
configure thread priorities. You also get a notification when a
thread is destroyed.
- You get messages when the thread starts, pauses and stops. This
could be used to visualize the status of streaming threads in a gui
application.
We will now look at some examples in the next sections.
## Boost priority of a thread
```
.----------. .----------.
| faksesrc | | fakesink |
| src->sink |
'----------' '----------'
```
Let's look at the simple pipeline above. We would like to boost the
priority of the streaming thread. It will be the fakesrc element that
starts the streaming thread for generating the fake data pushing them to
the peer fakesink. The flow for changing the priority would go like
this:
- When going from READY to PAUSED state, fakesrc will require a
streaming thread for pushing data into the fakesink. It will post a
STREAM\_STATUS message indicating its requirement for a streaming
thread.
- The application will react to the STREAM\_STATUS messages with a
sync bus handler. It will then configure a custom `GstTaskPool` on
the `GstTask` inside the message. The custom taskpool is responsible
for creating the threads. In this example we will make a thread with
a higher priority.
- Alternatively, since the sync message is called in the thread
context, you can use thread ENTER/LEAVE notifications to change the
priority or scheduling pollicy of the current thread.
In a first step we need to implement a custom `GstTaskPool` that we can
configure on the task. Below is the implementation of a `GstTaskPool`
subclass that uses pthreads to create a SCHED\_RR real-time thread. Note
that creating real-time threads might require extra priveleges.
```
#include <pthread.h>
typedef struct
{
pthread_t thread;
} TestRTId;
G_DEFINE_TYPE (TestRTPool, test_rt_pool, GST_TYPE_TASK_POOL);
static void
default_prepare (GstTaskPool * pool, GError ** error)
{
/* we don't do anything here. We could construct a pool of threads here that
* we could reuse later but we don't */
}
static void
default_cleanup (GstTaskPool * pool)
{
}
static gpointer
default_push (GstTaskPool * pool, GstTaskPoolFunction func, gpointer data,
GError ** error)
{
TestRTId *tid;
gint res;
pthread_attr_t attr;
struct sched_param param;
tid = g_slice_new0 (TestRTId);
pthread_attr_init (&attr);
if ((res = pthread_attr_setschedpolicy (&attr, SCHED_RR)) != 0)
g_warning ("setschedpolicy: failure: %p", g_strerror (res));
param.sched_priority = 50;
if ((res = pthread_attr_setschedparam (&attr, &param)) != 0)
g_warning ("setschedparam: failure: %p", g_strerror (res));
if ((res = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED)) != 0)
g_warning ("setinheritsched: failure: %p", g_strerror (res));
res = pthread_create (&tid->thread, &attr, (void *(*)(void *)) func, data);
if (res != 0) {
g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN,
"Error creating thread: %s", g_strerror (res));
g_slice_free (TestRTId, tid);
tid = NULL;
}
return tid;
}
static void
default_join (GstTaskPool * pool, gpointer id)
{
TestRTId *tid = (TestRTId *) id;
pthread_join (tid->thread, NULL);
g_slice_free (TestRTId, tid);
}
static void
test_rt_pool_class_init (TestRTPoolClass * klass)
{
GstTaskPoolClass *gsttaskpool_class;
gsttaskpool_class = (GstTaskPoolClass *) klass;
gsttaskpool_class->prepare = default_prepare;
gsttaskpool_class->cleanup = default_cleanup;
gsttaskpool_class->push = default_push;
gsttaskpool_class->join = default_join;
}
static void
test_rt_pool_init (TestRTPool * pool)
{
}
GstTaskPool *
test_rt_pool_new (void)
{
GstTaskPool *pool;
pool = g_object_new (TEST_TYPE_RT_POOL, NULL);
return pool;
}
```
The important function to implement when writing an taskpool is the
“push” function. The implementation should start a thread that calls
the given function. More involved implementations might want to keep
some threads around in a pool because creating and destroying threads is
not always the fastest operation.
In a next step we need to actually configure the custom taskpool when
the fakesrc needs it. For this we intercept the STREAM\_STATUS messages
with a sync handler.
```
static GMainLoop* loop;
static void
on_stream_status (GstBus *bus,
GstMessage *message,
gpointer user_data)
{
GstStreamStatusType type;
GstElement *owner;
const GValue *val;
GstTask *task = NULL;
gst_message_parse_stream_status (message, &type, &owner);
val = gst_message_get_stream_status_object (message);
/* see if we know how to deal with this object */
if (G_VALUE_TYPE (val) == GST_TYPE_TASK) {
task = g_value_get_object (val);
}
switch (type) {
case GST_STREAM_STATUS_TYPE_CREATE:
if (task) {
GstTaskPool *pool;
pool = test_rt_pool_new();
gst_task_set_pool (task, pool);
}
break;
default:
break;
}
}
static void
on_error (GstBus *bus,
GstMessage *message,
gpointer user_data)
{
g_message ("received ERROR");
g_main_loop_quit (loop);
}
static void
on_eos (GstBus *bus,
GstMessage *message,
gpointer user_data)
{
g_main_loop_quit (loop);
}
int
main (int argc, char *argv[])
{
GstElement *bin, *fakesrc, *fakesink;
GstBus *bus;
GstStateChangeReturn ret;
gst_init (&argc, &argv);
/* create a new bin to hold the elements */
bin = gst_pipeline_new ("pipeline");
g_assert (bin);
/* create a source */
fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
g_assert (fakesrc);
g_object_set (fakesrc, "num-buffers", 50, NULL);
/* and a sink */
fakesink = gst_element_factory_make ("fakesink", "fakesink");
g_assert (fakesink);
/* add objects to the main pipeline */
gst_bin_add_many (GST_BIN (bin), fakesrc, fakesink, NULL);
/* link the elements */
gst_element_link (fakesrc, fakesink);
loop = g_main_loop_new (NULL, FALSE);
/* get the bus, we need to install a sync handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (bin));
gst_bus_enable_sync_message_emission (bus);
gst_bus_add_signal_watch (bus);
g_signal_connect (bus, "sync-message::stream-status",
(GCallback) on_stream_status, NULL);
g_signal_connect (bus, "message::error",
(GCallback) on_error, NULL);
g_signal_connect (bus, "message::eos",
(GCallback) on_eos, NULL);
/* start playing */
ret = gst_element_set_state (bin, GST_STATE_PLAYING);
if (ret != GST_STATE_CHANGE_SUCCESS) {
g_message ("failed to change state");
return -1;
}
/* Run event loop listening for bus messages until EOS or ERROR */
g_main_loop_run (loop);
/* stop the bin */
gst_element_set_state (bin, GST_STATE_NULL);
gst_object_unref (bus);
g_main_loop_unref (loop);
return 0;
}
```
Note that this program likely needs root permissions in order to create
real-time threads. When the thread can't be created, the state change
function will fail, which we catch in the application above.
When there are multiple threads in the pipeline, you will receive
multiple STREAM\_STATUS messages. You should use the owner of the
message, which is likely the pad or the element that starts the thread,
to figure out what the function of this thread is in the context of the
application.
# When would you want to force a thread?
We have seen that threads are created by elements but it is also
possible to insert elements in the pipeline for the sole purpose of
forcing a new thread in the pipeline.
There are several reasons to force the use of threads. However, for
performance reasons, you never want to use one thread for every element
out there, since that will create some overhead. Let's now list some
situations where threads can be particularly useful:
- Data buffering, for example when dealing with network streams or
when recording data from a live stream such as a video or audio
card. Short hickups elsewhere in the pipeline will not cause data
loss. See also [Stream
buffering](manual-buffering.md#stream-buffering) about network
buffering with queue2.
![Data buffering, from a networked
source](images/thread-buffering.png "fig:")
- Synchronizing output devices, e.g. when playing a stream containing
both video and audio data. By using threads for both outputs, they
will run independently and their synchronization will be better.
![Synchronizing audio and video
sinks](images/thread-synchronizing.png "fig:")
Above, we've mentioned the “queue” element several times now. A queue is
the thread boundary element through which you can force the use of
threads. It does so by using a classic provider/consumer model as
learned in threading classes at universities all around the world. By
doing this, it acts both as a means to make data throughput between
threads threadsafe, and it can also act as a buffer. Queues have several
`GObject` properties to be configured for specific uses. For example,
you can set lower and upper thresholds for the element. If there's less
data than the lower threshold (default: disabled), it will block output.
If there's more data than the upper threshold, it will block input or
(if configured to do so) drop data.
To use a queue (and therefore force the use of two distinct threads in
the pipeline), one can simply create a “queue” element and put this in
as part of the pipeline. GStreamer will take care of all threading
details internally.

View file

@ -53,6 +53,40 @@ Home.markdown
GStreamer+reference.markdown
gst-inspect.markdown
gst-launch.markdown
manual-index.md
manual-introduction.md
manual-gstreamer.md
manual-motivation.md
manual-intro-basics.md
manual-building.md
manual-init.md
manual-elements.md
manual-bins.md
manual-bus.md
manual-pads.md
manual-data.md
manual-helloworld.md
manual-advanced.md
manual-queryevents.md
manual-metadata.md
manual-interfaces.md
manual-clocks.md
manual-buffering.md
manual-dparams.md
manual-threads.md
manual-autoplugging.md
manual-dataaccess.md
manual-highlevel.md
manual-playback-components.md
manual-appendices.md
manual-programs.md
manual-compiling.md
manual-checklist-element.md
manual-porting.md
manual-porting-1.0.md
manual-intgration.md
manual-licensing.md
manual-quotes.md
pwg-index.md
pwg-introduction.md
pwg-intro-preface.md