| <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, |
| pausing and stopping the pipeline. |
| </para> |
| |
| <sect1> |
| <title>Hello world</title> |
| <para> |
| We will create a simple first application, a complete MP3 player, using |
| standard <application>GStreamer</application> components. The player |
| will read from a file that is given as the first argument to the program. |
| </para> |
| |
| <programlisting> |
| |
| #include <gst/gst.h> |
| |
| int |
| main (int argc, char *argv[]) |
| { |
| GstElement *pipeline, *filesrc, *decoder, *audiosink; |
| |
| gst_init(&argc, &argv); |
| |
| if (argc != 2) { |
| g_print ("usage: %s <filename>\n", argv[0]); |
| exit (-1); |
| } |
| |
| /* create a new pipeline to hold the elements */ |
| pipeline = gst_pipeline_new ("pipeline"); |
| |
| /* create a disk reader */ |
| filesrc = gst_element_factory_make ("filesrc", "disk_source"); |
| g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); |
| |
| /* now it's time to get the decoder */ |
| decoder = gst_element_factory_make ("mad", "decoder"); |
| |
| /* and an audio sink */ |
| audiosink = gst_element_factory_make ("osssink", "play_audio"); |
| |
| /* add objects to the main pipeline */ |
| gst_bin_add_many (GST_BIN (pipeline), filesrc, decoder, audiosink, NULL); |
| |
| /* connect src to sink */ |
| gst_element_connect_many (filesrc, decoder, audiosink, NULL); |
| |
| /* 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 (pipeline)); |
| /* unreffing the pipeline unrefs the contained elements as well */ |
| |
| 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 <gst/gst.h> |
| |
| ... |
| |
| int |
| main (int argc, char *argv[]) |
| { |
| ... |
| gst_init(&argc, &argv); |
| ... |
| |
| </programlisting> |
| |
| <para> |
| We are going to create three elements and one pipeline. Since all |
| elements share the same base type, <classname>GstElement</classname>, |
| we can define them as: |
| </para> |
| <programlisting> |
| ... |
| GstElement *pipeline, *filesrc, *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 pack 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 (). |
| </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 */ |
| filesrc = gst_element_factory_make ("filesrc", "disk_source"); |
| g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); |
| </programlisting> |
| <note> |
| <para> |
| You can check if the filesrc != NULL to verify the creation of the |
| disk source element. |
| </para> |
| </note> |
| |
| <para> |
| We now create the MP3 decoder element. This assumes that the 'mad' plugin |
| is installed on the system where this application is executed. |
| </para> |
| <programlisting> |
| /* now it's time to get the decoder */ |
| decoder = gst_element_factory_make ("mad", "decoder"); |
| </programlisting> |
| <para> |
| gst_element_factory_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 play back the audio using OSS. |
| </para> |
| <programlisting> |
| /* and an audio sink */ |
| audiosink = gst_element_factory_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_many (GST_BIN (pipeline), filesrc, decoder, audiosink, NULL); |
| </programlisting> |
| |
| <para> |
| We connect the different pads of the elements together like this: |
| </para> |
| <programlisting> |
| /* connect src to sink */ |
| gst_element_connect_many (filesrc, decoder, audiosink, NULL); |
| </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.&magic;" format="&magic;" /> |
| </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 |
| you when going from NULL to PLAYING. |
| </para> |
| </note> |
| |
| <para> |
| Since we do not use threads, nothing will happen yet. We 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 happened 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 (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 `pkg-config gstreamer --cflags --libs` helloworld.c \ |
| -o helloworld |
| </programlisting> |
| <para> |
| 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. |
| </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 low-level but powerful. You will see later in this manual how |
| you can create a custom MP3 element with a higher-level API. |
| </para> |
| <para> |
| It should be clear from the example that we can very easily replace the |
| filesrc element with an httpsrc element, giving you instant network |
| streaming. An element could be built 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 already existing elements. |
| </para> |
| </sect1> |
| </chapter> |