3781a365642a5d2cf857a436bcaf5806507d7230
[platform/upstream/gstreamer.git] / docs / manual / advanced-dataaccess.xml
1 <chapter id="chapter-dataaccess">
2   <title>Pipeline manipulation</title>
3   <para>
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.
8   </para>
9   <para>
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.
14   </para>
15
16   <sect1 id="section-data-probe">
17     <title>Data probing</title>
18     <para>
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.
32     </para>
33     <para>
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.
42     </para>
43     <para>
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):
49     </para>
50     <programlisting><!-- example-begin probe.c -->
51 #include &lt;gst/gst.h&gt;
52
53 static gboolean
54 cb_have_data (GstPad    *pad,
55               GstBuffer *buffer,
56               gpointer   u_data)
57 {
58   gint x, y;
59   GstMapInfo info;
60   guint16 *ptr, t;
61   
62   gst_buffer_map (buffer, &amp;info, GST_MAP_WRITE);
63
64   ptr = info.data;
65   /* invert data */
66   for (y = 0; y &lt; 288; y++) {
67     for (x = 0; x &lt; 384 / 2; x++) {
68       t = ptr[384 - 1 - x];
69       ptr[384 - 1 - x] = ptr[x];
70       ptr[x] = t;
71     }
72     ptr += 384;
73   }
74   gst_buffer_unmap (buffer, &amp;info);
75
76   return TRUE;
77 }
78
79 gint
80 main (gint   argc,
81       gchar *argv[])
82 {
83   GMainLoop *loop;
84   GstElement *pipeline, *src, *sink, *filter, *csp;
85   GstCaps *filtercaps;
86   GstPad *pad;
87
88   /* init GStreamer */
89   gst_init (&amp;argc, &amp;argv);
90   loop = g_main_loop_new (NULL, FALSE);
91
92   /* build */
93   pipeline = gst_pipeline_new ("my-pipeline");
94   src = gst_element_factory_make ("videotestsrc", "src");
95   if (src == NULL)
96     g_error ("Could not create 'videotestsrc' element");
97
98   filter = gst_element_factory_make ("capsfilter", "filter");
99   g_assert (filter != NULL); /* should always exist */
100
101   csp = gst_element_factory_make ("ffmpegcolorspace", "csp");
102   if (csp == NULL)
103     g_error ("Could not create 'ffmpegcolorspace' element");
104
105   sink = gst_element_factory_make ("xvimagesink", "sink");
106   if (sink == NULL) {
107     sink = gst_element_factory_make ("ximagesink", "sink");
108     if (sink == NULL)
109       g_error ("Could not create neither 'xvimagesink' nor 'ximagesink' element");
110   }
111
112   gst_bin_add_many (GST_BIN (pipeline), src, filter, csp, sink, NULL);
113   gst_element_link_many (src, filter, csp, sink, NULL);
114   filtercaps = gst_caps_new_simple ("video/x-raw-rgb",
115                            "width", G_TYPE_INT, 384,
116                            "height", G_TYPE_INT, 288,
117                            "framerate", GST_TYPE_FRACTION, 25, 1,
118                            "bpp", G_TYPE_INT, 16,
119                            "depth", G_TYPE_INT, 16,
120                            "endianness", G_TYPE_INT, G_BYTE_ORDER,
121                            NULL);
122   g_object_set (G_OBJECT (filter), "caps", filtercaps, NULL);
123   gst_caps_unref (filtercaps);
124
125   pad = gst_element_get_pad (src, "src");
126   gst_pad_add_buffer_probe (pad, G_CALLBACK (cb_have_data), NULL);
127   gst_object_unref (pad);
128
129   /* run */
130   gst_element_set_state (pipeline, GST_STATE_PLAYING);
131
132   /* wait until it's up and running or failed */
133   if (gst_element_get_state (pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE) {
134     g_error ("Failed to go into PLAYING state");
135   }
136
137   g_print ("Running ...\n");
138   g_main_loop_run (loop);
139
140   /* exit */
141   gst_element_set_state (pipeline, GST_STATE_NULL);
142   gst_object_unref (pipeline);
143
144   return 0;
145 }
146     <!-- example-end probe.c --></programlisting>
147     <para>
148       Compare that output with the output of <quote>gst-launch-0.10
149       videotestsrc ! xvimagesink</quote>, just so you know what you're
150       looking for.
151     </para>
152     <para>
153       The above example is not really correct though.  Strictly speaking, a
154       pad probe callback is only allowed to modify the buffer content if the
155       buffer is writable, and it is only allowed to modify buffer metadata like
156       timestamps, caps, etc. if the buffer metadata is writable.  Whether this
157       is the case or not depends a lot on the pipeline and the elements
158       involved.  Often enough, this is the case, but sometimes it is not,
159       and if it is not then unexpected modification of the data or metadata
160       can introduce bugs that are very hard to debug and track down. You can
161       check if a buffer and its metadata are writable with
162       <function>gst_buffer_is_writable ()</function> and
163       <function>gst_buffer_is_metadata_writable ()</function>.  Since you
164       can't pass back a different buffer than the one passed in, there is no
165       point of making a buffer writable in the callback function.
166     </para>
167     <para>
168       Pad probes are suited best for looking at data as it passes through
169       the pipeline. If you need to modify data, you should write your own
170       GStreamer element. Base classes like GstAudioFilter, GstVideoFilter or
171       GstBaseTransform make this fairly easy.
172     </para>
173     <para>
174       If you just want to inspect buffers as they pass through the pipeline,
175       you don't even need to set up pad probes. You could also just insert
176       an identity element into the pipeline and connect to its "handoff"
177       signal. The identity element also provides a few useful debugging tools
178       like the "dump" property or the "last-message" property (the latter is
179       enabled by passing the '-v' switch to gst-launch).
180     </para>
181   </sect1>
182
183   <sect1 id="section-data-spoof">
184     <title>Manually adding or removing data from/to a pipeline</title>
185     <para>
186       Many people have expressed the wish to use their own sources to inject
187       data into a pipeline. Some people have also expressed the wish to grab
188       the output in a pipeline and take care of the actual output inside
189       their application. While either of these methods are stongly
190       discouraged, &GStreamer; offers hacks to do this. <emphasis>However,
191       there is no support for those methods.</emphasis> If it doesn't work,
192       you're on your own. Also, synchronization, thread-safety and other
193       things that you've been able to take for granted so far are no longer
194       guaranteed if you use any of those methods. It's always better to
195       simply write a plugin and have the pipeline schedule and manage it.
196       See the Plugin Writer's Guide for more information on this topic. Also
197       see the next section, which will explain how to embed plugins statically
198       in your application.
199     </para>
200     <note><para>
201         <ulink type="http"
202           url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/gstreamer-app.html">New
203           API</ulink> was developed to make data insertion and extraction easy
204         for applications. It can be found as GstAppSrc and GstAppSink in the
205         <ulink type="http"
206           url="http://gstreamer.freedesktop.org/modules/gst-plugins-base.html">
207           gst-plugins-base</ulink> module.
208     </para></note>
209     <para>
210       After all those disclaimers, let's start. There's three possible
211       elements that you can use for the above-mentioned purposes. Those are
212       called <quote>fakesrc</quote> (an imaginary source),
213       <quote>fakesink</quote> (an imaginary sink) and <quote>identity</quote>
214       (an imaginary filter). The same method applies to each of those
215       elements. Here, we will discuss how to use those elements to insert
216       (using fakesrc) or grab (using fakesink or identity) data from a
217       pipeline, and how to set negotiation.
218     </para>
219     <para>
220       Those who're paying close attention will notice that the purpose
221       of identity is almost identical to that of probes. Indeed, this is
222       true. Probes allow for the same purpose, and a bunch more, and
223       with less overhead plus dynamic removing/adding of handlers, but
224       apart from those, probes and identity have the same purpose, just
225       in a completely different implementation type.
226     </para>
227
228     <sect2 id="section-spoof-handoff">
229       <title>Inserting or grabbing data</title>
230       <para>
231         The three before-mentioned elements (fakesrc, fakesink and identity)
232         each have a <quote>handoff</quote> signal that will be called in
233         the <function>_get ()</function>- (fakesrc) or <function>_chain
234         ()</function>-function (identity, fakesink). In the signal handler,
235         you can set (fakesrc) or get (identity, fakesink) data to/from the
236         provided buffer. Note that in the case of fakesrc, you have to set
237         the size of the provided buffer using the <quote>sizemax</quote>
238         property. For both fakesrc and fakesink, you also have to set the
239         <quote>signal-handoffs</quote> property for this method to work.
240       </para>
241       <para>
242         Note that your handoff function should <emphasis>not</emphasis>
243         block, since this will block pipeline iteration. Also, do not try
244         to use all sort of weird hacks in such functions to accomplish
245         something that looks like synchronization or so; it's not the right
246         way and will lead to issues elsewhere. If you're doing any of this,
247         you're basically misunderstanding the &GStreamer; design.
248       </para>
249     </sect2>
250
251     <sect2 id="section-spoof-format">
252       <title>Forcing a format</title>
253       <para>
254         Sometimes, when using fakesrc as a source in your pipeline, you'll
255         want to set a specific format, for example a video size and format
256         or an audio bitsize and number of channels. You can do this by
257         forcing a specific <classname>GstCaps</classname> on the pipeline,
258         which is possible by using <emphasis>filtered caps</emphasis>. You
259         can set a filtered caps on a link by using the
260         <quote>capsfilter</quote> element in between the two elements, and
261         specifying a <classname>GstCaps</classname> as
262         <quote>caps</quote> property on this element. It will then
263         only allow types matching that specified capability set for
264         negotiation.  See also <xref linkend="section-caps-filter"/>.
265       </para>
266     </sect2>
267
268     <sect2 id="section-spoof-example">
269       <title>Example application</title>
270       <para>
271         This example application will generate black/white (it switches
272         every second) video to an X-window output by using fakesrc as a
273         source and using filtered caps to force a format. Since the depth
274         of the image depends on your X-server settings, we use a colorspace
275         conversion element to make sure that the output to your X server
276         will have the correct bitdepth. You can also set timestamps on the
277         provided buffers to override the fixed framerate.
278       </para>
279       <programlisting><!-- example-begin fakesrc.c -->
280 #include &lt;string.h&gt; /* for memset () */
281 #include &lt;gst/gst.h&gt;
282
283 static void
284 cb_handoff (GstElement *fakesrc,
285             GstBuffer  *buffer,
286             GstPad     *pad,
287             gpointer    user_data)
288 {
289   static gboolean white = FALSE;
290   GstMapInfo info;
291   
292   gst_buffer_map (buffer, &amp;info, GST_MAP_WRITE);
293
294   /* this makes the image black/white */
295   memset (info.data, white ? 0xff : 0x0, info.size);
296   white = !white;
297
298   gst_buffer_unmap (buffer, &amp;info);
299 }
300
301 gint
302 main (gint   argc,
303       gchar *argv[])
304 {
305   GstElement *pipeline, *fakesrc, *flt, *conv, *videosink;
306   GMainLoop *loop;
307
308   /* init GStreamer */
309   gst_init (&amp;argc, &amp;argv);
310   loop = g_main_loop_new (NULL, FALSE);
311
312   /* setup pipeline */
313   pipeline = gst_pipeline_new ("pipeline");
314   fakesrc = gst_element_factory_make ("fakesrc", "source");
315   flt = gst_element_factory_make ("capsfilter", "flt");
316   conv = gst_element_factory_make ("ffmpegcolorspace", "conv");
317   videosink = gst_element_factory_make ("xvimagesink", "videosink");
318
319   /* setup */
320   g_object_set (G_OBJECT (flt), "caps",
321                 gst_caps_new_simple ("video/x-raw-rgb",
322                                      "width", G_TYPE_INT, 384,
323                                      "height", G_TYPE_INT, 288,
324                                      "framerate", GST_TYPE_FRACTION, 1, 1,
325                                      "bpp", G_TYPE_INT, 16,
326                                      "depth", G_TYPE_INT, 16,
327                                      "endianness", G_TYPE_INT, G_BYTE_ORDER,
328                                      NULL), NULL);
329   gst_bin_add_many (GST_BIN (pipeline), fakesrc, flt, conv, videosink, NULL);
330   gst_element_link_many (fakesrc, flt, conv, videosink, NULL);
331
332   /* setup fake source */
333   g_object_set (G_OBJECT (fakesrc),
334                 "signal-handoffs", TRUE,
335                 "sizemax", 384 * 288 * 2,
336                 "sizetype", 2, NULL);
337   g_signal_connect (fakesrc, "handoff", G_CALLBACK (cb_handoff), NULL);
338
339   /* play */
340   gst_element_set_state (pipeline, GST_STATE_PLAYING);
341   g_main_loop_run (loop);
342
343   /* clean up */
344   gst_element_set_state (pipeline, GST_STATE_NULL);
345   gst_object_unref (GST_OBJECT (pipeline));
346
347   return 0;
348 }
349       <!-- example-end fakesrc.c --></programlisting>
350     </sect2>
351   </sect1>
352
353   <sect1 id="section-data-manager">
354     <title>Embedding static elements in your application</title>
355     <para>
356       The <ulink type="http"
357       url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/index.html">Plugin
358       Writer's Guide</ulink> describes in great detail how to write elements
359       for the &GStreamer; framework. In this section, we will solely discuss
360       how to embed such elements statically in your application. This can be
361       useful for application-specific elements that have no use elsewhere in
362       &GStreamer;.
363     </para>
364     <para>
365       Dynamically loaded plugins contain a structure that's defined using
366       <function>GST_PLUGIN_DEFINE ()</function>. This structure is loaded
367       when the plugin is loaded by the &GStreamer; core. The structure
368       contains an initialization function (usually called
369       <function>plugin_init</function>) that will be called right after that.
370       It's purpose is to register the elements provided by the plugin with
371       the &GStreamer; framework. If you want to embed elements directly in
372       your application, the only thing you need to do is to replace
373           <function>GST_PLUGIN_DEFINE ()</function> with
374           <function>GST_PLUGIN_DEFINE_STATIC ()</function>. This will cause the
375       elements to be registered when your application loads, and the elements
376       will from then on be available like any other element, without them
377       having to be dynamically loadable libraries. In the example below, you
378       would be able to call <function>gst_element_factory_make
379       ("my-element-name", "some-name")</function> to create an instance of the
380       element.
381     </para>
382
383     <programlisting>
384 /*
385  * Here, you would write the actual plugin code.
386  */
387
388 [..]
389
390 static gboolean
391 register_elements (GstPlugin *plugin)
392 {
393   return gst_element_register (plugin, "my-element-name",
394                                GST_RANK_NONE, MY_PLUGIN_TYPE);
395 }
396
397 GST_PLUGIN_DEFINE_STATIC (
398   GST_VERSION_MAJOR,
399   GST_VERSION_MINOR,
400   "my-private-plugins",
401   "Private elements of my application",
402   register_elements,
403   VERSION,
404   "LGPL",
405   "my-application",
406   "http://www.my-application.net/"
407 )
408     </programlisting>
409   </sect1>
410 </chapter>