2004-01-28 15:08:17 +00:00
|
|
|
<chapter id="chapter-hello-world">
|
2000-08-18 20:38:54 +00:00
|
|
|
<title>Your first application</title>
|
|
|
|
<para>
|
2002-09-08 21:17:16 +00:00
|
|
|
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,
|
2002-09-14 14:13:34 +00:00
|
|
|
pausing and stopping the pipeline.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
|
2004-01-28 15:08:17 +00:00
|
|
|
<sect1 id="section-hello-world">
|
2000-08-18 20:38:54 +00:00
|
|
|
<title>Hello world</title>
|
2002-04-07 23:32:16 +00:00
|
|
|
<para>
|
2002-09-08 21:17:16 +00:00
|
|
|
We will create a simple first application, a complete MP3 player, using
|
|
|
|
standard <application>GStreamer</application> components. The player
|
2002-09-14 14:13:34 +00:00
|
|
|
will read from a file that is given as the first argument to the program.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<programlisting>
|
2002-09-15 13:15:18 +00:00
|
|
|
/* example-begin helloworld.c */
|
2000-08-18 20:38:54 +00:00
|
|
|
#include <gst/gst.h>
|
|
|
|
|
2001-01-04 23:35:50 +00:00
|
|
|
int
|
|
|
|
main (int argc, char *argv[])
|
2000-08-18 20:38:54 +00:00
|
|
|
{
|
2002-03-31 15:28:51 +00:00
|
|
|
GstElement *pipeline, *filesrc, *decoder, *audiosink;
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2001-01-04 23:35:50 +00:00
|
|
|
gst_init(&argc, &argv);
|
|
|
|
|
2000-08-18 20:38:54 +00:00
|
|
|
if (argc != 2) {
|
2002-09-15 13:15:18 +00:00
|
|
|
g_print ("usage: %s <mp3 filename>\n", argv[0]);
|
2001-01-04 23:35:50 +00:00
|
|
|
exit (-1);
|
2000-08-18 20:38:54 +00:00
|
|
|
}
|
|
|
|
|
2001-06-15 21:46:57 +00:00
|
|
|
/* create a new pipeline to hold the elements */
|
|
|
|
pipeline = gst_pipeline_new ("pipeline");
|
2000-08-18 20:38:54 +00:00
|
|
|
|
|
|
|
/* create a disk reader */
|
2002-04-11 20:35:18 +00:00
|
|
|
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
2002-01-06 04:26:37 +00:00
|
|
|
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2002-03-31 15:28:51 +00:00
|
|
|
/* now it's time to get the decoder */
|
2002-04-11 20:35:18 +00:00
|
|
|
decoder = gst_element_factory_make ("mad", "decoder");
|
2001-01-04 23:35:50 +00:00
|
|
|
|
2000-08-18 20:38:54 +00:00
|
|
|
/* and an audio sink */
|
2002-04-11 20:35:18 +00:00
|
|
|
audiosink = gst_element_factory_make ("osssink", "play_audio");
|
2000-08-18 20:38:54 +00:00
|
|
|
|
|
|
|
/* add objects to the main pipeline */
|
2002-04-07 23:32:16 +00:00
|
|
|
gst_bin_add_many (GST_BIN (pipeline), filesrc, decoder, audiosink, NULL);
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2003-01-09 14:15:37 +00:00
|
|
|
/* link src to sink */
|
|
|
|
gst_element_link_many (filesrc, decoder, audiosink, NULL);
|
2001-01-04 23:35:50 +00:00
|
|
|
|
2000-08-18 20:38:54 +00:00
|
|
|
/* start playing */
|
2001-06-15 21:46:57 +00:00
|
|
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2001-06-15 21:46:57 +00:00
|
|
|
while (gst_bin_iterate (GST_BIN (pipeline)));
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2001-06-15 21:46:57 +00:00
|
|
|
/* stop the pipeline */
|
|
|
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2001-06-15 21:46:57 +00:00
|
|
|
/* we don't need a reference to these objects anymore */
|
|
|
|
gst_object_unref (GST_OBJECT (pipeline));
|
2002-04-07 23:32:16 +00:00
|
|
|
/* unreffing the pipeline unrefs the contained elements as well */
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2001-01-04 23:35:50 +00:00
|
|
|
exit (0);
|
2000-08-18 20:38:54 +00:00
|
|
|
}
|
2002-09-15 13:15:18 +00:00
|
|
|
/* example-end helloworld.c */
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Let's go through this example step by step.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2002-09-15 13:15:18 +00:00
|
|
|
The first thing you have to do is to include the standard
|
|
|
|
<application>GStreamer</application> headers and
|
2000-08-18 20:38:54 +00:00
|
|
|
initialize the framework.
|
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
|
|
|
|
#include <gst/gst.h>
|
|
|
|
|
|
|
|
...
|
|
|
|
|
2001-01-04 23:35:50 +00:00
|
|
|
int
|
|
|
|
main (int argc, char *argv[])
|
2000-08-18 20:38:54 +00:00
|
|
|
{
|
|
|
|
...
|
2001-01-04 23:35:50 +00:00
|
|
|
gst_init(&argc, &argv);
|
2000-08-18 20:38:54 +00:00
|
|
|
...
|
|
|
|
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
<para>
|
2002-09-14 14:13:34 +00:00
|
|
|
We are going to create three elements and one pipeline. Since all
|
2004-07-27 15:01:10 +00:00
|
|
|
elements share the same base type, <ulink type="http"
|
|
|
|
url="../../gstreamer/html/GstElement.html"><classname>GstElement</classname></ulink>,
|
2002-09-14 14:13:34 +00:00
|
|
|
we can define them as:
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
...
|
2002-03-31 15:28:51 +00:00
|
|
|
GstElement *pipeline, *filesrc, *decoder, *audiosink;
|
2000-08-18 20:38:54 +00:00
|
|
|
...
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
<para>
|
2002-09-08 21:17:16 +00:00
|
|
|
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
|
2002-09-14 14:13:34 +00:00
|
|
|
elements we are going to pack into it.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
2001-06-15 21:46:57 +00:00
|
|
|
/* create a new pipeline to hold the elements */
|
|
|
|
pipeline = gst_pipeline_new ("pipeline");
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
2001-01-04 23:35:50 +00:00
|
|
|
<para>
|
2002-09-14 14:13:34 +00:00
|
|
|
We use the standard constructor for a pipeline: gst_pipeline_new ().
|
2001-01-04 23:35:50 +00:00
|
|
|
</para>
|
2000-08-18 20:38:54 +00:00
|
|
|
|
|
|
|
<para>
|
|
|
|
We then create a disk source element. The disk source element is able to
|
2001-07-07 11:34:54 +00:00
|
|
|
read from a file. We use the standard GObject property mechanism to set
|
2000-08-18 20:38:54 +00:00
|
|
|
a property of the element: the file to read from.
|
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
/* create a disk reader */
|
2002-04-11 20:35:18 +00:00
|
|
|
filesrc = gst_element_factory_make ("filesrc", "disk_source");
|
2002-01-06 04:26:37 +00:00
|
|
|
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
<note>
|
|
|
|
<para>
|
2002-01-06 04:26:37 +00:00
|
|
|
You can check if the filesrc != NULL to verify the creation of the
|
2000-08-18 20:38:54 +00:00
|
|
|
disk source element.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
|
|
|
<para>
|
2002-03-31 15:28:51 +00:00
|
|
|
We now create the MP3 decoder element. This assumes that the 'mad' plugin
|
|
|
|
is installed on the system where this application is executed.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
2002-04-07 23:32:16 +00:00
|
|
|
/* now it's time to get the decoder */
|
2002-04-11 20:35:18 +00:00
|
|
|
decoder = gst_element_factory_make ("mad", "decoder");
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
<para>
|
2002-04-11 20:35:18 +00:00
|
|
|
gst_element_factory_make() takes two arguments: a string that will
|
2000-08-18 20:38:54 +00:00
|
|
|
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
|
2001-06-15 21:46:57 +00:00
|
|
|
bin/pipeline.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Finally we create our audio sink element. This element will be able
|
2002-09-14 14:13:34 +00:00
|
|
|
to play back the audio using OSS.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
/* and an audio sink */
|
2004-05-08 11:18:48 +00:00
|
|
|
audiosink = gst_element_factory_make ("osssink", "play_audio");
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
<para>
|
2001-06-15 21:46:57 +00:00
|
|
|
We then add the elements to the pipeline.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
/* add objects to the main pipeline */
|
2002-04-07 23:32:16 +00:00
|
|
|
gst_bin_add_many (GST_BIN (pipeline), filesrc, decoder, audiosink, NULL);
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
<para>
|
2003-01-09 14:15:37 +00:00
|
|
|
We link the different pads of the elements together like this:
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
2003-01-09 14:15:37 +00:00
|
|
|
/* link src to sink */
|
|
|
|
gst_element_link_many (filesrc, decoder, audiosink, NULL);
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
<para>
|
2004-07-16 00:43:57 +00:00
|
|
|
We now have created a complete pipeline. We can visualise the
|
2000-08-18 20:38:54 +00:00
|
|
|
pipeline as follows:
|
|
|
|
</para>
|
2004-01-28 15:08:17 +00:00
|
|
|
<figure float="1" id="section-hello-img">
|
2003-10-09 12:42:49 +00:00
|
|
|
<title>The "hello world" pipeline</title>
|
2001-12-13 15:24:00 +00:00
|
|
|
<mediaobject>
|
|
|
|
<imageobject>
|
2003-10-08 14:34:09 +00:00
|
|
|
<imagedata fileref="images/hello-world.ℑ" format="&IMAGE;" />
|
2001-12-13 15:24:00 +00:00
|
|
|
</imageobject>
|
|
|
|
</mediaobject>
|
|
|
|
|
2000-08-18 20:38:54 +00:00
|
|
|
</figure>
|
|
|
|
|
|
|
|
<para>
|
2003-10-09 12:42:49 +00:00
|
|
|
Everything is now set up to start streaming. We use the following
|
2001-06-15 21:46:57 +00:00
|
|
|
statements to change the state of the pipeline:
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
/* start playing */
|
2001-06-15 21:46:57 +00:00
|
|
|
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
2000-08-18 20:38:54 +00:00
|
|
|
|
|
|
|
</programlisting>
|
|
|
|
<note>
|
|
|
|
<para>
|
2002-03-31 15:28:51 +00:00
|
|
|
<application>GStreamer</application> will take care of the READY and PAUSED state for
|
|
|
|
you when going from NULL to PLAYING.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
|
|
|
<para>
|
2002-09-14 14:13:34 +00:00
|
|
|
Since we do not use threads, nothing will happen yet. We have to
|
2001-06-15 21:46:57 +00:00
|
|
|
call gst_bin_iterate() to execute one iteration of the pipeline.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
2001-06-15 21:46:57 +00:00
|
|
|
while (gst_bin_iterate (GST_BIN (pipeline)));
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
<para>
|
2002-09-08 21:17:16 +00:00
|
|
|
The gst_bin_iterate() function will return TRUE as long as something
|
2002-09-14 14:13:34 +00:00
|
|
|
interesting happened inside the pipeline. When the end-of-file has been
|
2002-09-08 21:17:16 +00:00
|
|
|
reached the _iterate function will return FALSE and we can end the loop.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
2001-06-15 21:46:57 +00:00
|
|
|
/* stop the pipeline */
|
|
|
|
gst_element_set_state (pipeline, GST_STATE_NULL);
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2001-06-15 21:46:57 +00:00
|
|
|
gst_object_unref (GST_OBJECT (pipeline));
|
2000-08-18 20:38:54 +00:00
|
|
|
|
2001-01-04 23:35:50 +00:00
|
|
|
exit (0);
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
<note>
|
|
|
|
<para>
|
2002-04-07 23:32:16 +00:00
|
|
|
Don't forget to set the state of the pipeline to NULL. This will free
|
2000-08-18 20:38:54 +00:00
|
|
|
all of the resources held by the elements.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
|
|
|
</sect1>
|
|
|
|
|
2004-01-28 15:08:17 +00:00
|
|
|
<sect1 id="section-hello-world-compile">
|
2002-04-07 23:32:16 +00:00
|
|
|
<title>Compiling helloworld.c</title>
|
2000-08-18 20:38:54 +00:00
|
|
|
<para>
|
|
|
|
To compile the helloworld example, use:
|
|
|
|
</para>
|
|
|
|
<programlisting>
|
2003-10-08 18:21:41 +00:00
|
|
|
gcc -Wall `pkg-config gstreamer-&GST_MAJORMINOR; --cflags --libs` helloworld.c \
|
2000-09-09 16:36:10 +00:00
|
|
|
-o helloworld
|
2000-08-18 20:38:54 +00:00
|
|
|
</programlisting>
|
|
|
|
<para>
|
2002-09-15 13:57:34 +00:00
|
|
|
We use pkg-config to get the compiler flags needed to compile
|
|
|
|
this application. Make sure to have your PKG_CONFIG_PATH environment
|
|
|
|
variable set to the correct location if you are building this
|
|
|
|
application against the uninstalled location.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<para>
|
2002-09-15 13:57:34 +00:00
|
|
|
You can run the example with
|
|
|
|
(substitute helloworld.mp3 with you favorite MP3 file):
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
./helloworld helloworld.mp3
|
|
|
|
</programlisting>
|
|
|
|
</sect1>
|
|
|
|
|
2004-01-28 15:08:17 +00:00
|
|
|
<sect1 id="section-hello-world-conclusion">
|
2002-04-07 23:32:16 +00:00
|
|
|
<title>Conclusion</title>
|
2000-08-18 20:38:54 +00:00
|
|
|
<para>
|
|
|
|
This concludes our first example. As you see, setting up a pipeline
|
2002-09-14 14:13:34 +00:00
|
|
|
is very low-level but powerful. You will see later in this manual how
|
|
|
|
you can create a custom MP3 element with a higher-level API.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<para>
|
2002-09-08 21:17:16 +00:00
|
|
|
It should be clear from the example that we can very easily replace the
|
2004-07-16 00:43:57 +00:00
|
|
|
filesrc element with the gnomevfssrc element, giving you instant streaming
|
|
|
|
from any gnomevfs URL.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
We can also choose to use another type of sink instead of the audiosink.
|
2004-05-02 23:30:31 +00:00
|
|
|
We could use a filesink to write the raw samples to a file, for example.
|
2000-08-18 20:38:54 +00:00
|
|
|
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
|
2002-04-07 23:32:16 +00:00
|
|
|
that you can reuse already existing elements.
|
2000-08-18 20:38:54 +00:00
|
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|