Implement our own theme, yay!
[platform/upstream/gstreamer.git] / sdk-playback-tutorial-audio-visualization.md
1 # Playback tutorial 6: Audio visualization
2
3 ## Goal
4
5 GStreamer comes with a set of elements that turn audio into video. They
6 can be used for scientific visualization or to spice up your music
7 player, for example. This tutorial shows:
8
9   - How to enable audio visualization
10   - How to select the visualization element
11
12 ## Introduction
13
14 Enabling audio visualization in `playbin` is actually very easy. Just
15 set the appropriate `playbin` flag and, when an audio-only stream is
16 found, it will instantiate the necessary elements to create and display
17 the visualization.
18
19 If you want to specify the actual element that you want to use to
20 generate the visualization, you instantiate it yourself and then tell
21 `playbin` about it through the `vis-plugin` property.
22
23 This tutorial searches the GStreamer registry for all the elements of
24 the Visualization class, tries to select `goom` (or another one if it is
25 not available) and passes it to `playbin`.
26
27 ## A fancy music player
28
29 Copy this code into a text file named `playback-tutorial-6.c`.
30
31 **playback-tutorial-6.c**
32
33 ``` c
34 #include <gst/gst.h>
35
36 /* playbin flags */
37 typedef enum {
38   GST_PLAY_FLAG_VIS           = (1 << 3) /* Enable rendering of visualizations when there is no video stream. */
39 } GstPlayFlags;
40
41 /* Return TRUE if this is a Visualization element */
42 static gboolean filter_vis_features (GstPluginFeature *feature, gpointer data) {
43   GstElementFactory *factory;
44
45   if (!GST_IS_ELEMENT_FACTORY (feature))
46     return FALSE;
47   factory = GST_ELEMENT_FACTORY (feature);
48   if (!g_strrstr (gst_element_factory_get_klass (factory), "Visualization"))
49     return FALSE;
50
51   return TRUE;
52 }
53
54 int main(int argc, char *argv[]) {
55   GstElement *pipeline, *vis_plugin;
56   GstBus *bus;
57   GstMessage *msg;
58   GList *list, *walk;
59   GstElementFactory *selected_factory = NULL;
60   guint flags;
61
62   /* Initialize GStreamer */
63   gst_init (&argc, &argv);
64
65   /* Get a list of all visualization plugins */
66   list = gst_registry_feature_filter (gst_registry_get (), filter_vis_features, FALSE, NULL);
67
68   /* Print their names */
69   g_print("Available visualization plugins:\n");
70   for (walk = list; walk != NULL; walk = g_list_next (walk)) {
71     const gchar *name;
72     GstElementFactory *factory;
73
74     factory = GST_ELEMENT_FACTORY (walk->data);
75     name = gst_element_factory_get_longname (factory);
76     g_print("  %s\n", name);
77
78     if (selected_factory == NULL || g_str_has_prefix (name, "GOOM")) {
79       selected_factory = factory;
80     }
81   }
82
83   /* Don't use the factory if it's still empty */
84   /* e.g. no visualization plugins found */
85   if (!selected_factory) {
86     g_print ("No visualization plugins found!\n");
87     return -1;
88   }
89
90   /* We have now selected a factory for the visualization element */
91   g_print ("Selected '%s'\n", gst_element_factory_get_longname (selected_factory));
92   vis_plugin = gst_element_factory_create (selected_factory, NULL);
93   if (!vis_plugin)
94     return -1;
95
96   /* Build the pipeline */
97   pipeline = gst_parse_launch ("playbin uri=http://radio.hbr1.com:19800/ambient.ogg", NULL);
98
99   /* Set the visualization flag */
100   g_object_get (pipeline, "flags", &flags, NULL);
101   flags |= GST_PLAY_FLAG_VIS;
102   g_object_set (pipeline, "flags", flags, NULL);
103
104   /* set vis plugin for playbin */
105   g_object_set (pipeline, "vis-plugin", vis_plugin, NULL);
106
107   /* Start playing */
108   gst_element_set_state (pipeline, GST_STATE_PLAYING);
109
110   /* Wait until error or EOS */
111   bus = gst_element_get_bus (pipeline);
112   msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
113
114   /* Free resources */
115   if (msg != NULL)
116     gst_message_unref (msg);
117   gst_plugin_feature_list_free (list);
118   gst_object_unref (bus);
119   gst_element_set_state (pipeline, GST_STATE_NULL);
120   gst_object_unref (pipeline);
121   return 0;
122 }
123 ```
124
125 > ![information] If you need help to compile this code, refer to the
126 > **Building the tutorials** section for your platform: [Mac] or
127 > [Windows] or use this specific command on Linux:
128 >
129 > `` gcc playback-tutorial-6.c -o playback-tutorial-6 `pkg-config --cflags --libs gstreamer-1.0` ``
130 >
131 > If you need help to run this code, refer to the **Running the
132 > tutorials** section for your platform: [Mac OS X], [Windows][1], for
133 > [iOS] or for [android].
134 >
135 > This tutorial plays music streamed from the [HBR1](http://www.hbr1.com/) Internet radio station. A window should open displaying somewhat psychedelic color patterns moving with the music. The media is fetched from the Internet, so the window might take a few seconds to appear, depending on your connection speed.
136 >
137 > Required libraries: `gstreamer-1.0`
138
139 ## Walkthrough
140
141 First off, we indicate `playbin` that we want an audio visualization by
142 setting the `GST_PLAY_FLAG_VIS` flag. If the media already contains
143 video, this flag has no effect.
144
145 ``` c
146 /* Set the visualization flag */
147 g_object_get (pipeline, "flags", &flags, NULL);
148 flags |= GST_PLAY_FLAG_VIS;
149 g_object_set (pipeline, "flags", flags, NULL);
150 ```
151
152 If no visualization plugin is enforced by the user, `playbin` will use
153 `goom` (audio visualization will be disabled if `goom` is not
154 available). The rest of the tutorial shows how to find out the available
155 visualization elements and enforce one to `playbin`.
156
157 ``` c
158 /* Get a list of all visualization plugins */
159 list = gst_registry_feature_filter (gst_registry_get (), filter_vis_features, FALSE, NULL);
160 ```
161
162 `gst_registry_feature_filter()` examines all elements currently in the
163 GStreamer registry and selects those for which
164 the `filter_vis_features` function returns TRUE. This function selects
165 only the Visualization plugins:
166
167 ``` c
168 /* Return TRUE if this is a Visualization element */
169 static gboolean filter_vis_features (GstPluginFeature *feature, gpointer data) {
170   GstElementFactory *factory;
171
172   if (!GST_IS_ELEMENT_FACTORY (feature))
173     return FALSE;
174   factory = GST_ELEMENT_FACTORY (feature);
175   if (!g_strrstr (gst_element_factory_get_klass (factory), "Visualization"))
176     return FALSE;
177
178   return TRUE;
179 }
180 ```
181
182 A bit of theory regarding the organization of GStreamer elements is in
183 place: Each of the files that GStreamer loads at runtime is known as a
184 Plugin (`GstPlugin`). A Plugin can contain many Features
185 (`GstPluginFeature`). There are different kinds of Features, among them,
186 the Element Factories (`GstElementFactory`) that we have been using to
187 build Elements (`GstElement`).
188
189 This function simply disregards all Features which are not Factories,
190 and then all Factories whose class (obtained with
191 `gst_element_factory_get_klass()`) does not include “Visualization”.  As
192 stated in the documentation for `GstElementFactory`, a Factory’s class
193 is a “string describing the type of element, as an unordered list
194 separated with slashes (/)”. Examples of classes are “Source/Network”,
195 “Codec/Decoder/Video”, “Codec/Encoder/Audio” or “Visualization”.
196
197 ``` c
198 /* Print their names */
199 g_print("Available visualization plugins:\n");
200 for (walk = list; walk != NULL; walk = g_list_next (walk)) {
201   const gchar *name;
202   GstElementFactory *factory;
203
204   factory = GST_ELEMENT_FACTORY (walk->data);
205   name = gst_element_factory_get_longname (factory);
206   g_print("  %s\n", name);
207
208   if (selected_factory == NULL || g_str_has_prefix (name, "GOOM")) {
209     selected_factory = factory;
210   }
211 }
212 ```
213
214 Once we have the list of Visualization plugins, we print their names
215 (`gst_element_factory_get_longname()`) and choose one (in this case,
216 GOOM).
217
218 ``` c
219 /* We have now selected a factory for the visualization element */
220 g_print ("Selected '%s'\n", gst_element_factory_get_longname (selected_factory));
221 vis_plugin = gst_element_factory_create (selected_factory, NULL);
222 if (!vis_plugin)
223   return -1;
224 ```
225
226 The selected factory is used to instantiate an actual `GstElement` which
227 is then passed to `playbin` through the `vis-plugin` property:
228
229 ``` c
230 /* set vis plugin for playbin */
231 g_object_set (pipeline, "vis-plugin", vis_plugin, NULL);
232 ```
233
234 And we are done.
235
236 ## Conclusion
237
238 This tutorial has shown:
239
240   - How to enable Audio Visualization in `playbin` with the
241     `GST_PLAY_FLAG_VIS` flag
242   - How to enforce one particular visualization element with the
243     `vis-plugin` `playbin` property 
244
245 It has been a pleasure having you here, and see you soon\!
246
247   [information]: images/icons/emoticons/information.png
248   [Mac]: sdk-installing-on-mac-osx.md
249   [Windows]: sdk-installing-on-windows.md
250   [Mac OS X]: sdk-installing-on-mac-osx.md#building-the-tutorials
251   [1]: sdk-installing-on-windows.md#running-the-tutorials
252   [iOS]: sdk-installing-for-ios-development.md#building-the-tutorials
253   [android]: sdk-installing-for-android-development.md#building-the-tutorials
254   [warning]: images/icons/emoticons/warning.png