1 <chapter id="chapter-dataaccess">
2 <title>Pipeline manipulation</title>
4 This chapter will discuss how you can manipulate your pipeline in several
5 ways from your application on. Parts of this chapter are downright
6 hackish, so be assured that you'll need some programming knowledge
7 before you start reading this.
10 Topics that will be discussed here include how you can insert data into
11 a pipeline from your application, how to read data from a pipeline,
12 how to manipulate the pipeline's speed, length, starting point and how
13 to listen to a pipeline's data processing.
16 <sect1 id="section-data-probe">
17 <title>Data probing</title>
19 Probing is best envisioned as a pad listener. Technically, a probe is
20 nothing more than a signal callback that can be attached to a pad.
21 Those signals are by default not fired at all (since that may have a
22 negative impact on performance), but can be enabled by attaching a
23 probe using <function>gst_pad_add_buffer_probe ()</function>,
24 <function>gst_pad_add_event_probe ()</function>, or
25 <function>gst_pad_add_data_probe ()</function>.
26 Those functions attach the signal handler and
27 enable the actual signal emission. Similarly, one can use the
28 <function>gst_pad_remove_buffer_probe ()</function>,
29 <function>gst_pad_remove_event_probe ()</function>, or
30 <function>gst_pad_remove_data_probe ()</function>
31 to remove the signal handlers again.
34 Probes run in pipeline threading context, so callbacks should try to
35 not block and generally not do any weird stuff, since this could
36 have a negative impact on pipeline performance or, in case of bugs,
37 cause deadlocks or crashes. More precisely, one should usually not
38 call any GUI-related functions from within a probe callback, nor try
39 to change the state of the pipeline. An application may post custom
40 messages on the pipeline's bus though to communicate with the main
41 application thread and have it do things like stop the pipeline.
44 In any case, most common buffer operations
45 that elements can do in <function>_chain ()</function> functions, can
46 be done in probe callbacks as well. The example below gives a short
47 impression on how to use them (even if this usage is not entirely
48 correct, but more on that below):
50 <programlisting><!-- example-begin probe.c -->
51 #include <gst/gst.h>
54 cb_have_data (GstPad *pad,
59 guint16 *data, *ptr, t;
62 data = gst_buffer_map (buffer, &size, NULL, GST_MAP_WRITE);
66 for (y = 0; y < 288; y++) {
67 for (x = 0; x < 384 / 2; x++) {
69 ptr[384 - 1 - x] = ptr[x];
74 gst_buffer_unmap (buffer, data, size);
85 GstElement *pipeline, *src, *sink, *filter, *csp;
90 gst_init (&argc, &argv);
91 loop = g_main_loop_new (NULL, FALSE);
94 pipeline = gst_pipeline_new ("my-pipeline");
95 src = gst_element_factory_make ("videotestsrc", "src");
97 g_error ("Could not create 'videotestsrc' element");
99 filter = gst_element_factory_make ("capsfilter", "filter");
100 g_assert (filter != NULL); /* should always exist */
102 csp = gst_element_factory_make ("ffmpegcolorspace", "csp");
104 g_error ("Could not create 'ffmpegcolorspace' element");
106 sink = gst_element_factory_make ("xvimagesink", "sink");
108 sink = gst_element_factory_make ("ximagesink", "sink");
110 g_error ("Could not create neither 'xvimagesink' nor 'ximagesink' element");
113 gst_bin_add_many (GST_BIN (pipeline), src, filter, csp, sink, NULL);
114 gst_element_link_many (src, filter, csp, sink, NULL);
115 filtercaps = gst_caps_new_simple ("video/x-raw-rgb",
116 "width", G_TYPE_INT, 384,
117 "height", G_TYPE_INT, 288,
118 "framerate", GST_TYPE_FRACTION, 25, 1,
119 "bpp", G_TYPE_INT, 16,
120 "depth", G_TYPE_INT, 16,
121 "endianness", G_TYPE_INT, G_BYTE_ORDER,
123 g_object_set (G_OBJECT (filter), "caps", filtercaps, NULL);
124 gst_caps_unref (filtercaps);
126 pad = gst_element_get_pad (src, "src");
127 gst_pad_add_buffer_probe (pad, G_CALLBACK (cb_have_data), NULL);
128 gst_object_unref (pad);
131 gst_element_set_state (pipeline, GST_STATE_PLAYING);
133 /* wait until it's up and running or failed */
134 if (gst_element_get_state (pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) {
135 g_error ("Failed to go into PLAYING state");
138 g_print ("Running ...\n");
139 g_main_loop_run (loop);
142 gst_element_set_state (pipeline, GST_STATE_NULL);
143 gst_object_unref (pipeline);
147 <!-- example-end probe.c --></programlisting>
149 Compare that output with the output of <quote>gst-launch-0.10
150 videotestsrc ! xvimagesink</quote>, just so you know what you're
154 The above example is not really correct though. Strictly speaking, a
155 pad probe callback is only allowed to modify the buffer content if the
156 buffer is writable, and it is only allowed to modify buffer metadata like
157 timestamps, caps, etc. if the buffer metadata is writable. Whether this
158 is the case or not depends a lot on the pipeline and the elements
159 involved. Often enough, this is the case, but sometimes it is not,
160 and if it is not then unexpected modification of the data or metadata
161 can introduce bugs that are very hard to debug and track down. You can
162 check if a buffer and its metadata are writable with
163 <function>gst_buffer_is_writable ()</function> and
164 <function>gst_buffer_is_metadata_writable ()</function>. Since you
165 can't pass back a different buffer than the one passed in, there is no
166 point of making a buffer writable in the callback function.
169 Pad probes are suited best for looking at data as it passes through
170 the pipeline. If you need to modify data, you should write your own
171 GStreamer element. Base classes like GstAudioFilter, GstVideoFilter or
172 GstBaseTransform make this fairly easy.
175 If you just want to inspect buffers as they pass through the pipeline,
176 you don't even need to set up pad probes. You could also just insert
177 an identity element into the pipeline and connect to its "handoff"
178 signal. The identity element also provides a few useful debugging tools
179 like the "dump" property or the "last-message" property (the latter is
180 enabled by passing the '-v' switch to gst-launch).
184 <sect1 id="section-data-spoof">
185 <title>Manually adding or removing data from/to a pipeline</title>
187 Many people have expressed the wish to use their own sources to inject
188 data into a pipeline. Some people have also expressed the wish to grab
189 the output in a pipeline and take care of the actual output inside
190 their application. While either of these methods are stongly
191 discouraged, &GStreamer; offers hacks to do this. <emphasis>However,
192 there is no support for those methods.</emphasis> If it doesn't work,
193 you're on your own. Also, synchronization, thread-safety and other
194 things that you've been able to take for granted so far are no longer
195 guaranteed if you use any of those methods. It's always better to
196 simply write a plugin and have the pipeline schedule and manage it.
197 See the Plugin Writer's Guide for more information on this topic. Also
198 see the next section, which will explain how to embed plugins statically
203 url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gstreamer-app.html">New
204 API</ulink> was developed to make data insertion and extraction easy
205 for applications. It can be found as GstAppSrc and GstAppSink in the
207 url="http://gstreamer.freedesktop.org/modules/gst-plugins-base.html">
208 gst-plugins-base</ulink> module.
211 After all those disclaimers, let's start. There's three possible
212 elements that you can use for the above-mentioned purposes. Those are
213 called <quote>fakesrc</quote> (an imaginary source),
214 <quote>fakesink</quote> (an imaginary sink) and <quote>identity</quote>
215 (an imaginary filter). The same method applies to each of those
216 elements. Here, we will discuss how to use those elements to insert
217 (using fakesrc) or grab (using fakesink or identity) data from a
218 pipeline, and how to set negotiation.
221 Those who're paying close attention will notice that the purpose
222 of identity is almost identical to that of probes. Indeed, this is
223 true. Probes allow for the same purpose, and a bunch more, and
224 with less overhead plus dynamic removing/adding of handlers, but
225 apart from those, probes and identity have the same purpose, just
226 in a completely different implementation type.
229 <sect2 id="section-spoof-handoff">
230 <title>Inserting or grabbing data</title>
232 The three before-mentioned elements (fakesrc, fakesink and identity)
233 each have a <quote>handoff</quote> signal that will be called in
234 the <function>_get ()</function>- (fakesrc) or <function>_chain
235 ()</function>-function (identity, fakesink). In the signal handler,
236 you can set (fakesrc) or get (identity, fakesink) data to/from the
237 provided buffer. Note that in the case of fakesrc, you have to set
238 the size of the provided buffer using the <quote>sizemax</quote>
239 property. For both fakesrc and fakesink, you also have to set the
240 <quote>signal-handoffs</quote> property for this method to work.
243 Note that your handoff function should <emphasis>not</emphasis>
244 block, since this will block pipeline iteration. Also, do not try
245 to use all sort of weird hacks in such functions to accomplish
246 something that looks like synchronization or so; it's not the right
247 way and will lead to issues elsewhere. If you're doing any of this,
248 you're basically misunderstanding the &GStreamer; design.
252 <sect2 id="section-spoof-format">
253 <title>Forcing a format</title>
255 Sometimes, when using fakesrc as a source in your pipeline, you'll
256 want to set a specific format, for example a video size and format
257 or an audio bitsize and number of channels. You can do this by
258 forcing a specific <classname>GstCaps</classname> on the pipeline,
259 which is possible by using <emphasis>filtered caps</emphasis>. You
260 can set a filtered caps on a link by using the
261 <quote>capsfilter</quote> element in between the two elements, and
262 specifying a <classname>GstCaps</classname> as
263 <quote>caps</quote> property on this element. It will then
264 only allow types matching that specified capability set for
265 negotiation. See also <xref linkend="section-caps-filter"/>.
269 <sect2 id="section-spoof-example">
270 <title>Example application</title>
272 This example application will generate black/white (it switches
273 every second) video to an X-window output by using fakesrc as a
274 source and using filtered caps to force a format. Since the depth
275 of the image depends on your X-server settings, we use a colorspace
276 conversion element to make sure that the output to your X server
277 will have the correct bitdepth. You can also set timestamps on the
278 provided buffers to override the fixed framerate.
280 <programlisting><!-- example-begin fakesrc.c -->
281 #include <string.h> /* for memset () */
282 #include <gst/gst.h>
285 cb_handoff (GstElement *fakesrc,
290 static gboolean white = FALSE;
294 data = gst_buffer_map (buffer, &size, NULL, GST_MAP_WRITE);
296 /* this makes the image black/white */
297 memset (data, white ? 0xff : 0x0, size);
300 gst_buffer_unmap (buffer, data, size);
307 GstElement *pipeline, *fakesrc, *flt, *conv, *videosink;
311 gst_init (&argc, &argv);
312 loop = g_main_loop_new (NULL, FALSE);
315 pipeline = gst_pipeline_new ("pipeline");
316 fakesrc = gst_element_factory_make ("fakesrc", "source");
317 flt = gst_element_factory_make ("capsfilter", "flt");
318 conv = gst_element_factory_make ("ffmpegcolorspace", "conv");
319 videosink = gst_element_factory_make ("xvimagesink", "videosink");
322 g_object_set (G_OBJECT (flt), "caps",
323 gst_caps_new_simple ("video/x-raw-rgb",
324 "width", G_TYPE_INT, 384,
325 "height", G_TYPE_INT, 288,
326 "framerate", GST_TYPE_FRACTION, 1, 1,
327 "bpp", G_TYPE_INT, 16,
328 "depth", G_TYPE_INT, 16,
329 "endianness", G_TYPE_INT, G_BYTE_ORDER,
331 gst_bin_add_many (GST_BIN (pipeline), fakesrc, flt, conv, videosink, NULL);
332 gst_element_link_many (fakesrc, flt, conv, videosink, NULL);
334 /* setup fake source */
335 g_object_set (G_OBJECT (fakesrc),
336 "signal-handoffs", TRUE,
337 "sizemax", 384 * 288 * 2,
338 "sizetype", 2, NULL);
339 g_signal_connect (fakesrc, "handoff", G_CALLBACK (cb_handoff), NULL);
342 gst_element_set_state (pipeline, GST_STATE_PLAYING);
343 g_main_loop_run (loop);
346 gst_element_set_state (pipeline, GST_STATE_NULL);
347 gst_object_unref (GST_OBJECT (pipeline));
351 <!-- example-end fakesrc.c --></programlisting>
355 <sect1 id="section-data-manager">
356 <title>Embedding static elements in your application</title>
358 The <ulink type="http"
359 url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/index.html">Plugin
360 Writer's Guide</ulink> describes in great detail how to write elements
361 for the &GStreamer; framework. In this section, we will solely discuss
362 how to embed such elements statically in your application. This can be
363 useful for application-specific elements that have no use elsewhere in
367 Dynamically loaded plugins contain a structure that's defined using
368 <function>GST_PLUGIN_DEFINE ()</function>. This structure is loaded
369 when the plugin is loaded by the &GStreamer; core. The structure
370 contains an initialization function (usually called
371 <function>plugin_init</function>) that will be called right after that.
372 It's purpose is to register the elements provided by the plugin with
373 the &GStreamer; framework. If you want to embed elements directly in
374 your application, the only thing you need to do is to replace
375 <function>GST_PLUGIN_DEFINE ()</function> with
376 <function>GST_PLUGIN_DEFINE_STATIC ()</function>. This will cause the
377 elements to be registered when your application loads, and the elements
378 will from then on be available like any other element, without them
379 having to be dynamically loadable libraries. In the example below, you
380 would be able to call <function>gst_element_factory_make
381 ("my-element-name", "some-name")</function> to create an instance of the
387 * Here, you would write the actual plugin code.
393 register_elements (GstPlugin *plugin)
395 return gst_element_register (plugin, "my-element-name",
396 GST_RANK_NONE, MY_PLUGIN_TYPE);
399 GST_PLUGIN_DEFINE_STATIC (
402 "my-private-plugins",
403 "Private elements of my application",
408 "http://www.my-application.net/"