Implement our own theme, yay!
[platform/upstream/gstreamer.git] / sdk-playback-tutorial-custom-playbin-sinks.md
1 # Playback tutorial 7: Custom playbin sinks
2
3 ## Goal
4
5 `playbin` can be further customized by manually selecting its audio and
6 video sinks. This allows applications to rely on `playbin` to retrieve
7 and decode the media and then manage the final render/display
8 themselves. This tutorial shows:
9
10   - How to replace the sinks selected by `playbin`.
11   - How to use a complex pipeline as a sink.
12
13 ## Introduction
14
15 Two properties of `playbin` allow selecting the desired audio and video
16 sinks: `audio-sink` and `video-sink` (respectively). The application
17 only needs to instantiate the appropriate `GstElement` and pass it to
18 `playbin` through these properties.
19
20 This method, though, only allows using a single Element as sink. If a
21 more complex pipeline is required, for example, an equalizer plus an
22 audio sink, it needs to be wrapped in a Bin, so it looks to
23 `playbin` as if it was a single Element.
24
25 A Bin (`GstBin`) is a container that encapsulates partial pipelines so
26 they can be managed as single elements. As an example, the
27 `GstPipeline` we have been using in all tutorials is a type of
28 `GstBin`, which does not interact with external Elements. Elements
29 inside a Bin connect to external elements through Ghost Pads
30 (`GstGhostPad`), this is, Pads on the surface of the Bin which simply
31 forward data from an external Pad to a given Pad on an internal Element.
32
33 ![](images/bin-element-ghost.png)
34
35 **Figure 1:** A Bin with two Elements and one Ghost Pad.
36
37 `GstBin`s are also a type of `GstElement`, so they can be used wherever
38 an Element is required, in particular, as sinks for `playbin` (and they
39 are then known as **sink-bins**).
40
41 ## An equalized player
42
43 Copy this code into a text file named `playback-tutorial-7.c`.
44
45 **playback-tutorial7.c**
46
47 ``` c
48 #include <gst/gst.h>
49
50 int main(int argc, char *argv[]) {
51   GstElement *pipeline, *bin, *equalizer, *convert, *sink;
52   GstPad *pad, *ghost_pad;
53   GstBus *bus;
54   GstMessage *msg;
55
56   /* Initialize GStreamer */
57   gst_init (&argc, &argv);
58
59   /* Build the pipeline */
60   pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
61
62   /* Create the elements inside the sink bin */
63   equalizer = gst_element_factory_make ("equalizer-3bands", "equalizer");
64   convert = gst_element_factory_make ("audioconvert", "convert");
65   sink = gst_element_factory_make ("autoaudiosink", "audio_sink");
66   if (!equalizer || !convert || !sink) {
67     g_printerr ("Not all elements could be created.\n");
68     return -1;
69   }
70
71   /* Create the sink bin, add the elements and link them */
72   bin = gst_bin_new ("audio_sink_bin");
73   gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL);
74   gst_element_link_many (equalizer, convert, sink, NULL);
75   pad = gst_element_get_static_pad (equalizer, "sink");
76   ghost_pad = gst_ghost_pad_new ("sink", pad);
77   gst_pad_set_active (ghost_pad, TRUE);
78   gst_element_add_pad (bin, ghost_pad);
79   gst_object_unref (pad);
80
81   /* Configure the equalizer */
82   g_object_set (G_OBJECT (equalizer), "band1", (gdouble)-24.0, NULL);
83   g_object_set (G_OBJECT (equalizer), "band2", (gdouble)-24.0, NULL);
84
85   /* Set playbin's audio sink to be our sink bin */
86   g_object_set (GST_OBJECT (pipeline), "audio-sink", bin, NULL);
87
88   /* Start playing */
89   gst_element_set_state (pipeline, GST_STATE_PLAYING);
90
91   /* Wait until error or EOS */
92   bus = gst_element_get_bus (pipeline);
93   msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
94
95   /* Free resources */
96   if (msg != NULL)
97     gst_message_unref (msg);
98   gst_object_unref (bus);
99   gst_element_set_state (pipeline, GST_STATE_NULL);
100   gst_object_unref (pipeline);
101   return 0;
102 }
103 ```
104
105 > ![information] If you need help to compile this code, refer to the
106 > **Building the tutorials** section for your platform: [Mac] or
107 > [Windows] or use this specific command on Linux:
108 >
109 > `` gcc playback-tutorial-7.c -o playback-tutorial-7 `pkg-config --cflags --libs gstreamer-1.0` ``
110 >
111 > If you need help to run this code, refer to the **Running the
112 > tutorials** section for your platform: [Mac OS X], [Windows][1], for
113 > [iOS] or for [android].
114 >
115 > 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.<
116 >
117 > Required libraries: `gstreamer-1.0`
118
119 ## Walkthrough
120
121 ``` c
122 /* Create the elements inside the sink bin */
123 equalizer = gst_element_factory_make ("equalizer-3bands", "equalizer");
124 convert = gst_element_factory_make ("audioconvert", "convert");
125 sink = gst_element_factory_make ("autoaudiosink", "audio_sink");
126 if (!equalizer || !convert || !sink) {
127   g_printerr ("Not all elements could be created.\n");
128   return -1;
129 }
130 ```
131
132 All the Elements that compose our sink-bin are instantiated. We use an
133 `equalizer-3bands` and an `autoaudiosink`, with an `audioconvert` in
134 between, because we are not sure of the capabilities of the audio sink
135 (since they are hardware-dependant).
136
137 ``` c
138 /* Create the sink bin, add the elements and link them */
139 bin = gst_bin_new ("audio_sink_bin");
140 gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL);
141 gst_element_link_many (equalizer, convert, sink, NULL);
142 ```
143
144 This adds the new Elements to the Bin and links them just as we would do
145 if this was a pipeline.
146
147 ``` c
148 pad = gst_element_get_static_pad (equalizer, "sink");
149 ghost_pad = gst_ghost_pad_new ("sink", pad);
150 gst_pad_set_active (ghost_pad, TRUE);
151 gst_element_add_pad (bin, ghost_pad);
152 gst_object_unref (pad);
153 ```
154
155 Now we need to create a Ghost Pad so this partial pipeline inside the
156 Bin can be connected to the outside. This Ghost Pad will be connected to
157 a Pad in one of the internal Elements (the sink pad of the equalizer),
158 so we retrieve this Pad with `gst_element_get_static_pad()`. Remember
159 from [](sdk-basic-tutorial-multithreading-and-pad-availability.md) that
160 if this was a Request Pad instead of an Always Pad, we would need to use
161 `gst_element_request_pad()`.
162
163 The Ghost Pad is created with `gst_ghost_pad_new()` (pointing to the
164 inner Pad we just acquired), and activated with `gst_pad_set_active()`.
165 It is then added to the Bin with `gst_element_add_pad()`, transferring
166 ownership of the Ghost Pad to the bin, so we do not have to worry about
167 releasing it.
168
169 Finally, the sink Pad we obtained from the equalizer needs to be release
170 with `gst_object_unref()`.
171
172 At this point, we have a functional sink-bin, which we can use as the
173 audio sink in `playbin`. We just need to instruct `playbin` to use it:
174
175 ``` c
176 /* Set playbin's audio sink to be our sink bin */
177 g_object_set (GST_OBJECT (pipeline), "audio-sink", bin, NULL);
178 ```
179
180 It is as simple as setting the `audio-sink` property on `playbin` to
181 the newly created sink.
182
183 ``` c
184 /* Configure the equalizer */
185 g_object_set (G_OBJECT (equalizer), "band1", (gdouble)-24.0, NULL);
186 g_object_set (G_OBJECT (equalizer), "band2", (gdouble)-24.0, NULL);
187 ```
188
189 The only bit remaining is to configure the equalizer. For this example,
190 the two higher frequency bands are set to the maximum attenuation so the
191 bass is boosted. Play a bit with the values to feel the difference (Look
192 at the documentation for the `equalizer-3bands` element for the allowed
193 range of values).
194
195 ## Exercise
196
197 Build a video bin instead of an audio bin, using one of the many
198 interesting video filters GStreamer offers, like `solarize`,
199 `vertigotv` or any of the Elements in the `effectv` plugin. Remember to
200 use the color space conversion element `videoconvert` if your
201 pipeline fails to link due to incompatible caps.
202
203 ## Conclusion
204
205 This tutorial has shown:
206
207   - How to set your own sinks to `playbin` using the audio-sink and
208     video-sink properties.
209   - How to wrap a piece of pipeline into a `GstBin` so it can be used as
210     a **sink-bin** by `playbin`.
211
212 It has been a pleasure having you here, and see you soon\!
213
214   [information]: images/icons/emoticons/information.png
215   [Mac]: sdk-installing-on-mac-osx.md
216   [Windows]: sdk-installing-on-windows.md
217   [Mac OS X]: sdk-installing-on-mac-osx.md#building-the-tutorials
218   [1]: sdk-installing-on-windows.md#running-the-tutorials
219   [iOS]: sdk-installing-for-ios-development.md#building-the-tutorials
220   [android]: sdk-installing-for-android-development.md#building-the-tutorials
221   [warning]: images/icons/emoticons/warning.png