gstreamer/subprojects/gst-docs/markdown/tutorials/playback/custom-playbin-sinks.md

227 lines
8.3 KiB
Markdown
Raw Normal View History

2016-05-27 18:19:02 +00:00
# Playback tutorial 7: Custom playbin sinks
2016-05-16 14:30:34 +00:00
{{ ALERT_PY.md }}
{{ ALERT_JS.md }}
2016-06-16 01:26:59 +00:00
## Goal
2016-05-16 14:30:34 +00:00
2016-06-16 01:26:59 +00:00
`playbin` can be further customized by manually selecting its audio and
video sinks. This allows applications to rely on `playbin` to retrieve
2016-05-16 14:30:34 +00:00
and decode the media and then manage the final render/display
themselves. This tutorial shows:
2016-05-27 18:19:02 +00:00
- How to replace the sinks selected by `playbin`.
2016-05-16 14:30:34 +00:00
- How to use a complex pipeline as a sink.
2016-06-16 01:26:59 +00:00
## Introduction
2016-05-16 14:30:34 +00:00
2016-06-16 01:26:59 +00:00
Two properties of `playbin` allow selecting the desired audio and video
sinks: `audio-sink` and `video-sink` (respectively). The application
only needs to instantiate the appropriate `GstElement` and pass it to
`playbin` through these properties.
2016-05-16 14:30:34 +00:00
This method, though, only allows using a single Element as sink. If a
more complex pipeline is required, for example, an equalizer plus an
audio sink, it needs to be wrapped in a Bin, so it looks to
2016-06-16 01:26:59 +00:00
`playbin` as if it was a single Element.
2016-05-16 14:30:34 +00:00
A Bin (`GstBin`) is a container that encapsulates partial pipelines so
they can be managed as single elements. As an example, the
2016-06-16 01:26:59 +00:00
`GstPipeline` we have been using in all tutorials is a type of
2016-05-16 14:30:34 +00:00
`GstBin`, which does not interact with external Elements. Elements
inside a Bin connect to external elements through Ghost Pads
(`GstGhostPad`), this is, Pads on the surface of the Bin which simply
forward data from an external Pad to a given Pad on an internal Element.
2016-06-16 01:26:59 +00:00
![](images/bin-element-ghost.png)
2016-05-16 14:30:34 +00:00
**Figure 1:** A Bin with two Elements and one Ghost Pad.
2016-06-16 01:26:59 +00:00
`GstBin`s are also a type of `GstElement`, so they can be used wherever
an Element is required, in particular, as sinks for `playbin` (and they
2016-05-16 14:30:34 +00:00
are then known as **sink-bins**).
2016-06-16 01:26:59 +00:00
## An equalized player
2016-05-16 14:30:34 +00:00
2016-06-16 01:26:59 +00:00
Copy this code into a text file named `playback-tutorial-7.c`.
2016-05-16 14:30:34 +00:00
**playback-tutorial7.c**
2016-06-06 00:58:09 +00:00
``` c
2016-05-16 14:30:34 +00:00
#include <gst/gst.h>
2016-05-16 14:30:34 +00:00
int main(int argc, char *argv[]) {
GstElement *pipeline, *bin, *equalizer, *convert, *sink;
GstPad *pad, *ghost_pad;
GstBus *bus;
GstMessage *msg;
2016-05-16 14:30:34 +00:00
/* Initialize GStreamer */
gst_init (&argc, &argv);
2016-05-16 14:30:34 +00:00
/* Build the pipeline */
pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
2016-05-16 14:30:34 +00:00
/* Create the elements inside the sink bin */
equalizer = gst_element_factory_make ("equalizer-3bands", "equalizer");
convert = gst_element_factory_make ("audioconvert", "convert");
sink = gst_element_factory_make ("autoaudiosink", "audio_sink");
if (!equalizer || !convert || !sink) {
g_printerr ("Not all elements could be created.\n");
return -1;
}
2016-05-16 14:30:34 +00:00
/* Create the sink bin, add the elements and link them */
bin = gst_bin_new ("audio_sink_bin");
gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL);
gst_element_link_many (equalizer, convert, sink, NULL);
pad = gst_element_get_static_pad (equalizer, "sink");
ghost_pad = gst_ghost_pad_new ("sink", pad);
gst_pad_set_active (ghost_pad, TRUE);
gst_element_add_pad (bin, ghost_pad);
gst_object_unref (pad);
2016-05-16 14:30:34 +00:00
/* Configure the equalizer */
g_object_set (G_OBJECT (equalizer), "band1", (gdouble)-24.0, NULL);
g_object_set (G_OBJECT (equalizer), "band2", (gdouble)-24.0, NULL);
2016-05-27 18:19:02 +00:00
/* Set playbin's audio sink to be our sink bin */
2016-05-16 14:30:34 +00:00
g_object_set (GST_OBJECT (pipeline), "audio-sink", bin, NULL);
2016-05-16 14:30:34 +00:00
/* Start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
2016-05-16 14:30:34 +00:00
/* Wait until error or EOS */
bus = gst_element_get_bus (pipeline);
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
2016-05-16 14:30:34 +00:00
/* Free resources */
if (msg != NULL)
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
return 0;
}
```
2016-06-16 01:26:59 +00:00
> ![information] If you need help to compile this code, refer to the
> **Building the tutorials** section for your platform: [Mac] or
> [Windows] or use this specific command on Linux:
>
> `` gcc playback-tutorial-7.c -o playback-tutorial-7 `pkg-config --cflags --libs gstreamer-1.0` ``
>
> If you need help to run this code, refer to the **Running the
> tutorials** section for your platform: [Mac OS X], [Windows][1], for
> [iOS] or for [android].
>
> This tutorial opens a window and displays a movie, with accompanying audio. The media is fetched from the Internet, so the window might take a few seconds to appear, depending on your connection speed. The higher frequency bands have been attenuated, so the movie sound should have a more powerful bass component.<
>
> Required libraries: `gstreamer-1.0`
## Walkthrough
2016-05-16 14:30:34 +00:00
2016-06-06 00:58:09 +00:00
``` c
2016-05-16 14:30:34 +00:00
/* Create the elements inside the sink bin */
equalizer = gst_element_factory_make ("equalizer-3bands", "equalizer");
convert = gst_element_factory_make ("audioconvert", "convert");
sink = gst_element_factory_make ("autoaudiosink", "audio_sink");
if (!equalizer || !convert || !sink) {
g_printerr ("Not all elements could be created.\n");
return -1;
}
```
All the Elements that compose our sink-bin are instantiated. We use an
2016-06-16 01:26:59 +00:00
`equalizer-3bands` and an `autoaudiosink`, with an `audioconvert` in
2016-05-16 14:30:34 +00:00
between, because we are not sure of the capabilities of the audio sink
(since they are hardware-dependant).
2016-06-06 00:58:09 +00:00
``` c
2016-05-16 14:30:34 +00:00
/* Create the sink bin, add the elements and link them */
bin = gst_bin_new ("audio_sink_bin");
gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL);
gst_element_link_many (equalizer, convert, sink, NULL);
```
This adds the new Elements to the Bin and links them just as we would do
if this was a pipeline.
2016-06-06 00:58:09 +00:00
``` c
2016-05-16 14:30:34 +00:00
pad = gst_element_get_static_pad (equalizer, "sink");
ghost_pad = gst_ghost_pad_new ("sink", pad);
gst_pad_set_active (ghost_pad, TRUE);
gst_element_add_pad (bin, ghost_pad);
gst_object_unref (pad);
```
Now we need to create a Ghost Pad so this partial pipeline inside the
Bin can be connected to the outside. This Ghost Pad will be connected to
a Pad in one of the internal Elements (the sink pad of the equalizer),
so we retrieve this Pad with `gst_element_get_static_pad()`. Remember
from [](tutorials/basic/multithreading-and-pad-availability.md) that
2016-05-16 14:30:34 +00:00
if this was a Request Pad instead of an Always Pad, we would need to use
`gst_element_request_pad()`.
2016-06-16 01:26:59 +00:00
The Ghost Pad is created with `gst_ghost_pad_new()` (pointing to the
2016-05-16 14:30:34 +00:00
inner Pad we just acquired), and activated with `gst_pad_set_active()`.
2016-06-16 01:26:59 +00:00
It is then added to the Bin with `gst_element_add_pad()`, transferring
2016-05-16 14:30:34 +00:00
ownership of the Ghost Pad to the bin, so we do not have to worry about
releasing it.
Finally, the sink Pad we obtained from the equalizer needs to be release
with `gst_object_unref()`.
At this point, we have a functional sink-bin, which we can use as the
2016-06-16 01:26:59 +00:00
audio sink in `playbin`. We just need to instruct `playbin` to use it:
2016-05-16 14:30:34 +00:00
2016-06-06 00:58:09 +00:00
``` c
2016-05-27 18:19:02 +00:00
/* Set playbin's audio sink to be our sink bin */
2016-05-16 14:30:34 +00:00
g_object_set (GST_OBJECT (pipeline), "audio-sink", bin, NULL);
```
2016-06-16 01:26:59 +00:00
It is as simple as setting the `audio-sink` property on `playbin` to
2016-05-16 14:30:34 +00:00
the newly created sink.
2016-06-06 00:58:09 +00:00
``` c
2016-05-16 14:30:34 +00:00
/* Configure the equalizer */
g_object_set (G_OBJECT (equalizer), "band1", (gdouble)-24.0, NULL);
g_object_set (G_OBJECT (equalizer), "band2", (gdouble)-24.0, NULL);
```
The only bit remaining is to configure the equalizer. For this example,
the two higher frequency bands are set to the maximum attenuation so the
bass is boosted. Play a bit with the values to feel the difference (Look
2016-06-16 01:26:59 +00:00
at the documentation for the `equalizer-3bands` element for the allowed
2016-05-16 14:30:34 +00:00
range of values).
2016-06-16 01:26:59 +00:00
## Exercise
2016-05-16 14:30:34 +00:00
Build a video bin instead of an audio bin, using one of the many
interesting video filters GStreamer offers, like `solarize`,
2016-06-16 01:26:59 +00:00
`vertigotv` or any of the Elements in the `effectv` plugin. Remember to
use the color space conversion element `videoconvert` if your
2016-05-16 14:30:34 +00:00
pipeline fails to link due to incompatible caps.
2016-06-16 01:26:59 +00:00
## Conclusion
2016-05-16 14:30:34 +00:00
This tutorial has shown:
2016-06-16 01:26:59 +00:00
- How to set your own sinks to `playbin` using the audio-sink and
2016-05-16 14:30:34 +00:00
video-sink properties.
2016-06-16 01:26:59 +00:00
- How to wrap a piece of pipeline into a `GstBin` so it can be used as
a **sink-bin** by `playbin`.
2016-05-16 14:30:34 +00:00
It has been a pleasure having you here, and see you soon\!
[information]: images/icons/emoticons/information.svg
[Mac]: installing/on-mac-osx.md
[Windows]: installing/on-windows.md
[Mac OS X]: installing/on-mac-osx.md#building-the-tutorials
[1]: installing/on-windows.md#running-the-tutorials
[iOS]: installing/for-ios-development.md#building-the-tutorials
[android]: installing/for-android-development.md#building-the-tutorials
[warning]: images/icons/emoticons/warning.svg