diff --git a/docs/manual/autoplugging.sgml b/docs/manual/autoplugging.sgml index 6a73b343ff..01f9852cc8 100644 --- a/docs/manual/autoplugging.sgml +++ b/docs/manual/autoplugging.sgml @@ -90,10 +90,59 @@ - A complete autoplugging example + Using the <classname>GstAutoplugCache</classname> element - We will create and explain how a complete media player can be built with the - autoplugger. + The GstAutoplugCache element is used to cache the + media stream when performing typedetection. As we have have seen in the + previous chapter (typedetection), the type typefind function consumes a + buffer to determine the media type of it. After we have set up the pipeline + to play the media stream we should be able to 'replay' the previous buffer(s). + This is where the autoplugcache is used for. + + + The basic usage pattern for the autoplugcache in combination with the typefind + element is like this: + + + + Add the autoplugcache element to a bin and connect the sink pad to the src + pad of an element with unkown caps. + + + + + Connect the src pad of the autoplugcache to the sink pad of the typefind + element. + + + + + Loop the pipeline until the typefind element has found a type. + + + + + Remove the typefind element and add the plugins needed to play back the discovered + media type to the autoplugcache src pad. + + + + + Reset the cache to start playback of the cached data. Connect to the + "cache_empty" signal. + + + + + In the cache_empty signal callback function, remove the autoplugcache and + reconnect the pads. + + + + + + In the next chapter we will create a new version of our helloworld exaple using the + autoplugger, the autoplugcache and the typefind element. diff --git a/docs/manual/debugging.sgml b/docs/manual/debugging.sgml index aae503c5ab..34c92060f3 100644 --- a/docs/manual/debugging.sgml +++ b/docs/manual/debugging.sgml @@ -26,6 +26,12 @@ Sets the mask for the info output. + + + + Sets the mask for the info *and* the debug output. + + @@ -74,10 +80,13 @@ Mask (to be OR'ed) info/debug FLAGS 0x00010000 / PIPELINE 0x00020000 / PLUGIN_LOADING 0x00040000 / PLUGIN_ERRORS -0x00080000 / PROPERTIES -0x00100000 / THREAD -0x00200000 / TYPES -0x00400000 / XML +0x00080000 / PLUGIN_INFO +0x00100000 / PROPERTIES +0x00200000 / THREAD +0x00400000 / TYPES +0x00800000 / XML +0x01000000 / NEGOTIATION +0x02000000 / REFCOUNTING diff --git a/docs/manual/gstreamer-manual.sgml b/docs/manual/gstreamer-manual.sgml index de3bf958f2..7c718c155d 100644 --- a/docs/manual/gstreamer-manual.sgml +++ b/docs/manual/gstreamer-manual.sgml @@ -131,9 +131,6 @@ &FACTORIES; - &AUTOPLUGGING; - - &HELLOWORLD2; @@ -160,6 +157,10 @@ &TYPEDETECTION; + &AUTOPLUGGING; + + &HELLOWORLD2; + &UTILITY; diff --git a/docs/manual/helloworld2.sgml b/docs/manual/helloworld2.sgml index b10fa0b39d..13e143a330 100644 --- a/docs/manual/helloworld2.sgml +++ b/docs/manual/helloworld2.sgml @@ -1,153 +1,246 @@ Your second application - In the previous chapter we created a first version of the helloworld + In a previous chapter we created a first version of the helloworld application. We then explained a better way of creating the elements - using factories identified by MIME types. - - - In this chapter we will introduce you to autoplugging. Using the MIME - types of the elements GStreamer can automatically create a pipeline - for you. + using factories identified by MIME types and the autoplugger. - Autoplugging helloworld (outdated) + Autoplugging helloworld We will create a second version of the helloworld application using - autoplugging. Its source code is considerably easier to write and - it can also handle many more data types. + autoplugging. Its source code is a bit more complicated but + it can handle many more data types. + + + We start by creating the main() of our program: - #include <gst/gst.h> -static gboolean playing; - -/* eos will be called when the src element has an end of stream */ -void -eos (GstSrc *src) -{ - g_print ("have eos, quitting\n"); - - playing = FALSE; -} +static void gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline); +static void gst_play_cache_empty (GstElement *element, GstElement *pipeline); int main (int argc, char *argv[]) { - GstElement *disksrc, *audiosink; + GstElement *disksrc; GstElement *pipeline; - - if (argc != 2) { - g_print ("usage: %s <filename>\n", argv[0]); - exit (-1); - } + GstElement *autobin; + GstElement *typefind; + GstElement *cache; gst_init (&argc, &argv); - /* create a new bin to hold the elements */ + 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"); + g_assert (pipeline != NULL); /* create a disk reader */ disksrc = gst_elementfactory_make ("disksrc", "disk_source"); + g_assert (disksrc != NULL); g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL); - g_signal_connectc (G_OBJECT (disksrc), "eos", - G_CALLBACK (eos), NULL, FALSE); + gst_bin_add (GST_BIN (pipeline), disksrc); - /* and an audio sink */ - audiosink = gst_elementfactory_make ("audiosink", "play_audio"); + autobin = gst_bin_new ("autobin"); + cache = gst_elementfactory_make ("autoplugcache", "cache"); + g_signal_connectc (G_OBJECT (cache), "cache_empty", + G_CALLBACK (gst_play_cache_empty), pipeline, FALSE); - /* add objects to the main pipeline */ - gst_pipeline_add_src (GST_PIPELINE (pipeline), disksrc); - gst_pipeline_add_sink (GST_PIPELINE (pipeline), audiosink); + typefind = gst_elementfactory_make ("typefind", "typefind"); + g_signal_connectc (G_OBJECT (typefind), "have_type", + G_CALLBACK (gst_play_have_type), pipeline, FALSE); + gst_bin_add (GST_BIN (autobin), cache); + gst_bin_add (GST_BIN (autobin), typefind); - if (!gst_pipeline_autoplug (GST_PIPELINE (pipeline))) { - g_print ("unable to handle stream\n"); - exit (-1); - } + gst_element_connect (cache, "src", typefind, "sink"); + gst_element_add_ghost_pad (autobin, gst_element_get_pad (cache, "sink"), "sink"); + + gst_bin_add (GST_BIN( pipeline), autobin); + gst_element_connect (disksrc, "src", autobin, "sink"); /* start playing */ - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); + gst_element_set_state( GST_ELEMENT (pipeline), GST_STATE_PLAYING); - playing = TRUE; + while (gst_bin_iterate (GST_BIN (pipeline))); - while (playing) { - gst_bin_iterate (GST_BIN (pipeline)); - } - - /* stop the bin */ + /* stop the pipeline */ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL); - gst_pipeline_destroy (pipeline); + gst_object_unref (GST_OBJECT (pipeline)); - exit (0); + exit(0); } - - - First of all, we do not use any mpg123 or mp3parse element in this example. - In fact, we only specify a source element and a sink element and add them - to a pipeline. + We start by constructing a 'disksrc' element and an 'autobin' element that + holds the autoplugcache and the typefind element. + + + We attach the "cache_empty" signal to gst_play_cache_empty and the + "have_type" to our gst_play_have_type function (defined below). - - The most interesting change however is the following: - +static void +gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline) +{ + GstElement *osssink; + GstElement *new_element; + GstAutoplug *autoplug; + GstElement *autobin; + GstElement *disksrc; + GstElement *cache; - ... - if (!gst_pipeline_autoplug (pipeline)) { - g_print ("unable to handle stream\n"); + GST_DEBUG (0,"GstPipeline: play have type\n"); + + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + disksrc = gst_bin_get_by_name (GST_BIN (pipeline), "disk_source"); + autobin = gst_bin_get_by_name (GST_BIN (pipeline), "autobin"); + cache = gst_bin_get_by_name (GST_BIN (autobin), "cache"); + + // disconnect the typefind from the pipeline and remove it + gst_element_disconnect (cache, "src", typefind, "sink"); + gst_bin_remove (GST_BIN (autobin), typefind); + + /* and an audio sink */ + osssink = gst_elementfactory_make("osssink", "play_audio"); + g_assert(osssink != NULL); + + autoplug = gst_autoplugfactory_make ("staticrender"); + g_assert (autoplug != NULL); + + new_element = gst_autoplug_to_renderers (autoplug, + caps, + osssink, + NULL); + + if (!new_element) { + g_print ("could not autoplug, no suitable codecs found...\n"); exit (-1); } - ... + gst_element_set_name (new_element, "new_element"); + + gst_bin_add (GST_BIN (autobin), new_element); + + g_object_set (G_OBJECT (cache), "reset", TRUE, NULL); + + gst_element_connect (cache, "src", new_element, "sink"); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); +} + + + The _have_type function first sets the pipeline to the PAUSED state so that + it can safely modify the pipeline. It then finds the elements it is going to + manipulate in the pipeline with: + + + disksrc = gst_bin_get_by_name (GST_BIN (pipeline), "disk_source"); + autobin = gst_bin_get_by_name (GST_BIN (pipeline), "autobin"); + cache = gst_bin_get_by_name (GST_BIN (autobin), "cache"); - This piece of code does all the magic. + Now we have a handle to the elements we are going to manipulate in + the next step. + + We don't need the typefind element anymore so we remove it from the pipeline: + + + // disconnect the typefind from the pipeline and remove it + gst_element_disconnect (cache, "src", typefind, "sink"); + gst_bin_remove (GST_BIN (autobin), typefind); + - - - - The pipeline will try to connect the src and the sink element. - - - - - Since the source has no type, a typedetection will be started on - the source element. - - - - - The best set of elements that connect the MIME type of the source - element to the MIME type of the sink are found. - - - - - The elements are added to the pipeline and their pads are connected. - - - + Our next step is to construct an element that can play the type we just + detected. We are going to use the autoplugger to create an element that + connects the type to an osssink. We add the new element to our + autobin. - - After this autoplugging, the pipeline is ready to play. Remember that this - pipeline will be able to playback all of the media types for which an - appropriate plugin exists since the autoplugging is all done using MIME - types. - + + /* and an audio sink */ + osssink = gst_elementfactory_make("osssink", "play_audio"); + g_assert(osssink != NULL); + + autoplug = gst_autoplugfactory_make ("staticrender"); + g_assert (autoplug != NULL); + + new_element = gst_autoplug_to_renderers (autoplug, + caps, + osssink, + NULL); + + if (!new_element) { + g_print ("could not autoplug, no suitable codecs found...\n"); + exit (-1); + } + + gst_element_set_name (new_element, "new_element"); + + gst_bin_add (GST_BIN (autobin), new_element); + - If you really want, you can use the GSteamer components to do the - autoplugging yourself. We will cover this topic in the dynamic pipeline chapter. + Our next step is to reset the cache so that the buffers used by the + typefind element are fed into the new element we just created. We reset + the cache by setting the "reset" property of the cache element to TRUE. + + + g_object_set (G_OBJECT (cache), "reset", TRUE, NULL); + + gst_element_connect (cache, "src", new_element, "sink"); + + + Finally we set the pipeline back to the playing state. At this point the + cache will replay the buffers. We will be notified when the cache is empty + with the gst_play_cache_empty callback function: + + + +static void +gst_play_cache_empty (GstElement *element, GstElement *pipeline) +{ + GstElement *autobin; + GstElement *disksrc; + GstElement *cache; + GstElement *new_element; + + fprintf (stderr, "have cache empty\n"); + + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + disksrc = gst_bin_get_by_name (GST_BIN (pipeline), "disk_source"); + autobin = gst_bin_get_by_name (GST_BIN (pipeline), "autobin"); + cache = gst_bin_get_by_name (GST_BIN (autobin), "cache"); + new_element = gst_bin_get_by_name (GST_BIN (autobin), "new_element"); + + gst_element_disconnect (disksrc, "src", cache, "sink"); + gst_element_disconnect (cache, "src", new_element, "sink"); + gst_bin_remove (GST_BIN (autobin), cache); + gst_element_connect (disksrc, "src", new_element, "sink"); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + fprintf (stderr, "done with cache_empty\n"); +} + + + + The cache empty function simply removes the autoplugcache element from + the pipeline and reconnects the disksrc to the autoplugged element. @@ -167,7 +260,7 @@ main (int argc, char *argv[]) You can also try to use an AVI or MPEG file as its input. Using autoplugging, GStreamer will automatically figure out how to handle the stream. Remember that only the audio part will be played because - we have only added an audiosink to the pipeline. + we have only added an osssink to the pipeline. ./helloworld2 mymovie.mpeg diff --git a/docs/manual/programs.sgml b/docs/manual/programs.sgml index d61cf4d009..d38cdb494e 100644 --- a/docs/manual/programs.sgml +++ b/docs/manual/programs.sgml @@ -101,52 +101,51 @@ video_00! (mpeg2dec ! videosink) - Note that the parser isn't capable of more complex pipelines yet, including - the VOB player above. The minor tweaks will be made post 0.1.0. + the VOB player above. The minor tweaks will be made post 0.2.1. You can also use the the parser in you own code. GStreamer - provides a function gst_parse_launch () that you can use to construt a pipeline. - The code of gstreamer-launch actually looks like: + provides a function gst_parse_launch () that you can use to construt a pipeline. + The following programs lets you create an mp3 pipeline using the gst_parse_launch () + function: #include <gst/gst.h> -#include <string.h> -#include <stdlib.h> -int -main (int argc, char *argv[]) +int +main (int argc, char *argv[]) { GstElement *pipeline; - char **argvn; - gchar *cmdline; - int i; + GstElement *disksrc; gst_init (&argc, &argv); - pipeline = gst_pipeline_new ("launch"); + if (argc != 2) { + g_print ("usage: %s <filename>\n", argv[0]); + return -1; + } + pipeline = gst_pipeline_new ("my_pipeline"); - // make a null-terminated version of argv - argvn = g_new0 (char *,argc); - memcpy (argvn, argv+1, sizeof (char*) * (argc-1)); - // join the argvs together - cmdline = g_strjoinv (" ", argvn); - // free the null-terminated argv - g_free (argvn); + gst_parse_launch ("disksrc[my_disksrc] ! mp3parse ! mpg123 ! osssink", GST_BIN (pipeline)); - gst_parse_launch (cmdline, pipeline); + disksrc = gst_bin_get_by_name (GST_BIN (pipeline), "my_disksrc"); + g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL); - fprintf(stderr,"RUNNING pipeline\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); - while (1) - gst_bin_iterate (GST_BIN (pipeline)); + while (gst_bin_iterate (GST_BIN (pipeline))); + + gst_element_set_state (pipeline, GST_STATE_NULL); return 0; } + + Note how we can retrieve the disksrc element from the constructed bin using the + element name. +