summaryrefslogtreecommitdiff
path: root/docs/manual/helloworld.sgml
blob: 1002425dca81aad17aec4c298a2453d2a78e2be8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<chapter id="cha-hello">
  <title>Your first application</title>
  <para> 
    This chapter describes the most rudimentary aspects of a <application>GStreamer</application> application, 
    including initializing the libraries, creating elements, packing them into
    a pipeline and playing, pause and stop the pipeline.
  </para>

  <sect1>
    <title>Hello world</title>
    <para> 
      We will create a simple first application. In fact it will be a complete
      MP3 player, using standard <application>GStreamer</application> components. The player will read from
      a file that is given as the first argument of the program.
    </para>


    <programlisting>
      
#include &lt;gst/gst.h&gt;

int 
main (int argc, char *argv[]) 
{
  GstElement *pipeline, *disksrc, *parse, *decoder, *audiosink;

  gst_init(&amp;argc, &amp;argv);

  if (argc != 2) {
    g_print ("usage: &percnt;s &lt;filename&gt;\n", argv[0]);
    exit (-1);
  }

  /* create a new pipeline to hold the elements */
  pipeline = gst_pipeline_new ("pipeline");

  /* create a disk reader */
  disksrc = gst_elementfactory_make ("disksrc", "disk_source");
  g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);

  /* now it's time to get the parser */
  parse = gst_elementfactory_make ("mp3parse", "parse");
  decoder = gst_elementfactory_make ("mpg123", "decoder");
  
  /* and an audio sink */
  audiosink = gst_elementfactory_make ("osssink", "play_audio");

  /* add objects to the main pipeline */
  gst_bin_add (GST_BIN (pipeline), disksrc);
  gst_bin_add (GST_BIN (pipeline), parse);
  gst_bin_add (GST_BIN (pipeline), decoder);
  gst_bin_add (GST_BIN (pipeline), audiosink);

  /* connect src to sink */
  gst_pad_connect (gst_element_get_pad (disksrc, "src"),
                   gst_element_get_pad (parse, "sink"));
  gst_pad_connect (gst_element_get_pad (parse, "src"),
                   gst_element_get_pad (decoder, "sink"));
  gst_pad_connect (gst_element_get_pad (decoder, "src"),
                   gst_element_get_pad (audiosink, "sink"));

  /* start playing */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  while (gst_bin_iterate (GST_BIN (pipeline)));

  /* stop the pipeline */
  gst_element_set_state (pipeline, GST_STATE_NULL);

  /* we don't need a reference to these objects anymore */
  gst_object_unref (GST_OBJECT (audiosink));
  gst_object_unref (GST_OBJECT (parse));
  gst_object_unref (GST_OBJECT (decoder));
  gst_object_unref (GST_OBJECT (disksrc));
  gst_object_unref (GST_OBJECT (pipeline));

  exit (0);
}

    </programlisting>

    <para>
      Let's go through this example step by step.
    </para>

    <para>
      The first thing you have to do is to include the standard <application>GStreamer</application> headers and 
      initialize the framework.
    </para>
    <programlisting>

#include &lt;gst/gst.h&gt;

  ...

int 
main (int argc, char *argv[]) 
{
  ...
  gst_init(&amp;argc, &amp;argv);
  ...

    </programlisting>

    <para>
      We are going to create 4 elements and one pipeline. Since all objects are
      in fact elements, we can define them as:
    </para>
    <programlisting>
  ...
  GstElement *pipeline, *disksrc, *parse, *decoder, *audiosink;
  ...
    </programlisting>

    <para>
      Next, we are going to create an empty pipeline. As you have seen in the basic
      introduction, this pipeline will hold and manage all the elements we are 
      going to stuff into it.
    </para>
    <programlisting>
  /* create a new pipeline to hold the elements */
  pipeline = gst_pipeline_new ("pipeline");
    </programlisting>
    <para>
      We use the standard constructor for a pipeline: gst_pipeline_new ("name").
    </para>

    <para>
      We then create a disk source element. The disk source element is able to
      read from a file.  We use the standard GObject property mechanism to set
      a property of the element: the file to read from.
    </para>
    <programlisting>
  /* create a disk reader */
  disksrc = gst_elementfactory_make ("disksrc", "disk_source");
  g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
    </programlisting>
    <note>
      <para>
        You can check if the disksrc != NULL to verify the creation of the
	disk source element.
      </para>
    </note>

    <para>
      We now create the MP3 decoder element. <application>GStreamer</application> requires you
      to put a parser in front of the decoder. This parser will
      cut the raw data from the disk source into MP3 frames
      suitable for the decoder. In the advanced concepts chapter we will
      see how this can be avoided.
    </para>
    <programlisting>
  /* now it's time to get the parser */
  parse = gst_elementfactory_make ("mp3parse", "parse");
  decoder = gst_elementfactory_make ("mpg123", "decoder");
    </programlisting>
    <para>
      gst_elementfactory_make() takes two arguments: a string that will
      identify the element you need and a second argument: how you want
      to name the element. The name of the element is something you can
      choose yourself and might be used to retrieve the element from a
      bin/pipeline.
    </para>

    <para>
      Finally we create our audio sink element. This element will be able
      to playback the audio using OSS.
    </para>
    <programlisting>
  /* and an audio sink */
  audiosink = gst_elementfactory_make ("audiosink", "play_audio");
    </programlisting>

    <para>
      We then add the elements to the pipeline.
    </para>
    <programlisting>
  /* add objects to the main pipeline */
  gst_bin_add (GST_BIN (pipeline), disksrc);
  gst_bin_add (GST_BIN (pipeline), parse);
  gst_bin_add (GST_BIN (pipeline), decoder);
  gst_bin_add (GST_BIN (pipeline), audiosink);
    </programlisting>

    <para>
      We connect the different pads of the elements together like this:
    </para>
    <programlisting>
  /* connect src to sink */
  gst_pad_connect (gst_element_get_pad (disksrc, "src"),
                   gst_element_get_pad (parse, "sink"));
  gst_pad_connect (gst_element_get_pad (parse, "src"),
                   gst_element_get_pad (decoder, "sink"));
  gst_pad_connect (gst_element_get_pad (decoder, "src"),
                   gst_element_get_pad (audiosink, "sink"));
    </programlisting>
    
    <para>
      We now have a created a complete pipeline.  We can visualise the
      pipeline as follows:
    </para>
    <figure float="1" id="sec-hello-img">
      <title>The Hello world pipeline</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="images/hello-world" format="PNG">
        </imageobject>
      </mediaobject>  

    </figure>

    <para>
     Everything is now set up to start the streaming. We use the following
     statements to change the state of the pipeline:
    </para>
    <programlisting>
  /* start playing */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);

    </programlisting>
    <note>
      <para>
        <application>GStreamer</application> will take care of the READY and PAUSED state for y
	ou when going from NULL to PLAYING.
      </para>
    </note>

    <para>
      Since we do not use threads, nothing will happen yet. We manually have to
      call gst_bin_iterate() to execute one iteration of the pipeline. 
    </para>
    <programlisting>
  while (gst_bin_iterate (GST_BIN (pipeline)));
    </programlisting>
    <para>
      The gst_bin_iterate() function will return TRUE as long as something interesting
      happended inside the pipeline. When the end-of-file has been reached the _iterate 
      function will return FALSE and we can end the loop.
    </para>
    <programlisting>
  /* stop the pipeline */
  gst_element_set_state (pipeline, GST_STATE_NULL);

  gst_object_unref (GST_OBJECT (audiosink));
  gst_object_unref (GST_OBJECT (decoder));
  gst_object_unref (GST_OBJECT (disksrc));
  gst_object_unref (GST_OBJECT (pipeline));

  exit (0);
    </programlisting>
    <note>
      <para>
        don't forget to set the state of the pipeline to NULL. This will free
        all of the resources held by the elements.
      </para>
    </note>
    
  </sect1>

  <sect1>
    <title>compiling helloworld.c</title>
    <para>
      To compile the helloworld example, use: 
    </para>
    <programlisting>
       gcc -Wall `gstreamer-config --cflags --libs` helloworld.c \
             -o helloworld 
    </programlisting>
    <para>
      This uses the program gstreamer-config, which comes with <application>GStreamer</application>. This program "knows" 
      what compiler switches are needed to compile programs that use <application>GStreamer</application>. 
      gstreamer-config --cflags will output a list of include
      directories for the compiler to look in, and gstreamer-config --libs will output the 
      list of libraries for the compiler to link with and the directories to find them 
      in. 
    </para>
    <para>
      You can run the example with (substitute helloworld.mp3 with you favorite MP3 file):
    </para>
    <programlisting>
      ./helloworld helloworld.mp3
    </programlisting>
  </sect1>

  <sect1>
    <title>conclusion</title>
    <para>
      This concludes our first example. As you see, setting up a pipeline
      is very lowlevel but powerfull. You will later in this manual how
      you can create a custom MP3 element with a more high level API.
    </para>
    <para>
      It should be clear from the example that we can very easily replace the 
      disksrc element with an httpsrc, giving you instant network streaming.
      An element could be build to handle icecast connections, for example.
    </para>
    <para>
      We can also choose to use another type of sink instead of the audiosink.
      We could use a disksink to write the raw samples to a file, for example.
      It should also be clear that inserting filters, like a stereo effect,
      into the pipeline is not that hard to do. The most important thing is
      that you can reuse allready existing elements.
    </para>
    

  </sect1>
</chapter>