Your first application This chapter describes the most rudimentary aspects of a GStreamer application, including initializing the libraries, creating elements, packing them into a pipeline and playing, pause and stop the pipeline. Hello world We will create a simple first application. In fact it will be a complete MP3 player, using standard GStreamer components. The player will read from a file that is given as the first argument of the program. #include <gst/gst.h> int main (int argc, char *argv[]) { GstElement *pipeline, *disksrc, *parse, *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 */ 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); } Let's go through this example step by step. The first thing you have to do is to include the standard GStreamer headers and initialize the framework. #include <gst/gst.h> ... int main (int argc, char *argv[]) { ... gst_init(&argc, &argv); ... We are going to create 4 elements and one pipeline. Since all objects are in fact elements, we can define them as: ... GstElement *pipeline, *disksrc, *parse, *decoder, *audiosink; ... 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. /* create a new pipeline to hold the elements */ pipeline = gst_pipeline_new ("pipeline"); We use the standard constructor for a pipeline: gst_pipeline_new ("name"). 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. /* create a disk reader */ disksrc = gst_elementfactory_make ("disksrc", "disk_source"); g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL); You can check if the disksrc != NULL to verify the creation of the disk source element. We now create the MP3 decoder element. GStreamer 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. /* now it's time to get the parser */ parse = gst_elementfactory_make ("mp3parse", "parse"); decoder = gst_elementfactory_make ("mpg123", "decoder"); 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. Finally we create our audio sink element. This element will be able to playback the audio using OSS. /* and an audio sink */ audiosink = gst_elementfactory_make ("audiosink", "play_audio"); We then add the elements to the pipeline. /* 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); We connect the different pads of the elements together like this: /* 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")); We now have a created a complete pipeline. We can visualise the pipeline as follows:
The Hello world pipeline
Everything is now set up to start the streaming. We use the following statements to change the state of the pipeline: /* start playing */ gst_element_set_state (pipeline, GST_STATE_PLAYING); GStreamer will take care of the READY and PAUSED state for y ou when going from NULL to PLAYING. 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. while (gst_bin_iterate (GST_BIN (pipeline))); 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. /* 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); don't forget to set the state of the pipeline to NULL. This will free all of the resources held by the elements.
compiling helloworld.c To compile the helloworld example, use: gcc -Wall `gstreamer-config --cflags --libs` helloworld.c \ -o helloworld This uses the program gstreamer-config, which comes with GStreamer. This program "knows" what compiler switches are needed to compile programs that use GStreamer. 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. You can run the example with (substitute helloworld.mp3 with you favorite MP3 file): ./helloworld helloworld.mp3 conclusion 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. 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. 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.