0f19d74d2b4059d5351e343e7d78be798ea27c27
[platform/upstream/gstreamer.git] / docs / manual / advanced-threads.xml
1 <chapter id="chapter-threads">
2   <title>Threads</title>
3   <para> 
4     GStreamer has support for multithreading through the use of
5     the <ulink type="http" url="../../gstreamer/html/GstThread.html"><classname>
6     GstThread</classname></ulink> object. This object is in fact
7     a special <ulink type="http" url="../../gstreamer/html/GstBin.html"><classname>
8     GstBin</classname></ulink> that will become a thread when started.
9   </para>
10
11   <para> 
12     To construct a new thread you will perform something like:
13   </para>
14
15   <para>
16     <programlisting>
17   GstElement *my_thread;
18
19   /* create the thread object */
20   my_thread = gst_thread_new ("my_thread");
21   /* you could have used gst_element_factory_make ("thread", "my_thread"); */
22   g_return_if_fail (my_thread != NULL);
23
24   /* add some plugins */
25   gst_bin_add (GST_BIN (my_thread), GST_ELEMENT (funky_src));
26   gst_bin_add (GST_BIN (my_thread), GST_ELEMENT (cool_effect));
27
28   /* link the elements here... */
29   ...
30   
31   /* start playing */
32   gst_element_set_state (GST_ELEMENT (my_thread), GST_STATE_PLAYING);
33
34     </programlisting>
35   </para>
36   <para>
37     The above program will create a thread with two elements in it. As soon
38     as it is set to the PLAYING state, the thread will start to iterate
39     itself. You never need to explicitly iterate a thread.
40   </para>
41   
42   <sect1 id="section-threads-constraints">
43     <title>Constraints placed on the pipeline by the GstThread</title>
44     <para>
45       Within the pipeline, everything is the same as in any other bin. The
46       difference lies at the thread boundary, at the link between the
47       thread and the outside world (containing bin).  Since GStreamer is
48       fundamentally buffer-oriented rather than byte-oriented, the natural
49       solution to this problem is an element that can "buffer" the buffers
50       between the threads, in a thread-safe fashion. This element is the
51       queue, described more fully in <xref linkend="chapter-queues"/>. It doesn't
52       matter if the queue is placed in the containing bin or in the thread
53       itself, but it needs to be present on one side or the other to enable
54       inter-thread communication.
55     </para>
56   </sect1>
57   <sect1 id="section-threads-when">
58     <title>When would you want to use a thread?</title>
59     <para>
60       If you are writing a GUI application, making the top-level bin a thread will make your GUI
61       more responsive. If it were a pipeline instead, it would have to be iterated by your
62       application's event loop, which increases the latency between events (say, keyboard presses)
63       and responses from the GUI. In addition, any slight hang in the GUI would delay iteration of
64       the pipeline, which (for example) could cause pops in the output of the sound card, if it is
65       an audio pipeline.
66     </para>
67     <para> 
68     <xref linkend="section-threads-img"/> shows how a thread can be visualised.
69     </para>
70     <figure float="1" id="section-threads-img">
71       <title>A thread</title>
72       <mediaobject>
73         <imageobject>
74           <imagedata fileref="images/thread.&image;" format="&IMAGE;" />
75         </imageobject>
76       </mediaobject>  
77     </figure>
78
79     <para> 
80     As an example we show the helloworld program using a thread.
81     </para>
82   
83     <para>
84       <programlisting>
85 <!-- example-begin threads.c a -->
86 <![CDATA[
87 #include <gst/gst.h>
88
89 /* we set this to TRUE right before gst_main (), but there could still
90    be a race condition between setting it and entering the function */
91 gboolean can_quit = FALSE;
92
93 /* eos will be called when the src element has an end of stream */
94 void 
95 eos (GstElement *src, gpointer data) 
96 {
97   GstThread *thread = GST_THREAD (data);
98   g_print ("have eos, quitting\n");
99
100   /* stop the bin */
101   gst_element_set_state (GST_ELEMENT (thread), GST_STATE_NULL);
102
103   while (!can_quit) /* waste cycles */ ;
104   gst_main_quit ();
105 }
106
107 int 
108 main (int argc, char *argv[]) 
109 {
110   GstElement *filesrc, *demuxer, *decoder, *converter, *audiosink;
111   GstElement *thread;
112
113   if (argc &lt; 2) {
114     g_print ("usage: %s &lt;Ogg/Vorbis filename&gt;\n", argv[0]);
115     exit (-1);
116   }
117
118   gst_init (&amp;argc, &amp;argv);
119
120   /* create a new thread to hold the elements */
121   thread = gst_thread_new ("thread");
122   g_assert (thread != NULL);
123
124   /* create a disk reader */
125   filesrc = gst_element_factory_make ("filesrc", "disk_source");
126   g_assert (filesrc != NULL);
127   g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
128   g_signal_connect (G_OBJECT (filesrc), "eos",
129                      G_CALLBACK (eos), thread);
130
131   /* create an ogg demuxer */
132   demuxer = gst_element_factory_make ("oggdemux", "demuxer");
133   g_assert (demuxer != NULL);
134
135   /* create a vorbis decoder */
136   decoder = gst_element_factory_make ("vorbisdec", "decoder");
137   g_assert (decoder != NULL);
138
139   /* create an audio converter */
140   converter = gst_element_factory_make ("audioconvert", "converter");
141   g_assert (decoder != NULL);
142
143   /* and an audio sink */
144   audiosink = gst_element_factory_make ("osssink", "play_audio");
145   g_assert (audiosink != NULL);
146
147   /* add objects to the thread */
148   gst_bin_add_many (GST_BIN (thread), filesrc, demuxer, decoder, converter, audiosink, NULL);
149   /* link them in the logical order */
150   gst_element_link_many (filesrc, demuxer, decoder, converter, audiosink, NULL);
151
152   /* start playing */
153   gst_element_set_state (thread, GST_STATE_PLAYING);
154
155   /* do whatever you want here, the thread will be playing */
156   g_print ("thread is playing\n");
157   
158   can_quit = TRUE;
159   gst_main ();
160
161   gst_object_unref (GST_OBJECT (thread));
162
163   exit (0);
164 }
165 ]]>
166 <!-- example-end threads.c a -->
167       </programlisting>
168     </para>
169   </sect1>
170 </chapter>