+2004-12-15 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+
+ * docs/manual/advanced-autoplugging.xml:
+ * docs/manual/advanced-clocks.xml:
+ * docs/manual/advanced-interfaces.xml:
+ * docs/manual/advanced-metadata.xml:
+ * docs/manual/advanced-position.xml:
+ * docs/manual/advanced-schedulers.xml:
+ * docs/manual/advanced-threads.xml:
+ * docs/manual/appendix-gnome.xml:
+ * docs/manual/appendix-programs.xml:
+ * docs/manual/appendix-quotes.xml:
+ * docs/manual/autoplugging.xml:
+ * docs/manual/basics-bins.xml:
+ * docs/manual/basics-data.xml:
+ * docs/manual/basics-elements.xml:
+ * docs/manual/basics-helloworld.xml:
+ * docs/manual/basics-init.xml:
+ * docs/manual/basics-pads.xml:
+ * docs/manual/basics-plugins.xml:
+ * docs/manual/bins-api.xml:
+ * docs/manual/bins.xml:
+ * docs/manual/buffers-api.xml:
+ * docs/manual/buffers.xml:
+ * docs/manual/clocks.xml:
+ * docs/manual/components.xml:
+ * docs/manual/cothreads.xml:
+ * docs/manual/debugging.xml:
+ * docs/manual/dparams-app.xml:
+ * docs/manual/dynamic.xml:
+ * docs/manual/elements-api.xml:
+ * docs/manual/elements.xml:
+ * docs/manual/factories.xml:
+ * docs/manual/gnome.xml:
+ * docs/manual/goals.xml:
+ * docs/manual/helloworld.xml:
+ * docs/manual/helloworld2.xml:
+ * docs/manual/highlevel-components.xml:
+ * docs/manual/highlevel-xml.xml:
+ * docs/manual/init-api.xml:
+ * docs/manual/intro-basics.xml:
+ * docs/manual/intro-motivation.xml:
+ * docs/manual/intro-preface.xml:
+ * docs/manual/intro.xml:
+ * docs/manual/links-api.xml:
+ * docs/manual/links.xml:
+ * docs/manual/manual.xml:
+ * docs/manual/motivation.xml:
+ * docs/manual/pads-api.xml:
+ * docs/manual/pads.xml:
+ * docs/manual/plugins-api.xml:
+ * docs/manual/plugins.xml:
+ * docs/manual/programs.xml:
+ * docs/manual/queues.xml:
+ * docs/manual/quotes.xml:
+ * docs/manual/schedulers.xml:
+ * docs/manual/states-api.xml:
+ * docs/manual/states.xml:
+ * docs/manual/threads.xml:
+ * docs/manual/typedetection.xml:
+ * docs/manual/win32.xml:
+ * docs/manual/xml.xml:
+ Try 2. This time, include a short preface as a "general
+ introduction", also add code blocks around all code samples
+ so they get compiled. We still need a way to tell readers
+ the filename of the code sample. In some cases, don't show
+ all code in the documentation, but do include it in the generated
+ code. This allows for focussing on specific bits in the docs,
+ while still having a full test application available.
+ * examples/manual/Makefile.am:
+ Fix up examples for new ADM. Add several of the new examples that
+ were either added or were missing from the build system.
+ * examples/manual/extract.pl:
+ Allow nameless blocks.
+
2004-12-15 Thomas Vander Stichele <thomas at apestaart dot org>
* docs/manual/elements-api.xml:
-<chapter id="chapter-factories">
- <title>More on factories</title>
+<chapter id="chapter-autoplugging">
+ <title>Putting together a pipeline</title>
<para>
The small application we created in the previous chapter used the
concept of a factory to create the elements. In this chapter we will
<para>
This function will return 0 if the extension was not known.
</para>
- <para>
- For more information, see <xref linkend="chapter-autoplug"/>.
- </para>
</sect2>
</sect1>
</para>
</sect1>
+
+ <sect1 id="chapter-dynamic">
+ <title>Dynamic pipelines</title>
+ <para>
+ In this chapter we will see how you can create a dynamic pipeline. A
+ dynamic pipeline is a pipeline that is updated or created while data
+ is flowing through it. We will create a partial pipeline first and add
+ more elements while the pipeline is playing. Dynamic pipelines cause
+ all sorts of scheduling issues and will remain a topic of research for
+ a long time in GStreamer.
+ </para>
+ <para>
+ We will show how to create an MPEG1 video player using dynamic pipelines.
+ As you have seen in the pad section, we can attach a signal to an element
+ when a pad is created. We will use this to create our MPEG1 player.
+ </para>
+
+ <para>
+ We'll start with a simple main function:
+ </para>
+ <programlisting>
+<!-- example-begin dynamic.c -->
+#include <string.h>
+#include <gst/gst.h>
+
+void
+eof (GstElement *src)
+{
+ g_print ("have eos, quitting\n");
+ exit (0);
+}
+
+gboolean
+idle_func (gpointer data)
+{
+ gst_bin_iterate (GST_BIN (data));
+ return TRUE;
+}
+
+void
+new_pad_created (GstElement *parse, GstPad *pad, GstElement *pipeline)
+{
+ GstElement *decode_video = NULL;
+ GstElement *decode_audio, *play, *color, *show;
+ GstElement *audio_queue, *video_queue;
+ GstElement *audio_thread, *video_thread;
+
+ g_print ("***** a new pad %s was created\n", gst_pad_get_name (pad));
+
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
+
+ /* link to audio pad */
+ if (strncmp (gst_pad_get_name (pad), "audio_", 6) == 0) {
+
+ /* construct internal pipeline elements */
+ decode_audio = gst_element_factory_make ("mad", "decode_audio");
+ g_return_if_fail (decode_audio != NULL);
+ play = gst_element_factory_make ("osssink", "play_audio");
+ g_return_if_fail (play != NULL);
+
+ /* create the thread and pack stuff into it */
+ audio_thread = gst_thread_new ("audio_thread");
+ g_return_if_fail (audio_thread != NULL);
+
+ /* construct queue and link everything in the main pipeline */
+ audio_queue = gst_element_factory_make ("queue", "audio_queue");
+ g_return_if_fail (audio_queue != NULL);
+
+ gst_bin_add_many (GST_BIN (audio_thread),
+ audio_queue, decode_audio, play, NULL);
+
+ /* set up pad links */
+ gst_element_add_ghost_pad (audio_thread,
+ gst_element_get_pad (audio_queue, "sink"),
+ "sink");
+ gst_element_link (audio_queue, decode_audio);
+ gst_element_link (decode_audio, play);
+
+ gst_bin_add (GST_BIN (pipeline), audio_thread);
+
+ gst_pad_link (pad, gst_element_get_pad (audio_thread, "sink"));
+
+ /* set up thread state and kick things off */
+ g_print ("setting to READY state\n");
+ gst_element_set_state (GST_ELEMENT (audio_thread), GST_STATE_READY);
+
+ }
+ else if (strncmp (gst_pad_get_name (pad), "video_", 6) == 0) {
+
+ /* construct internal pipeline elements */
+ decode_video = gst_element_factory_make ("mpeg2dec", "decode_video");
+ g_return_if_fail (decode_video != NULL);
+
+ color = gst_element_factory_make ("colorspace", "color");
+ g_return_if_fail (color != NULL);
+
+
+ show = gst_element_factory_make ("xvideosink", "show");
+ g_return_if_fail (show != NULL);
+
+ /* construct queue and link everything in the main pipeline */
+ video_queue = gst_element_factory_make ("queue", "video_queue");
+ g_return_if_fail (video_queue != NULL);
+
+ /* create the thread and pack stuff into it */
+ video_thread = gst_thread_new ("video_thread");
+ g_return_if_fail (video_thread != NULL);
+ gst_bin_add_many (GST_BIN (video_thread), video_queue,
+ decode_video, color, show, NULL);
+
+ /* set up pad links */
+ gst_element_add_ghost_pad (video_thread,
+ gst_element_get_pad (video_queue, "sink"),
+ "sink");
+ gst_element_link (video_queue, decode_video);
+ gst_element_link_many (decode_video, color, show, NULL);
+
+ gst_bin_add (GST_BIN (pipeline), video_thread);
+
+ gst_pad_link (pad, gst_element_get_pad (video_thread, "sink"));
+
+ /* set up thread state and kick things off */
+ g_print ("setting to READY state\n");
+ gst_element_set_state (GST_ELEMENT (video_thread), GST_STATE_READY);
+ }
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GstElement *pipeline, *src, *demux;
+
+ gst_init (&argc, &argv);
+
+ pipeline = gst_pipeline_new ("pipeline");
+ g_return_val_if_fail (pipeline != NULL, -1);
+
+ src = gst_element_factory_make ("filesrc", "src");
+ g_return_val_if_fail (src != NULL, -1);
+ if (argc < 2)
+ g_error ("Please specify a video file to play !");
+
+ g_object_set (G_OBJECT (src), "location", argv[1], NULL);
+
+ demux = gst_element_factory_make ("mpegdemux", "demux");
+ g_return_val_if_fail (demux != NULL, -1);
+
+ gst_bin_add_many (GST_BIN (pipeline), src, demux, NULL);
+
+ g_signal_connect (G_OBJECT (demux), "new_pad",
+ G_CALLBACK (new_pad_created), pipeline);
+
+ g_signal_connect (G_OBJECT (src), "eos",
+ G_CALLBACK (eof), NULL);
+
+ gst_element_link (src, demux);
+
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+
+ g_idle_add (idle_func, pipeline);
+
+ gst_main ();
+
+ return 0;
+}
+<!-- example-end dynamic.c -->
+ </programlisting>
+ <para>
+ We create two elements: a file source and an MPEG demuxer.
+ There's nothing special about this piece of code except for
+ the signal 'new_pad' that we linked to the mpegdemux
+ element using:
+ </para>
+ <programlisting>
+ g_signal_connect (G_OBJECT (demux), "new_pad",
+ G_CALLBACK (new_pad_created), pipeline);
+ </programlisting>
+ <para>
+ When an elementary stream has been detected in the system stream,
+ mpegdemux will create a new pad that will provide the data of the
+ elementary stream. A function 'new_pad_created' will be called when
+ the pad is created.
+ </para>
+ <para>
+ In the above example, we created new elements based on the name of
+ the newly created pad. We then added them to a new thread.
+ There are other possibilities to check the type of the pad, for
+ example by using the MIME type and the properties of the pad.
+ </para>
+ </sect1>
+
+
+ <sect1 id="chapter-typedetection">
+ <title>Type Detection</title>
+ <para>
+ Sometimes the capabilities of a pad are not specificied. The filesrc
+ element, for example, does not know what type of file it is reading. Before
+ you can attach an element to the pad of the filesrc, you need to determine
+ the media type in order to be able to choose a compatible element.
+ </para>
+ <para>
+ To solve this problem, a plugin can provide the <application>GStreamer</application>
+ core library with a type definition. The type definition
+ will contain the following information:
+ <itemizedlist>
+ <listitem>
+ <para>
+ The MIME type we are going to define.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ An optional string with a list of possible file extensions this
+ type usually is associated with. the list entries are separated with
+ a space. eg, ".mp3 .mpa .mpg".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ An optional typefind function.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ The typefind functions give a meaning to the MIME types that are used
+ in GStreamer. The typefind function is a function with the following definition:
+ </para>
+ <programlisting>
+typedef GstCaps *(*GstTypeFindFunc) (GstBuffer *buf, gpointer priv);
+ </programlisting>
+ <para>
+ This typefind function will inspect a GstBuffer with data and will output
+ a GstCaps structure describing the type. If the typefind function does not
+ understand the buffer contents, it will return NULL.
+ </para>
+ <para>
+ <application>GStreamer</application> has a typefind element in the set
+ of core elements
+ that can be used to determine the type of a given pad.
+ </para>
+ <para>
+ The next example will show how a typefind element can be inserted into a pipeline
+ to detect the media type of a file. It will output the capabilities of the pad into
+ an XML representation.
+ </para>
+ <programlisting>
+#include <gst/gst.h>
+
+void type_found (GstElement *typefind, GstCaps* caps);
+
+int
+main(int argc, char *argv[])
+{
+ GstElement *bin, *filesrc, *typefind;
+
+ gst_init (&argc, &argv);
+
+ if (argc != 2) {
+ g_print ("usage: %s <filename>\n", argv[0]);
+ exit (-1);
+ }
+
+ /* create a new bin to hold the elements */
+ bin = gst_bin_new ("bin");
+ g_assert (bin != NULL);
+
+ /* create a disk reader */
+ filesrc = gst_element_factory_make ("filesrc", "disk_source");
+ g_assert (filesrc != NULL);
+ g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
+
+ /* create the typefind element */
+ typefind = gst_element_factory_make ("typefind", "typefind");
+ g_assert (typefind != NULL);
+
+ /* add objects to the main pipeline */
+ gst_bin_add_many (GST_BIN (bin), filesrc, typefind, NULL);
+
+ g_signal_connect (G_OBJECT (typefind), "have_type",
+ G_CALLBACK (type_found), NULL);
+
+ gst_element_link (filesrc, typefind);
+
+ /* start playing */
+ gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
+
+ gst_bin_iterate (GST_BIN (bin));
+
+ gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
+
+ exit (0);
+}
+ </programlisting>
+ <para>
+ We create a very simple pipeline with only a filesrc and the typefind
+ element in it. The sinkpad of the typefind element has been linked
+ to the source pad of the filesrc.
+ </para>
+ <para>
+ We attached a signal 'have_type' to the typefind element which will be called
+ when the type of the media stream as been detected.
+ </para>
+ <para>
+ The typefind function will loop over all the registered types and will
+ execute each of the typefind functions. As soon as a function returns
+ a GstCaps pointer, the type_found function will be called:
+ </para>
+
+ <programlisting>
+void
+type_found (GstElement *typefind, GstCaps* caps)
+{
+ xmlDocPtr doc;
+ xmlNodePtr parent;
+
+ doc = xmlNewDoc ("1.0");
+ doc->root = xmlNewDocNode (doc, NULL, "Capabilities", NULL);
+
+ parent = xmlNewChild (doc->root, NULL, "Caps1", NULL);
+ gst_caps_save_thyself (caps, parent);
+
+ xmlDocDump (stdout, doc);
+}
+ </programlisting>
+ <para>
+ In the type_found function we can print or inspect the type that has been
+ detected using the GstCaps APIs. In this example, we just print out the
+ XML representation of the caps structure to stdout.
+ </para>
+ <para>
+ A more useful option would be to use the registry to look up an element
+ that can handle this particular caps structure, or we can also use the
+ autoplugger to link this caps structure to, for example, a videosink.
+ </para>
+
+ </sect1>
+
+ <sect1 id="section-autoplugging-spider">
+ <title>Another approach to autoplugging</title>
+ <para>
+ The autoplug API is interesting, but often impractical. It is static;
+ it cannot deal with dynamic pipelines. An element that will
+ automatically figure out and decode the type is more useful.
+ Enter the spider.
+ </para>
+ <sect2>
+ <title>The spider element</title>
+ <para>
+ The spider element is a generalized autoplugging element. At this point (April 2002), it's
+ the best we've got; it can be inserted anywhere within a pipeline to perform caps
+ conversion, if possible. Consider the following gst-launch line:
+ <programlisting>
+ $ gst-launch filesrc location=my.mp3 ! spider ! osssink
+ </programlisting>
+ The spider will detect the type of the stream, autoplug it to the osssink's caps, and play
+ the pipeline. It's neat.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Spider features</title>
+ <para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Automatically typefinds the incoming stream.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Has request pads on the source side. This means that it can
+ autoplug one source stream into many sink streams. For example,
+ an MPEG1 system stream can have audio as well as video; that
+ pipeline would be represented in gst-launch syntax as
+
+ <programlisting>
+ $ gst-launch filesrc location=my.mpeg1 ! spider ! { queue ! osssink } spider.src_%d!
+ { queue ! xvideosink }
+ </programlisting>
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+ </sect2>
+ </sect1>
+
</chapter>
<chapter id="chapter-clocks">
<title>Clocks in GStreamer</title>
+
<para>
+ WRITEME
</para>
</chapter>
--- /dev/null
+<chapter id="chapter-interfaces">
+ <title>Interfaces</title>
+
+ <para>
+ In <xref linkend="section-elements-properties"/>, you have learned how
+ to use <classname>GObject</classname> properties as a simple way to do
+ interaction between applications and elements. This method suffices for
+ the simple'n'straight settings, but fails for anything more complicated
+ than a getter and setter. For the more complicated use cases, &GStreamer;
+ uses interfaces based on the Glib <classname>GInterface</classname> type.
+ </para>
+
+ <para>
+ Most of the interfaces handled here will not contain any example code.
+ See the API references for details. Here, we will just describe the
+ scope and purpose of each interface.
+ </para>
+
+ <sect1 id="section-interfaces-mixer">
+ <title>The Mixer interface</title>
+
+ <para>
+ The mixer interface provides a uniform way to control the volume on a
+ hardware (or software) mixer. The interface is primarily intended to
+ be implemented by elements for audio inputs and outputs that talk
+ directly to the hardware (e.g. OSS or ALSA plugins).
+ </para>
+ <para>
+ Using this interface, it is possible to control a list of tracks
+ (such as Line-in, Microphone, etc.) from a mixer element. They can
+ be muted, their volume can be changed and, for input tracks, their
+ record flag can be set as well.
+ </para>
+ <para>
+ Example plugins implementing this interface include the OSS elements
+ (osssrc, osssink, ossmixer) and the ALSA plugins (alsasrc, alsasink
+ and alsamixer).
+ </para>
+ </sect1>
+
+ <sect1 id="section-interfaces-tuner">
+ <title>The Tuner interface</title>
+
+ <para>
+ The tuner interface is a uniform way to control inputs and outputs
+ on a multi-input selection device. This is primarily used for input
+ selection on elements for TV- and capture-cards.
+ </para>
+ <para>
+ Using this interface, it is possible to select one track from a list
+ of tracks supported by that tuner-element. The tuner will than select
+ that track for media-processing internally. This can, for example, be
+ used to switch inputs on a TV-card (e.g. from Composite to S-video).
+ </para>
+ <para>
+ This interface is currently only implemented by the Video4linux and
+ Video4linux2 elements.
+ </para>
+ </sect1>
+
+ <sect1 id="section-interfaces-colorbalance">
+ <title>The Color Balance interface</title>
+
+ <para>
+ The colorbalance interface is a way to control video-related properties
+ on an element, such as brightness, contrast and so on. It's sole
+ reason for existance is that, as far as its authors know, there's no
+ way to dynamically register properties using
+ <classname>GObject</classname>.
+ </para>
+ <para>
+ The colorbalance interface is implemented by several plugins, including
+ xvimagesink and the Video4linux and Video4linux2 elements.
+ </para>
+ </sect1>
+
+ <sect1 id="section-interfaces-proprobe">
+ <title>The Property Probe interface</title>
+
+ <para>
+ The property probe is a way to autodetect allowed values for a
+ <classname>GObject</classname> property. It's primary use (and
+ the only thing that we currently use it for) is to autodetect
+ devices in several elements. For example, the OSS elements use
+ this interface to detect all OSS devices on a system. Applications
+ can then <quote>probe</quote> this property and get a list of
+ detected devices. Given the overlap between HAL and the practical
+ implementations of this interface, this might in time be deprecated
+ in favour of HAL.
+ </para>
+ <para>
+ This interface is currently implemented by many elements, including
+ the ALSA, OSS, Video4linux and Video4linux2 elements.
+ </para>
+ </sect1>
+
+ <sect1 id="section-interfaces-xoverlay">
+ <title>The X Overlay interface</title>
+
+ <para>
+ The X Overlay interface was created to solve the problem of embedding
+ video streams in an application window. The application provides an
+ X-window to the element implementing this interface to draw on, and
+ the element will then use this X-window to draw on rather than creating
+ a new toplevel window. This is useful to embed video in video players.
+ </para>
+ <para>
+ This interface is implemented by, amongst others, the Video4linux and
+ Video4linux2 elements and by ximagesink, xvimagesink and sdlvideosink.
+ </para>
+ </sect1>
+</chapter>
--- /dev/null
+<chapter id="chapter-metadata">
+ <title>Metadata</title>
+
+ <para>
+ &GStreamer; makes a clear distinction between two types of metadata, and
+ has support for both types. The first is stream tags, which describe the
+ content of a stream in a non-technical way. Examples include the author
+ of a song, the title of that very same song or the album it is a part of.
+ The other type of metadata is stream-info, which is a somewhat technical
+ description of the properties of a stream. This can include video size,
+ audio samplerate, codecs used and so on. Tags are handled using the
+ &GStreamer; tagging system. Stream-info can be retrieved from a
+ <classname>GstPad</classname>.
+ </para>
+
+ <sect1 id="section-streaminfo">
+ <title>Stream information</title>
+
+ <para>
+ Stream information can most easily be read by reading them from a
+ <classname>GstPad</classname>. This has already been discussed before
+ in <xref linkend="section-caps-metadata"/>. Therefore, we will skip
+ it here.
+ </para>
+ </sect1>
+
+ <sect1 id="section-tags-read">
+ <title>Tag reading</title>
+
+ <para>
+ Tag reading is remarkably simple in &GStreamer; Every element supports
+ the <quote>found-tag</quote> signal, which will be fired each the time
+ the element reads tags from the stream. A <classname>GstBin</classname>
+ will conveniently forward tags found by its childs. Therefore, in most
+ applications, you will only need to connect to the
+ <quote>found-tag</quote> signal on the top-most bin in your pipeline,
+ and you will automatically retrieve all tags from the stream.
+ </para>
+ <para>
+ Note, however, that the <quote>found-tag</quote> might be fired
+ multiple times and by multiple elements in the pipeline. It is the
+ application's responsibility to put all those tags together and
+ display them to the user in a nice, coherent way.
+ </para>
+ </sect1>
+
+ <sect1 id="section-tags-write">
+ <title>Tag writing</title>
+
+ <para>
+ WRITEME
+ </para>
+ </sect1>
+</chapter>
--- /dev/null
+<chapter id="chapter-queryevents">
+ <title>Position tracking and seeking</title>
+
+ <para>
+ So far, we've looked at how to create a pipeline to do media processing
+ and how to make it run ("iterate"). Most application developers will be
+ interested in providing feedback to the user on media progress. Media
+ players, for example, will want to show a slider showing the progress in
+ the song, and usually also a label indicating stream length. Transcoding
+ applications will want to show a progress bar on how much % of the task
+ is done. &GStreamer; has built-in support for doing all this using a
+ concept known as <emphasis>querying</emphasis>. Since seeking is very
+ similar, it will be discussed here as well. Seeking is done using the
+ concept of <emphasis>events</emphasis>.
+ </para>
+
+ <sect1 id="section-querying">
+ <title>Querying: getting the position or length of a stream</title>
+
+ <para>
+ Querying is defined as requesting a specific stream-property related
+ to progress tracking. This includes getting the length of a stream (if
+ available) or getting the current position. Those stream properties
+ can be retrieved in various formats such as time, audio samples, video
+ frames or bytes. The functions used are <function>gst_element_query
+ ()</function> and <function>gst_pad_query ()</function>.
+ </para>
+
+ <para>
+ Obviously, using either of the above-mentioned functions requires the
+ application to know <emphasis>which</emphasis> element or pad to run
+ the query on. This is tricky, but there are some good sides to the
+ story. The good thing is that elements (or, rather, pads - since
+ <function>gst_element_query ()</function> internally calls
+ <function>gst_pad_query ()</function>) forward (<quote>dispatch</quote>)
+ events and queries to peer pads (or elements) if they don't handle it
+ themselves. The bad side is that some elements (or pads) will handle
+ events, but not the specific formats that you want, and therefore it
+ still won't work.
+ </para>
+
+ <para>
+ Most queries will, fortunately, work fine. Queries are always
+ dispatched backwards. This means, effectively, that it's easiest to
+ run the query on your video or audio output element, and it will take
+ care of dispatching the query to the element that knows the answer
+ (such as the current position or the media length; usually the demuxer
+ or decoder).
+ </para>
+
+ <programlisting><!-- example-begin query.c a -->
+#include <gst/gst.h>
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ GstElement *sink, *pipeline;
+<!-- example-end query.c a -->
+[..]<!-- example-begin query.c b --><!--
+ gchar *l;
+
+ /* init */
+ gst_init (&argc, &argv);
+
+ /* args */
+ if (argc != 2) {
+ g_print ("Usage: %s <filename>\n", argv[0]);
+ return -1;
+ }
+
+ /* build pipeline, the easy way */
+ l = g_strdup_printf ("filesrc location=\"%s\" ! oggdemux ! vorbisdec ! "
+ "audioconvert ! audioscale ! alsasink name=a",
+ argv[1]);
+ pipeline = gst_parse_launch (l, NULL);
+ sink = gst_bin_get_by_name (GST_BIN (pipeline), "a");
+ g_free (l);
+
+ /* play */
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+--><!-- example-end query.c b -->
+<!-- example-begin query.c c -->
+ /* run pipeline */
+ do {
+ gint64 len, pos;
+ GstFormat fmt = GST_FORMAT_TIME;
+
+ if (gst_element_query (sink, GST_QUERY_POSITION, &fmt, &pos) &&
+ gst_element_query (sink, GST_QUERY_TOTAL, &fmt, &len)) {
+ g_print ("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
+ GST_TIME_ARGS (pos), GST_TIME_ARGS (len));
+ }
+ } while (gst_bin_iterate (GST_BIN (pipeline)));
+<!-- example-end query.c c -->
+[..]<!-- example-begin query.c d --><!--
+ /* clean up */
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (pipeline));
+
+ return 0;
+--><!-- example-end query.c d -->
+<!-- example-begin query.c e -->
+}
+ <!-- example-end query.c e --></programlisting>
+ <para>
+ If you are having problems with the dispatching behaviour, your best
+ bet is to manually decide which element to start running the query on.
+ You can get a list of supported formats and query-types with
+ <function>gst_element_get_query_types ()</function> and
+ <function>gst_element_get_formats ()</function>.
+ </para>
+ </sect1>
+
+ <sect1 id="section-eventsseek">
+ <title>Events: seeking (and more)</title>
+
+ <para>
+ Events work in a very similar way as queries. Dispatching, for
+ example, works exactly the same for events (and also has the same
+ limitations). Although there are more ways in which applications
+ and elements can interact using events, we will only focus on seeking
+ here. This is done using the seek-event. A seek-event contains a
+ seeking offset, a seek method (which indicates relative to what the
+ offset was given), a seek format (which is the unit of the offset,
+ e.g. time, audio samples, video frames or bytes) and optionally a
+ set of seeking-related flags (e.g. whether internal buffers should be
+ flushed). The behaviour of a seek is also wrapped in the function
+ <function>gst_element_seek ()</function>.
+ </para>
+
+ <programlisting>
+static void
+seek_to_time (GstElement *audiosink,
+ gint64 time_nanonseconds)
+{
+ gst_element_seek (audiosink,
+ GST_SEEK_METHOD_SET | GST_FORMAT_TIME |
+ GST_SEEK_FLAG_FLUSH, time_nanoseconds);
+}
+ </programlisting>
+ </sect1>
+</chapter>
+
<chapter id="chapter-scheduler">
- <title>Understanding schedulers</title>
+ <title>Scheduling</title>
<para>
The scheduler is responsible for managing the plugins at runtime. Its
main responsibilities are:
plugin as the entry point in the pipeline.
</para>
+ <sect1 id="section-chain-based">
+ <title>Chain-based elements</title>
+ <para>
+ Chain based elements receive a buffer of data and are supposed
+ to handle the data and perform a gst_pad_push.
+ </para>
+ <para>
+ The basic main function of a chain-based element is like:
+ </para>
+ <programlisting>
+static void
+chain_function (GstPad *pad, GstBuffer *buffer)
+{
+ GstBuffer *outbuffer;
+
+ ....
+ // process the buffer, create a new outbuffer
+ ...
+
+ gst_pad_push (srcpad, outbuffer);
+}
+ </programlisting>
+ <para>
+ Chain based function are mainly used for elements that have a one to one
+ relation between their input and output behaviour. An example of such an
+ element can be a simple video blur filter. The filter takes a buffer in, performs
+ the blur operation on it and sends out the resulting buffer.
+ </para>
+ <para>
+ Another element, for example, is a volume filter. The filter takes audio samples as
+ input, performs the volume effect and sends out the resulting buffer.
+ </para>
+
+ </sect1>
+
+ <sect1 id="section-loop-based">
+ <title>Loop-based elements</title>
+ <para>
+ As opposed to chain-based elements, loop-based elements enter an
+ infinite loop that looks like this:
+
+ <programlisting>
+ GstBuffer *buffer, *outbuffer;
+
+ while (1) {
+ buffer = gst_pad_pull (sinkpad);
+ ...
+ // process buffer, create outbuffer
+ while (!done) {
+ ....
+ // optionally request another buffer
+ buffer = gst_pad_pull (sinkpad);
+ ....
+ }
+ ...
+ gst_pad_push (srcpad, outbuffer);
+ }
+ </programlisting>
+
+ The loop-based elements request a buffer whenever they need one.
+ </para>
+
+ <para>
+ When the request for a buffer cannot be immediately satisfied, the control
+ will be given to the source element of the loop-based element until it
+ performs a push on its source pad. At that time the control is handed
+ back to the loop-based element, etc... The execution trace can get
+ fairly complex using cothreads when there are multiple input/output
+ pads for the loop-based element. Cothread switches are performed within
+ the call to gst_pad_pull and gst_pad_push; from the perspective of
+ the loop-based element, it just "appears" that gst_pad_push (or _pull)
+ might take a long time to return.
+ </para>
+ <para>
+ Loop based elements are mainly used for the more complex elements
+ that need a specific amount of data before they can start to produce
+ output. An example of such an element is the MPEG video decoder. The
+ element will pull a buffer, perform some decoding on it and optionally
+ request more buffers to decode, and when a complete video frame has
+ been decoded, a buffer is sent out. For example, any plugin using the
+ bytestream library will need to be loop-based.
+ </para>
+ <para>
+ There is no problem in putting cothreaded elements into a <ulink
+ type="http" url="../../gstreamer/html/GstThread.html"><classname>GstThread
+ </classname></ulink> to
+ create even more complex pipelines with both user and kernel space threads.
+ </para>
+
+ </sect1>
+
+ <sect1 id="section-opt">
+ <title>The optimal scheduler</title>
+
+ <para>
+ Explain opt a bit, chains, groups, and how it affects execution.
+ </para>
+ </sect1>
</chapter>
fundamentally buffer-oriented rather than byte-oriented, the natural
solution to this problem is an element that can "buffer" the buffers
between the threads, in a thread-safe fashion. This element is the
- queue, described more fully in <xref linkend="chapter-queues"/>. It doesn't
+ queue, described more fully in <xref linkend="section-queue"/>. It doesn't
matter if the queue is placed in the containing bin or in the thread
itself, but it needs to be present on one side or the other to enable
inter-thread communication.
<para>
<programlisting>
-<!-- example-begin threads.c a -->
-<![CDATA[
-#include <gst/gst.h>
+<!-- example-begin threads.c -->
+#include <gst/gst.h>
/* we set this to TRUE right before gst_main (), but there could still
be a race condition between setting it and entering the function */
exit (0);
}
-]]>
-<!-- example-end threads.c a -->
+<!-- example-end threads.c -->
</programlisting>
</para>
</sect1>
+
+ <sect1 id="section-queue">
+ <title>Queue</title>
+ <para>
+ A queue is a filter element.
+ Queues can be used to link two elements in such way that the data can
+ be buffered.
+ </para>
+ <para>
+ A buffer that is sinked to a Queue will not automatically be pushed to the
+ next linked element but will be buffered. It will be pushed to the next
+ element as soon as a gst_pad_pull () is called on the queue's source pad.
+ </para>
+ <para>
+ Queues are mostly used in conjunction with a thread bin to
+ provide an external link for the thread's elements. You could have one
+ thread feeding buffers into a queue and another
+ thread repeatedly pulling on the queue to feed its
+ internal elements.
+ </para>
+
+ <para>
+ Below is a figure of a two-threaded decoder. We have one thread (the main execution
+ thread) reading the data from a file, and another thread decoding the data.
+ </para>
+ <figure float="1" id="section-queues-img">
+ <title>a two-threaded decoder with a queue</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/queue.ℑ" format="&IMAGE;" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ The standard <application>GStreamer</application> queue implementation has some
+ properties that can be changed using the g_objet_set () method. To set the
+ maximum number of buffers that can be queued to 30, do:
+ </para>
+ <programlisting>
+ g_object_set (G_OBJECT (queue), "max_level", 30, NULL);
+ </programlisting>
+
+ <para>
+ The following MP3 player shows you how to create the above pipeline
+ using a thread and a queue.
+ </para>
+
+ <programlisting>
+<!-- example-begin queue.c -->
+#include <stdlib.h>
+#include <gst/gst.h>
+
+gboolean playing;
+
+/* eos will be called when the src element has an end of stream */
+void
+eos (GstElement *element, gpointer data)
+{
+ g_print ("have eos, quitting\n");
+
+ playing = FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GstElement *filesrc, *audiosink, *queue, *decode;
+ GstElement *bin;
+ GstElement *thread;
+
+ gst_init (&argc,&argv);
+
+ if (argc != 2) {
+ g_print ("usage: %s <mp3 filename>\n", argv[0]);
+ exit (-1);
+ }
+
+ /* create a new thread to hold the elements */
+ thread = gst_thread_new ("thread");
+ g_assert (thread != NULL);
+
+ /* create a new bin to hold the elements */
+ bin = gst_bin_new ("bin");
+ g_assert (bin != NULL);
+
+ /* create a disk reader */
+ filesrc = gst_element_factory_make ("filesrc", "disk_source");
+ g_assert (filesrc != NULL);
+ g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
+ g_signal_connect (G_OBJECT (filesrc), "eos",
+ G_CALLBACK (eos), thread);
+
+ queue = gst_element_factory_make ("queue", "queue");
+ g_assert (queue != NULL);
+
+ /* and an audio sink */
+ audiosink = gst_element_factory_make ("osssink", "play_audio");
+ g_assert (audiosink != NULL);
+
+ decode = gst_element_factory_make ("mad", "decode");
+
+ /* add objects to the main bin */
+ gst_bin_add_many (GST_BIN (thread), decode, audiosink, NULL);
+
+ gst_bin_add_many (GST_BIN (bin), filesrc, queue, thread, NULL);
+
+
+ gst_element_link (filesrc, queue);
+ gst_element_link_many (queue, decode, audiosink, NULL);
+
+ /* start playing */
+ gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
+
+ playing = TRUE;
+
+ while (playing) {
+ gst_bin_iterate (GST_BIN (bin));
+ }
+
+ gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
+
+ return 0;
+}
+<!-- example-end queue.c -->
+ </programlisting>
+
+ </sect1>
</chapter>
</para>
<programlisting>
-<!-- example-begin gnome.c a -->
-<![CDATA[
-#include <gnome.h>
-#include <gst/gst.h>
+<!-- example-begin gnome.c -->
+#include <gnome.h>
+#include <gst/gst.h>
int
main (int argc, char **argv)
return 0;
}
-]]>
-<!-- example-end gnome.c a -->
+<!-- example-end gnome.c -->
</programlisting>
<para>
If you try out this program, you will see that when called with
</para>
<programlisting>
-<!-- example-begin gnome.c a -->
-<![CDATA[
-#include <gnome.h>
-#include <gst/gst.h>
+<!-- example-begin gnome.c -->
+#include <gnome.h>
+#include <gst/gst.h>
int
main (int argc, char **argv)
return 0;
}
-]]>
-<!-- example-end gnome.c a -->
+<!-- example-end gnome.c -->
</programlisting>
<para>
If you try out this program, you will see that when called with
syntax.
</para>
<para>
- A simple commandline to play a mp3 audio file looks like:
+ A simple commandline looks like:
<screen>
gst-launch filesrc location=hello.mp3 ! mad ! osssink
demux.video_00! { mpeg2dec ! xvideosink }
</screen>
- <xref linkend="section-programs-gst-launch-more-examples"/> lists more gst-launch commandlines.
-
</para>
<para>
You can also use the parser in you own
the g_value_convert routines. No error message will be displayed on an invalid
conversion, due to limitations in the value convert API.
</para>
- <para>
- The list of properties an element supports can be found out using
- <userinput>gst-inspect elemnt-name</userinput>.
- </para>
</sect3>
<sect3>
<title>Bins, Threads, and Pipelines</title>
<para>
A pipeline description between parentheses is placed into a bin. The open paren may be
preceded by a type name, as in <computeroutput>jackbin.( ... )</computeroutput> to make
- a bin of a specified type. Square brackets '[ ]' make pipelines, and curly braces '{ }' make
+ a bin of a specified type. Square brackets make pipelines, and curly braces make
threads. The default toplevel bin type is a pipeline, although putting the whole
description within parentheses or braces can override this default.
</para>
</sect3>
</sect2>
- <sect2 id="section-programs-gst-launch-more-examples">
- <title>More Examples</title>
- <para>
- This chapter collects some more complex pipelines. The examples are split into several lines,
- so make sure to include the trailing backslashes.
- When modifying the pipelines and seeking for the right element to insert, a grep of the gst-inspect
- output often gives a starting point:
- <screen>
-gst-inspect | grep "avi"
- </screen>
- Another way is to do:
- <screen>
-gst-launch filesrc location=video.avi ! decodebin name=d ! xvimagesink d. ! { queue ! alsasink } -v
- </screen>
- and look on the output, which plugins it chooses.
- </para>
- <para>
- Play a remote mp3 audio file:
- <screen>
-gst-launch gnomevfssrc location=http://www.server.org/hello.mp3 ! mad ! alsasink
- </screen>
- </para>
- <para>
- Play a local mp3 audio file with visualisation:
- <screen>
-gst-launch filesrc location=Hello.mp3 ! mad ! tee name=t ! \
- { queue ! osssink } \
- { t. ! queue ! synaesthesia ! ffmpegcolorspace ! xvimagesink }
- </screen>
- </para>
- <para>
- Play a local ogg audio file:
- <screen>
-gst-launch filesrc location=file.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioscale ! alsasink
- </screen>
- </para>
- <para>
- Play a local ogg video file:
- <screen>
-gst-launch filesrc location=file.ogg ! oggdemux name=demux \
- { demux. ! queue ! theoradec ! ffmpegcolorspace ! videoscale ! xvimagesink } \
- { demux. ! queue ! vorbisdec ! audioconvert ! audioscale ! alsasink }
- </screen>
- </para>
- <para>
- Play a local avi video file:
- <screen>
-gst-launch filesrc location=video.avi ! mpegdemux name=demux \
- demux.audio_00! { queue ! ac3parse ! a52dec ! osssink } \
- demux.video_00! { queue ! mpeg2dec ! xvideosink }
- </screen>
- </para>
- <para>
- Transcoding an audio file from one format into another:
- <screen>
-gst-launch filesrc location=file.ogg ! oggdemux ! vorbisdec ! audioconvert ! flacenc ! filesink location=file.flac
- </screen>
- <screen>
-gst-launch filesrc location=file.mp3 ! id3demus ! mad ! audioconvert ! rawvorbisenc ! oggmux ! filesink location=file.ogg
- </screen>
- </para>
- <para>
- Transcoding an dvd video into a ogg video:
- <screen>
-gst-launch-0.8 oggmux name=mux ! filesink location=/tmp/file.ogg \
- { dvdreadsrc location=/dev/cdrom ! dvddemux name=demux.audio_00 ! \
- { queue ! a52dec ! audioconvert ! rawvorbisenc ! queue ! mux. } \
- { demux.video_00 ! queue ! mpeg2dec ! ffcolorspace ! videoscale ! video/x-raw-yuv,width=384,height=288 ! tee name=t ! \
- { queue ! theoraenc ! queue ! mux. } \
- } \
- } \
- { t. ! queue ! ffcolorspace ! ximagesink }
- </screen>
- </para>
-
- </sect2>
</sect1>
<sect1 id="section-programs-gst-inspect">
<variablelist>
-
- <varlistentry>
- <term>2 Nov 2004</term>
- <listitem>
- <para>
- <emphasis>zaheerm</emphasis>:
-wtay: unfair u fixed the bug i was using as a feature!
- </para>
- </listitem>
- </varlistentry>
-
-
<varlistentry>
<term>14 Oct 2004</term>
<listitem>
+++ /dev/null
-<chapter id="chapter-autoplug">
- <title>Autoplugging</title>
- <para>
- <application>GStreamer</application> provides an API to automatically
- construct complex pipelines based on source and destination capabilities.
- This feature is very useful if you want to convert type X to type Y but
- don't care about the plugins needed to accomplish this task. The
- autoplugger will consult the plugin repository, select and link the
- elements needed for the conversion.
- </para>
- <para>
- The autoplugger API is implemented in an abstract class. Autoplugger
- implementations reside in plugins and are therefore optional and can be
- optimized for a specific task. Two types of autopluggers exist: renderer
- ones and non-renderer ones. The renderer autopluggers will not have any
- source pads while the non-renderer ones do. The renderer autopluggers are
- mainly used for media playback while the non renderer ones are used for
- arbitrary format conversion.
- </para>
-
- <sect1>
- <title>Using autoplugging</title>
- <para>
- You first need to create a suitable autoplugger with gst_autoplug_factory_make().
- The name of the autoplugger must be one of the registered autopluggers..
- </para>
- <para>
- A list of all available autopluggers can be obtained with gst_autoplug_factory_get_list().
- </para>
- <para>
- If the autoplugger supports the RENDERER API, use the
- gst_autoplug_to_renderers() function to create a bin that links
- the source caps to the specified render elements. You can then add
- the bin to a pipeline and run it.
-
- <programlisting>
-
- GstAutoplug *autoplug;
- GstElement *element;
- GstElement *sink;
-
- /* create a static autoplugger */
- autoplug = gst_autoplug_factory_make ("staticrender");
-
- /* create an osssink */
- sink = gst_element_factory_make ("osssink", "our_sink");
-
- /* create an element that can play audio/mp3 through osssink */
- element = gst_autoplug_to_renderers (autoplug,
- gst_caps_new (
- "sink_audio_caps",
- "audio/mp3",
- NULL
- ),
- sink,
- NULL);
-
- /* add the element to a bin and link the sink pad */
- ...
- </programlisting>
- </para>
- <para>
- If the autoplugger supports the CAPS API, use the gst_autoplug_to_caps()
- function to link the source caps to the destination caps. The created
- bin will have source and sink pads compatible with the provided caps.
-
- <programlisting>
-
- GstAutoplug *autoplug;
- GstElement *element;
-
- /* create a static autoplugger */
- autoplug = gst_autoplug_factory_make ("static");
-
- /* create an element that converts audio/mp3 to audio/raw */
- element = gst_autoplug_to_caps (autoplug,
- gst_caps_new (
- "sink_audio_caps",
- "audio/mp3",
- NULL
- ),
- gst_caps_new (
- "src_audio_caps",
- "audio/raw",
- NULL
- ),
- NULL);
-
- /* add the element to a bin and link the src/sink pads */
- ...
- </programlisting>
- </para>
- </sect1>
- <sect1 id="section-autoplug-cache">
- <!-- FIXME: this is outdated, there is no GstAutoplugCache in gst-0.8.X -->
- <title>Using the <classname>GstAutoplugCache</classname> element</title>
- <para>
- The <classname>GstAutoplugCache</classname> element is used to cache the
- media stream when performing typedetection. As we have seen in
- <xref linkend="chapter-typedetection"/>, the typefind function consumes a
- buffer to determine its media type. After we have set up the pipeline
- to play the media stream we should be able to 'replay' the previous buffer(s).
- This is what the autoplugcache is used for.
- </para>
- <para>
- The basic usage pattern for the autoplugcache in combination with the typefind
- element is like this:
- <orderedlist>
- <listitem>
- <para>
- Add the autoplugcache element to a bin and link the sink pad
- to the source pad of an element with unknown caps.
- </para>
- </listitem>
- <listitem>
- <para>
- Link the source pad of the autoplugcache to the sink pad of
- the typefind element.
- </para>
- </listitem>
- <listitem>
- <para>
- Iterate the pipeline until the typefind element has found a type.
- </para>
- </listitem>
- <listitem>
- <para>
- Remove the typefind element and add the plugins needed to play
- back the discovered media type to the autoplugcache source pad.
- </para>
- </listitem>
- <listitem>
- <para>
- Reset the cache to start playback of the cached data. Connect to the
- "cache_empty" signal.
- </para>
- </listitem>
- <listitem>
- <para>
- In the cache_empty signal callback function, remove the autoplugcache and
- relink the pads.
- </para>
- </listitem>
- </orderedlist>
- </para>
- <para>
- In the next chapter we will create a new version of our helloworld example using the
- autoplugger, the autoplugcache and the typefind element.
- </para>
- </sect1>
- <sect1 id="section-autoplugging-spider">
- <title>Another approach to autoplugging</title>
- <para>
- The autoplug API is interesting, but often impractical. It is static;
- it cannot deal with dynamic pipelines. An element that will
- automatically figure out and decode the type is more useful.
- Enter the spider.
- </para>
- <sect2>
- <title>The spider element</title>
- <para>
- The spider element is a generalized autoplugging element. At this point (April 2002), it's
- the best we've got; it can be inserted anywhere within a pipeline to perform caps
- conversion, if possible. Consider the following gst-launch line:
- <programlisting>
- $ gst-launch filesrc location=my.mp3 ! spider ! osssink
- </programlisting>
- The spider will detect the type of the stream, autoplug it to the osssink's caps, and play
- the pipeline. It's neat.
- </para>
- </sect2>
- <sect2>
- <title>Spider features</title>
- <para>
- <orderedlist>
- <listitem>
- <para>
- Automatically typefinds the incoming stream.
- </para>
- </listitem>
- <listitem>
- <para>
- Has request pads on the source side. This means that it can
- autoplug one source stream into many sink streams. For example,
- an MPEG1 system stream can have audio as well as video; that
- pipeline would be represented in gst-launch syntax as
-
- <programlisting>
- $ gst-launch filesrc location=my.mpeg1 ! spider ! { queue ! osssink } spider.src_%d!
- { queue ! xvideosink }
- </programlisting>
- </para>
- </listitem>
- </orderedlist>
- </para>
- </sect2>
- </sect1>
-</chapter>
<chapter id="chapter-bins">
<title>Bins</title>
<para>
- A bin is a container element. You can add elements to a bin. Since a bin is
- an element itself, it can also be added to another bin.
- </para>
- <para>
- Bins allow you to combine a group of linked elements into one logical element. You do
- not deal with the individual elements anymore but with just one element, the bin.
- We will see that this is extremely powerful when you are going to construct
- complex pipelines since it allows you to break up the pipeline in smaller chunks.
- </para>
- <para>
- The bin will also manage the elements contained in it. It will figure out how
- the data will flow in the bin and generate an optimal plan for that data flow. Plan
- generation is one of the most complicated procedures in GStreamer.
+ A bin is a container element. You can add elements to a bin. Since a
+ bin is an element itself, a bin can be handled in the same way as any
+ other element. Therefore, the whole previous chapter (<xref
+ linkend="chapter-elements"/>) applies to bins as well.
</para>
- <figure float="1" id="section-bin-img">
- <title>Visualisation of a bin with some elements in it</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/bin-element.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
+ <sect1 id="section-bins">
+ <title>What are bins</title>
+ <para>
+ Bins allow you to combine a group of linked elements into one
+ logical element. You do not deal with the individual elements
+ anymore but with just one element, the bin. We will see that
+ this is extremely powerful when you are going to construct
+ complex pipelines since it allows you to break up the pipeline
+ in smaller chunks.
+ </para>
+ <para>
+ The bin will also manage the elements contained in it. It will
+ figure out how the data will flow in the bin and generate an
+ optimal plan for that data flow. Plan generation is one of the
+ most complicated procedures in &GStreamer;. You will learn more
+ about this process, called scheduling, in <xref
+ linkend="chapter-scheduler"/>.
+ </para>
- <para>
- There are two specialized bins available to the GStreamer programmer:
+ <figure float="1" id="section-bin-img">
+ <title>Visualisation of a bin with some elements in it</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/bin-element.ℑ" format="&IMAGE;"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ There are two specialized types of bins available to the
+ &GStreamer; programmer:
+ </para>
<itemizedlist>
<listitem>
<para>
- a pipeline: a generic container that allows scheduling of the
+ A pipeline: a generic container that allows scheduling of the
containing elements. The toplevel bin has to be a pipeline.
- Every application thus needs at least one of these.
+ Every application thus needs at least one of these. Applications
+ can iterate pipelines using <function>gst_bin_iterate
+ ()</function> to make it process data while in the playing state.
</para>
</listitem>
<listitem>
<para>
- a thread: a bin that will be run in a separate execution thread.
+ A thread: a bin that will be run in a separate execution thread.
You will have to use this bin if you have to carefully
synchronize audio and video, or for buffering. You will learn
more about threads in <xref linkend="chapter-threads"/>.
</para>
</listitem>
</itemizedlist>
- </para>
+ </sect1>
+
+ <sect1 id="section-bin-create">
+ <title>Creating a bin</title>
+ <para>
+ Bins are created in the same way that other elements are created,
+ i.e. using an element factory. There are also convenience functions
+ available (<function>gst_bin_new ()</function>,
+ <function>gst_thread_new ()</function> and <function>gst_pipeline_new
+ ()</function>). To add elements to a bin or remove elements from a
+ bin, you can use <function>gst_bin_add ()</function> and
+ <function>gst_bin_remove ()</function>. Note that the bin that you
+ add an element to will take ownership of that element. If you
+ destroy the bin, the element will be dereferenced with it. If you
+ remove an element from a bin, it will be dereferenced automatically.
+ </para>
+ <programlisting><!-- example-begin bin.c a -->
+#include <gst/gst.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ GstElement *bin, *pipeline, *source, *sink;
+
+ /* init */
+ gst_init (&argc, &argv);
+
+ /* create */
+ pipeline = gst_pipeline_new ("my_pipeline");
+ bin = gst_pipeline_new ("my_bin");
+ source = gst_element_factory_make ("fakesrc", "source");
+ sink = gst_element_factory_make ("fakesink", "sink");
+
+ /* set up pipeline */
+ gst_bin_add_many (GST_BIN (bin), source, sink, NULL);
+ gst_bin_add (GST_BIN (pipeline), bin);
+ gst_element_link (source, sink);
+<!-- example-end bin.c a -->
+[..]<!-- example-begin bin.c b --><!--
+ return 0;
+--><!-- example-end bin.c b -->
+<!-- example-begin bin.c c -->
+}
+ <!-- example-end bin.c c --></programlisting>
+ <para>
+ There are various functions to lookup elements in a bin. You can
+ also get a list of all elements that a bin contains using the function
+ <function>gst_bin_get_list ()</function>. See the API references of
+ <ulink type="http"
+ url="&URLAPI;GstBin.html"><classname>GstBin</classname></ulink>
+ for details.
+ </para>
+ </sect1>
+
+ <sect1 id="section-bin-custom">
+ <title>Custom bins</title>
+ <para>
+ The application programmer can create custom bins packed with elements
+ to perform a specific task. This allows you, for example, to write
+ an Ogg/Vorbis decoder with just the following lines of code:
+ </para>
+ <programlisting>
+int
+main (int argc
+ char *argv[])
+{
+ GstElement *player;
+
+ /* init */
+ gst_init (&argc, &argv);
+
+ /* create player */
+ player = gst_element_factory_make ("oggvorbisplayer", "player");
+
+ /* set the source audio file */
+ g_object_set (G_OBJECT (player), "location", "helloworld.ogg", NULL);
+
+ /* start playback */
+ gst_element_set_state (GST_ELEMENT (mp3player), GST_STATE_PLAYING);
+[..]
+}
+ </programlisting>
+ <para>
+ Custom bins can be created with a plugin or an XML description. You
+ will find more information about creating custom bin in the <ulink
+ type="http"
+ url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/index.html">Plugin
+ Writers Guide</ulink>.
+ </para>
+ </sect1>
</chapter>
-<chapter id="chapter-buffers">
- <title>Buffers</title>
- <para>
- Buffers contain the data that will flow through the pipeline you have
- created. A source element will typically create a new buffer and pass
- it through a pad to the next element in the chain. When using the
- GStreamer infrastructure to create a media pipeline you will not have
- to deal with buffers yourself; the elements will do that for you.
+<chapter id="chapter-data">
+ <title>Buffers and Events</title>
+ <para>
+ The data flowing through a pipeline consists of a combination of
+ buffers and events. Buffers contain the actual pipeline data. Events
+ contain control information, such as seeking information and
+ end-of-stream notifiers. All this will flow through the pipeline
+ automatically when it's running. This chapter is mostly meant to
+ explain the concept to you; you don't need to do anything for this.
</para>
- <para>
- A buffer consists of:
+ <sect1 id="section-buffers">
+ <title>Buffers</title>
+ <para>
+ Buffers contain the data that will flow through the pipeline you have
+ created. A source element will typically create a new buffer and pass
+ it through a pad to the next element in the chain. When using the
+ GStreamer infrastructure to create a media pipeline you will not have
+ to deal with buffers yourself; the elements will do that for you.
+ </para>
+ <para>
+ A buffer consists, amongst others, of:
+ </para>
<itemizedlist>
<listitem>
<para>
- a pointer to a piece of memory.
+ A pointer to a piece of memory.
</para>
</listitem>
<listitem>
<para>
- the size of the memory.
+ The size of the memory.
</para>
</listitem>
<listitem>
<para>
- a timestamp for the buffer.
+ A timestamp for the buffer.
</para>
</listitem>
<listitem>
</para>
</listitem>
</itemizedlist>
- </para>
-
- <para>
- <!-- FIXME: this is outdated, there is no GstBufferPool in gst-0.8.X -->
- GStreamer provides functions to create custom buffer create/destroy algorithms, called
- a <classname>GstBufferPool</classname>. This makes it possible to efficiently
- allocate and destroy buffer memory. It also makes it possible to exchange memory between
- elements by passing the <classname>GstBufferPool</classname>. A video element can,
- for example, create a custom buffer allocation algorithm that creates buffers with XSHM
- as the buffer memory. An element can use this algorithm to create and fill the buffer
- with data.
- </para>
-
- <para>
- The simple case is that a buffer is created, memory allocated, data put
- in it, and passed to the next element. That element reads the data, does
- something (like creating a new buffer and decoding into it), and
- unreferences the buffer. This causes the data to be freed and the buffer
- to be destroyed. A typical MPEG audio decoder works like this.
- </para>
+ <para>
+ The simple case is that a buffer is created, memory allocated, data
+ put in it, and passed to the next element. That element reads the
+ data, does something (like creating a new buffer and decoding into
+ it), and unreferences the buffer. This causes the data to be free'ed
+ and the buffer to be destroyed. A typical video or audio decoder
+ works like this.
+ </para>
+ <para>
+ There are more complex scenarios, though. Elements can modify buffers
+ in-place, i.e. without allocating a new one. Elements can also write
+ to hardware memory (such as from video-capture sources) or memory
+ allocated from the X-server using XShm). Buffers can be read-only,
+ and so on.
+ </para>
+ </sect1>
- <para>
- A more complex case is when the filter modifies the data in place. It
- does so and simply passes on the buffer to the next element. This is just
- as easy to deal with. An element that works in place has to be careful when
- the buffer is used in more than one element; a copy on write has to made in this
- situation.
- </para>
+ <sect1 id="section-events">
+ <title>Events</title>
+ <para>
+ Events are control particles that are sent both up- and downstream in
+ a pipeline along with buffers. Downstream events notify fellow elements
+ of stream states. Possible events include discontinuities, flushes,
+ end-of-stream notifications and so on. Upstream events are used both
+ in application-element interaction as well as event-event interaction
+ to request changes in stream state, such as seeks. For applications,
+ only upstream events are important. Downstream events are just
+ explained to get a more complete picture of the data concept.
+ </para>
+ <para>
+ Since most applications seek in time units, our example below does so
+ too:
+ </para>
+ <programlisting>
+static void
+seek_to_time (GstElement *element,
+ guint64 time_ns)
+{
+ GstEvent *event;
+ event = gst_event_new_seek (GST_SEEK_METHOD_SET |
+ GST_FORMAT_TIME,
+ time_ns);
+ gst_element_send_event (element, event);
+}
+ </programlisting>
+ <para>
+ The function <function>gst_element_seek ()</function> is a shortcut
+ for this. This is mostly just to show how it all works.
+ </para>
+ </sect1>
</chapter>
-<chapter id="chapter-elements">
+<chapter id="chapter-elements" xreflabel="Elements">
<title>Elements</title>
<para>
- The most important object in <application>GStreamer</application> for the
- application programmer is the <ulink type="http"
- url="../../gstreamer/html/GstElement.html"><classname>GstElement</classname>
- </ulink>object.
+ The most important object in &GStreamer; for the application programmer
+ is the <ulink type="http"
+ url="../../gstreamer/html/GstElement.html"><classname>GstElement</classname></ulink>
+ object. An element is the basic building block for a media pipeline. All
+ the different high-level components you will use are derived from
+ <classname>GstElement</classname>. Every decoder, encoder, demuxer, video
+ or audio output is in fact a <classname>GstElement</classname>
</para>
- <sect1 id="section-elements-design">
- <title>What is an element ?</title>
- <para>
- An element is the basic building block for the media pipeline.
- All the different high-level components you are going to use are
- derived from <ulink type="http" url="../../gstreamer/html/GstElement.html">
- <classname>GstElement</classname></ulink>. This means that a
- lot of functions you are going to use operate on objects of this class.
- </para>
+ <sect1 id="section-elements-design" xreflabel="What are elements?">
+ <title>What are elements?</title>
<para>
- Elements, from the perspective of GStreamer, are viewed as "black boxes"
- with a number of different aspects. One of these aspects is the presence
- of "pads" (see <xref linkend="chapter-pads"/>), or link points.
- This terminology arises from soldering; pads are where wires can be
- attached.
+ For the application programmer, elements are best visualized as black
+ boxes. On the one end, you might put something in, the element does
+ something with it and something else comes out at the other side. For
+ a decoder element, ifor example, you'd put in encoded data, and the
+ element would output decoded data. In the next chapter (see <xref
+ linkend="chapter-pads"/>), you will learn more about data input and
+ output in elements, and how you can set that up in your application.
</para>
- </sect1>
- <sect1 id="section-elements-types">
- <title>Types of elements</title>
-
<sect2 id="section-elements-src">
<title>Source elements</title>
<para>
- Source elements generate data for use by a pipeline, for example
- reading from disk or from a sound card.
- </para>
- <para>
- <xref linkend="section-element-srcimg"/> shows how we will visualise
- a source element.
- We always draw a source pad to the right of the element.
+ Source elements generate data for use by a pipeline, for example
+ reading from disk or from a sound card. <xref
+ linkend="section-element-srcimg"/> shows how we will visualise
+ a source element. We always draw a source pad to the right of
+ the element.
</para>
<figure float="1" id="section-element-srcimg">
<title>Visualisation of a source element</title>
<mediaobject>
<imageobject>
- <imagedata fileref="images/src-element.ℑ" format="&IMAGE;" />
+ <imagedata fileref="images/src-element.ℑ"
+ format="&IMAGE;"/>
</imageobject>
</mediaobject>
</figure>
<para>
Source elements do not accept data, they only generate data. You can
- see this in the figure because it only has a source pad. A source
- pad can only generate data.
+ see this in the figure because it only has a source pad (on the
+ right). A source pad can only generate data.
</para>
</sect2>
<sect2 id="section-elements-filter">
- <title>Filters and codecs</title>
+ <title>Filters, convertors, demuxers, muxers and codecs</title>
<para>
- Filter elements have both input and output pads. They operate on
- data they receive in their sink pads and produce data on their source
- pads. For example, MPEG decoders and volume filters would fall into
- this category.
+ Filters and filter-like elements have both input and outputs pads.
+ They operate on data that they receive on their input (sink) pads,
+ and will provide data on their output (source) pads. Examples of
+ such elements are a volume element (filter), a video scaler
+ (convertor), an Ogg demuxer or a Vorbis decoder.
</para>
<para>
- Elements are not constrained as to the number of pads they might have;
- for example, a video mixer might have two input pads (the images of
- the two different video streams) and one output pad.
+ Filter-like elements can have any number of source or sink pads. A
+ video demuxer, for example, would have one sink pad and several
+ (1-N) source pads, one for each elementary stream contained in the
+ container format. Decoders, on the other hand, will only have one
+ source and sink pads.
</para>
<figure float="1" id="section-element-filterimg">
<title>Visualisation of a filter element</title>
<mediaobject>
<imageobject>
- <imagedata fileref="images/filter-element.ℑ" format="&IMAGE;" />
+ <imagedata fileref="images/filter-element.ℑ"
+ format="&IMAGE;"/>
</imageobject>
</mediaobject>
</figure>
<para>
- <xref linkend="section-element-filterimg"/> shows how we will visualise
- a filter element.
- This element has one sink (input) pad and one source (output) pad.
- Sink pads are drawn on the left of the element.
+ <xref linkend="section-element-filterimg"/> shows how we will
+ visualise a filter-like element. This specific element has one source
+ and one sink element. Sink pads, receiving input data, are depicted
+ at the left of the element; source pads are still on the right.
</para>
<figure float="1" id="section-element-multifilterimg">
<title>Visualisation of a filter element with
<mediaobject>
<imageobject>
<imagedata fileref="images/filter-element-multi.ℑ"
- format="&IMAGE;" />
+ format="&IMAGE;" />
</imageobject>
</mediaobject>
</figure>
<para>
- <xref linkend="section-element-multifilterimg"/> shows the visualisation of a filter element with
- more than one output pad. An example of such a filter is the AVI
- demultiplexer. This element will parse the input data and
- extract the audio and video data. Most of these filters dynamically
- send out a signal when a new pad is created so that the application
- programmer can link an arbitrary element to the newly created pad.
+ <xref linkend="section-element-multifilterimg"/> shows another
+ filter-like element, this one having more than one output (source)
+ pad. An example of one such element could, for example, be an Ogg
+ demuxer for an Ogg stream containing both audio and video. One
+ source pad will contain the elementary video stream, another will
+ contain the elementary audio stream. Demuxers will generally fire
+ signals when a new pad is created. The application programmer can
+ then handle the new elementary stream in the signal handler.
</para>
</sect2>
<title>Visualisation of a sink element</title>
<mediaobject>
<imageobject>
- <imagedata fileref="images/sink-element.ℑ" format="&IMAGE;" />
+ <imagedata fileref="images/sink-element.ℑ"
+ format="&IMAGE;" />
</imageobject>
</mediaobject>
</figure>
</sect2>
</sect1>
+
+ <sect1 id="section-elements-create">
+ <title>Creating a <classname>GstElement</classname></title>
+ <para>
+ The simplest way to create an element is to use <ulink type="http"
+ url="&URLAPI;GstElementFactory.html#gst-element-factory-make"><function>gst_element_factory_make
+ ()</function></ulink>. This function takes a factory name and an
+ element name for the newly created element. The name of the element
+ is something you can use later on to look up the element in a bin,
+ for example. The name will also be used in debug output. You can
+ pass <symbol>NULL</symbol> as the name argument to get a unique,
+ default name.
+ </para>
+ <para>
+ When you don't need the element anymore, you need to unref it using
+ <ulink type="http"
+ url="&URLAPI;GstObject.html#gst-object-unref"><function>gst_object_unref
+ ()</function></ulink>. This decreases the reference count for the
+ element by 1. An element has a refcount of 1 when it gets created.
+ An element gets destroyed completely when the refcount is decreased
+ to 0.
+ </para>
+ <para>
+ The following example &EXAFOOT; shows how to create an element named
+ <emphasis>source</emphasis> from the element factory named
+ <emphasis>fakesrc</emphasis>. It checks if the creation succeeded.
+ After checking, it unrefs the element.
+ </para>
+ <programlisting><!-- example-begin elementmake.c --><![CDATA[
+#include <gst/gst.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ GstElement *element;
+
+ /* init GStreamer */
+ gst_init (&argc, &argv);
+
+ /* create element */
+ element = gst_element_factory_make ("fakesrc", "source");
+ if (!element) {
+ g_print ("Failed to create element of type 'fakesrc'\n");
+ return -1;
+ }
+
+ gst_object_unref (GST_OBJECT (element));
+
+ return 0;
+}
+ ]]><!-- example-end elementmake.c --></programlisting>
+ <para>
+ <function>gst_element_factory_make</function> is actually a shorthand
+ for a combination of two functions. A <ulink type="http"
+ url="&URLAPI;GstElement.html"><classname>GstElement</classname></ulink>
+ object is created from a factory. To create the element, you have to
+ get access to a <ulink type="http"
+ url="&URLAPI;GstElementFactory.html"><classname>GstElementFactory</classname></ulink>
+ object using a unique factory name. This is done with <ulink type="http"
+ url="&URLAPI;GstElementFactory.html#gst-element-factory-find"><function>gst_element_factory_find
+ ()</function></ulink>.
+ </para>
+ <para>
+ The following code fragment is used to get a factory that can be used
+ to create the <emphasis>fakesrc</emphasis> element, a fake data source.
+ The function <ulink type="http"
+ url="&URLAPI;GstElementFactory.html#gst-element-factory-create"><function>gst_element_factory_create
+ ()</function></ulink> will use the element factory to create an
+ element with the given name.
+ </para>
+ <programlisting><!-- example-begin elementcreate.c --><![CDATA[
+#include <gst/gst.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ GstElementFactory *factory;
+ GstElement * element;
+
+ /* init GStreamer */
+ gst_init (&argc, &argv);
+
+ /* create element, method #2 */
+ factory = gst_element_factory_find ("fakesrc");
+ if (!factory) {
+ g_print ("Failed to find fctory of type 'fakesrc'\n");
+ return -1;
+ }
+ element = gst_element_factory_create (factory, "source");
+ if (!element) {
+ g_print ("Failed to create element, even though it's factory exists!\n");
+ return -1;
+ }
+
+ gst_object_unref (GST_OBJECT (element));
+
+ return 0;
+}
+ ]]><!-- example-end elementcreate.c --></programlisting>
+ </sect1>
+
+ <sect1 id="section-elements-properties">
+ <title>Using an element as a <classname>GObject</classname></title>
+ <para>
+ A <ulink type="http"
+ url="&URLAPI;GstElement.html"><classname>GstElement</classname></ulink>
+ can have several properties which are implemented using standard
+ <classname>GObject</classname> properties. The usual
+ <classname>GObject</classname> methods to query, set and get
+ property values and <classname>GParamSpecs</classname> are
+ therefore supported.
+ </para>
+ <para>
+ Every <classname>GstElement</classname> inherits at least one
+ property from its parent <classname>GstObject</classname>: the
+ "name" property. This is the name you provide to the functions
+ <function>gst_element_factory_make ()</function> or
+ <function>gst_element_factory_create ()</function>. You can get
+ and set this property using the functions
+ <function>gst_object_set_name</function> and
+ <function>gst_object_get_name</function> or use the
+ <classname>GObject</classname> property mechanism as shown below.
+ </para>
+ <programlisting><!-- example-begin elementget.c --><![CDATA[
+#include <gst/gst.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ GstElement *element;
+ const gchar *name;
+
+ /* init GStreamer */
+ gst_init (&argc, &argv);
+
+ /* create element */
+ element = gst_element_factory_make ("fakesrc", "source");
+
+ /* get name */
+ g_object_get (G_OBJECT (element), "name", &name, NULL);
+ g_print ("The name of the element is '%s'.\n", name);
+
+ gst_object_unref (GST_OBJECT (element));
+
+ return 0;
+}
+ ]]><!-- example-end elementget.c --></programlisting>
+ <para>
+ Most plugins provide additional properties to provide more information
+ about their configuration or to configure the element.
+ <command>gst-inspect</command> is a useful tool to query the properties
+ of a particular element, it will also use property introspection to give
+ a short explanation about the function of the property and about the
+ parameter types and ranges it supports. See the appendix for details
+ about <command>gst-inspect</command>.
+ </para>
+ <para>
+ For more information about <classname>GObject</classname>
+ properties we recommend you read the <ulink
+ url="http://developer.gnome.org/doc/API/2.0/gobject/index.html"
+ type="http">GObject manual</ulink> and an introduction to <ulink
+ url="http://le-hacker.org/papers/gobject/index.html" type="http">The
+ Glib Object system</ulink>.
+ </para>
+ <para>
+ A <ulink type="http" url="&URLAPI;gstreamer/html/GstElementFactory.html">
+ <classname>GstElement</classname></ulink> also provides various
+ <classname>GObject</classname> signals that can be used as a flexible
+ callback mechanism. Here, too, you can use <command>gst-inspect</command>
+ to see which signals a specific elements supports. Together, signals
+ and properties are the most basic way in which elements and
+ applications interact.
+ </para>
+ </sect1>
+
+ <sect1 id="section-elements-factories">
+ <title>More about element factories</title>
+ <para>
+ In the previous section, we briefly introduced the <ulink type="http"
+ url="&URLAPI;GstElement.html"><classname>GstElementFactory</classname></ulink>
+ object already as a way to create instances of an element. Element
+ factories, however, are much more than just that. Element factories
+ are the basic types retrieved from the &GStreamer; registry, they
+ describe all plugins and elements that &GStreamer; can create. This
+ means that element factories are useful for automated element
+ instancing, such as what autopluggers do, and for creating lists
+ of available elements, such as what pipeline editing applications
+ (e.g. <ulink type="http"
+ url="http://gstreamer.freedesktop.org/modules/gst-editor.html">&GStreamer;
+ Editor</ulink>) do.
+ </para>
+
+ <sect2 id="section-elements-factories-details">
+ <title>Getting information about an element using a factory</title>
+ <para>
+ Tools like <command>gst-inspect</command> will provide some generic
+ information about an element, such as the person that wrote the
+ plugin, a descriptive name (and a shortname), a rank and a category.
+ The category can be used to get the type of the element that can
+ be created using this element factory. Examples of categories include
+ <classname>Codec/Decoder/Video</classname> (video decoder),
+ <classname>Codec/Encoder/Video</classname> (video encoder),
+ <classname>Source/Video</classname> (a video generator),
+ <classname>Sink/Video</classname> (a video output), and all these
+ exist for audio as well, of course. Then, there's also
+ <classname>Codec/Demuxer</classname> and
+ <classname>Codec/Muxer</classname> and a whole lot more.
+ <command>gst-inspect</command> will give a list of all factories, and
+ <command>gst-inspect <factory-name></command> will list all
+ of the above information, and a lot more.
+ </para>
+ <programlisting><!-- example-begin elementfactory.c --><![CDATA[
+#include <gst/gst.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ GstElementFactory *factory;
+
+ /* init GStreamer */
+ gst_init (&argc, &argv);
+
+ /* get factory */
+ factory = gst_element_factory_find ("sinesrc");
+ if (!factory) {
+ g_print ("You don't have the 'sinesrc' element installed, go get it!\n");
+ return -1;
+ }
+
+ /* display information */
+ g_print ("The '%s' element is a member of the category %s.\n"
+ "Description: %s\n",
+ gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
+ gst_element_factory_get_klass (factory),
+ gst_element_factory_get_description (factory));
+
+ return 0;
+}
+ ]]><!-- example-end elementfactory.c --></programlisting>
+ <para>
+ You can use <function>gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY)</function>
+ to get a list of all the element factories that &GStreamer; knows
+ about.
+ </para>
+ </sect2>
+
+ <sect2 id="section-elements-factories-padtemplates">
+ <title>Finding out what pads an element can contain</title>
+ <para>
+ Perhaps the most powerful feature of element factories is that
+ they contain a full description of the pads that the element
+ can generate, and the capabilities of those pads (in layman words:
+ what types of media can stream over those pads), without actually
+ having to load those plugins into memory. This can be used
+ to provide a codec selection list for encoders, or it can be used
+ for autoplugging purposes for media players. All current
+ &GStreamer;-based media players and autopluggers work this way.
+ We'll look closer at these features as we learn about
+ <classname>GstPad</classname> and <classname>GstCaps</classname>
+ in the next chapter: <xref linkend="chapter-pads"/>
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="section-elements-link" xreflabel="Linking elements">
+ <title>Linking elements</title>
+ <para>
+ By linking a source element with zero or more filter-like
+ elements and finally a sink element, you set up a media
+ pipeline. Data will flow through the elements. This is the
+ basic concept of media handling in &GStreamer;.
+ </para>
+ <figure float="1" id="section-link">
+ <title>Visualisation of three linked elements</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/linked-elements.ℑ"
+ format="&IMAGE;"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ By linking these three elements, we have created a very simple
+ chain of elements. The effect of this will be that the output of
+ the source element (<quote>element1</quote>) will be used as input
+ for the filter-like element (<quote>element2</quote>). The
+ filter-like element will do something with the data and send the
+ result to the final sink element (<quote>element3</quote>).
+ </para>
+ <para>
+ Imagine the above graph as a simple Ogg/Vorbis audio decoder. The
+ source is a disk source which reads the file from disc. The second
+ element is a Ogg/Vorbis audio decoder. The sink element is your
+ soundcard, playing back the decoded audio data. We will use this
+ simple graph to construct an Ogg/Vorbis player later in this manual.
+ </para>
+ <para>
+ In code, the above graph is written like this:
+ </para>
+ <programlisting><!-- example-begin elementlink.c a -->
+#include <gst/gst.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ GstElement *source, *filter, *sink;
+
+ /* init */
+ gst_init (&argc, &argv);
+
+ /* create elements */
+ source = gst_element_factory_make ("fakesrc", "source");
+ filter = gst_element_factory_make ("identity", "filter");
+ sink = gst_element_factory_make ("fakesink", "sink");
+
+ /* link */
+ gst_element_link_many (source, filter, sink, NULL);
+<!-- example-end elementlink.c a -->
+[..]<!-- example-begin elementlink.c b --><!--
+ return 0;
+--><!-- example-end elementlink.c b -->
+<!-- example-begin elementlink.c c -->
+}
+ <!-- example-end elementlink.c c --></programlisting>
+ <para>
+ For more specific behaviour, there are also the functions
+ <function>gst_element_link ()</function> and
+ <function>gst_element_link_pads ()</function>. You can also obtain
+ references to individual pads and link those using various
+ <function>gst_pad_link_* ()</function> functions. See the API
+ references for more details.
+ </para>
+ </sect1>
+
+ <sect1 id="section-elements-states">
+ <title>Element States</title>
+ <para>
+ After being created, an element will not actually perform any actions
+ yet. You need to change elements state to make it do something.
+ &GStreamer; knows four element states, each with a very specific
+ meaning. Those four states are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <classname>GST_STATE_NULL</classname>: this is the default state.
+ This state will deallocate all resources held by the element.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <classname>GST_STATE_READY</classname>: in the ready state, an
+ element has allocated all of its global resources, that is,
+ resources that can be kept within streams. You can think about
+ opening devices, allocating buffers and so on. However, the
+ stream is not opened in this state, so the stream positions is
+ automatically zero. If a stream was previously opened, it should
+ be closed in this state, and position, properties and such should
+ be reset.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <classname>GST_STATE_PAUSED</classname>: in this state, an
+ element has opened the stream, but is not actively processing
+ it. An element should not modify the stream's position, data or
+ anything else in this state. When set back to PLAYING, it should
+ continue processing at the point where it left off as soon as
+ possible.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <classname>GST_STATE_PLAYING</classname>: in the PLAYING state,
+ an element does exactly the same as in the PAUSED state, except
+ that it actually processes data.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ You can change the state of an element using the function
+ <function>gst_element_set_state ()</function>. If you set an element
+ to another state, &GStreamer; will internally traverse all intermediate
+ states. So if you set an element from NULL to PLAYING, &GStreamer;
+ will internally set the element to READY and PAUSED in between.
+ </para>
+ <para>
+ Even though an element in <classname>GST_STATE_PLAYING</classname>
+ is ready for data processing, it will not necessarily do that. If
+ the element is placed in a thread (see <xref
+ linkend="chapter-threads"/>), it will process data automatically.
+ In other cases, however, you will need to <emphasis>iterate</emphasis>
+ the element's container.
+ </para>
+ </sect1>
</chapter>
-<chapter id="chapter-hello-world">
+<chapter id="chapter-helloworld">
<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>
+ This chapter will summarize everything you've learned in the previous
+ chapters. It describes all aspects of a simple &GStreamer; application,
+ including initializing libraries, creating elements, packing elements
+ together in a pipeline and playing this pipeline. By doing all this,
+ you will be able to build a simple Ogg/Vorbis audio player.
</para>
- <sect1 id="section-hello-world">
+ <sect1 id="section-helloworld">
<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.
+ We're going to create a simple first application, a simple Ogg/Vorbis
+ command-line audio player. For this, we will use only standard
+ &GStreamer; components. The player will read a file specified on
+ the command-line. Let's get started!
+ </para>
+ <para>
+ We've learned, in <xref linkend="chapter-init"/>, that the first thing
+ to do in your application is to initialize &GStreamer; by calling
+ <function>gst_init ()</function>. Also, make sure that the application
+ includes <filename>gst/gst.h</filename> so all function names and
+ objects are properly defined. Use <function>#include
+ <gst/gst.h></function> to do that.
+ </para>
+ <para>
+ Next, you'll want to create the different elements using
+ <function>gst_element_factory_make ()</function>. For an Ogg/Vorbis
+ audio player, we'll need a source element that reads files from a
+ disk. &GStreamer; includes this element under the name
+ <quote>filesrc</quote>. Next, we'll need something to parse the
+ file and decoder it into raw audio. &GStreamer; has two elements
+ for this: the first parses Ogg streams into elementary streams (video,
+ audio) and is called <quote>oggdemux</quote>. The second is a Vorbis
+ audio decoder, it's conveniently called <quote>vorbisdec</quote>.
+ Since <quote>oggdemux</quote> creates dynamic pads for each elementary
+ stream, you'll need to set a <quote>new-pad</quote> event handler
+ on the <quote>oggdemux</quote> element, like you've learned in
+ <xref linkend="section-pads-dynamic"/>, to link the Ogg parser and
+ the Vorbis decoder elements together. At last, we'll also need an
+ audio output element, we will use <quote>alsasink</quote>, which
+ outputs sound to an ALSA audio device.
+ </para>
+ <para>
+ The last thing left to do is to add all elements into a container
+ element, a <classname>GstPipeline</classname>, and iterate this
+ pipeline until we've played the whole song. We've previously
+ learned how to add elements to a container bin in <xref
+ linkend="chapter-bins"/>, and we've learned about element states
+ in <xref linkend="section-elements-states"/>. We will use the function
+ <function>gst_bin_sync_children_state ()</function> to synchronize
+ the state of a bin on all of its contained children.
+ </para>
+ <para>
+ Let's now add all the code together to get our very first audio
+ player:
</para>
-
<programlisting>
-<!-- example-begin helloworld.c a -->
-<![CDATA[
-#include <gst/gst.h>
+<!-- example-begin helloworld.c -->
+#include <gst/gst.h>
+
+/*
+ * Global objects are usually a bad thing. For the purpose of this
+ * example, we will use them, however.
+ */
+
+GstElement *pipeline, *source, *parser, *decoder, *sink;
-int
-main (int argc, char *argv[])
+static void
+new_pad (GstElement *element,
+ GstPad *pad,
+ gpointer data)
{
- GstElement *pipeline, *filesrc, *decoder, *audiosink;
+ /* We can now link this pad with the audio decoder and
+ * add both decoder and audio output to the pipeline. */
+ gst_pad_link (pad, gst_element_get_pad (decoder, "sink"));
+ gst_bin_add_many (GST_BIN (pipeline), decoder, sink, NULL);
+
+ /* This function synchronizes a bins state on all of its
+ * contained children. */
+ gst_bin_sync_children_state (GST_BIN (pipeline));
+}
- gst_init(&argc, &argv);
+int
+main (int argc,
+ char *argv[])
+{
+ /* initialize GStreamer */
+ gst_init (&argc, &argv);
+ /* check input arguments */
if (argc != 2) {
- g_print ("usage: %s <mp3 filename>\n", argv[0]);
- exit (-1);
+ g_print ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]);
+ return -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);
-
- /* link src to sink */
- gst_element_link_many (filesrc, decoder, audiosink, NULL);
-
- /* start playing */
+ /* create elements */
+ pipeline = gst_pipeline_new ("audio-player");
+ source = gst_element_factory_make ("filesrc", "file-source");
+ parser = gst_element_factory_make ("oggdemux", "ogg-parser");
+ decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder");
+ sink = gst_element_factory_make ("alsasink", "alsa-output");
+
+ /* set filename property on the file source */
+ g_object_set (G_OBJECT (source), "location", argv[1], NULL);
+
+ /* link together - note that we cannot link the parser and
+ * decoder yet, becuse the parser uses dynamic pads. For that,
+ * we set a new-pad signal handler. */
+ gst_element_link (source, parser);
+ gst_element_link (decoder, sink);
+ g_signal_connect (parser, "new-pad", G_CALLBACK (new_pad), NULL);
+
+ /* put all elements in a bin - or at least the ones we will use
+ * instantly. */
+ gst_bin_add_many (GST_BIN (pipeline), source, parser, NULL);
+
+ /* Now set to playing and iterate. We will set the decoder and
+ * audio output to ready so they initialize their memory already.
+ * This will decrease the amount of time spent on linking these
+ * elements when the Ogg parser emits the new-pad signal. */
+ gst_element_set_state (decoder, GST_STATE_READY);
+ gst_element_set_state (sink, GST_STATE_READY);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
- while (gst_bin_iterate (GST_BIN (pipeline)));
+ /* and now iterate - the rest will be automatic from here on.
+ * When the file is finished, gst_bin_iterate () will return
+ * FALSE, thereby terminating this loop. */
+ while (gst_bin_iterate (GST_BIN (pipeline))) ;
- /* stop the pipeline */
+ /* clean up nicely */
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);
+ return 0;
}
-]]>
-<!-- example-end helloworld.c a -->
+<!-- example-end helloworld.c -->
</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, <ulink type="http"
- url="../../gstreamer/html/GstElement.html"><classname>GstElement</classname></ulink>,
- 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 ("osssink", "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 link the different pads of the elements together like this:
- </para>
- <programlisting>
- /* link src to sink */
- gst_element_link_many (filesrc, decoder, audiosink, NULL);
- </programlisting>
-
+ <!-- FIXME: this image needs updating -->
<para>
We now have created a complete pipeline. We can visualise the
pipeline as follows:
<imagedata fileref="images/hello-world.ℑ" format="&IMAGE;" />
</imageobject>
</mediaobject>
-
</figure>
-
- <para>
- Everything is now set up to start 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 id="section-hello-world-compile">
- <title>Compiling helloworld.c</title>
- <para>
- To compile the helloworld example, use:
- </para>
- <programlisting>
- gcc -Wall `pkg-config gstreamer-&GST_MAJORMINOR; --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
+ <sect1 id="section-helloworld-compilerun">
+ <title>Compiling and Running helloworld.c</title>
+ <para>
+ To compile the helloworld example, use: <command>gcc -Wall
+ $(pkg-config --cflags --libs gstreamer-&GST_MAJORMINOR;)
+ helloworld.c -o helloworld</command>. &GStreamer; makes use of
+ <command>pkg-config</command> to get compiler and linker flags
+ needed to compile this application. If you're running a
+ non-standard installation, make sure the
+ <classname>PKG_CONFIG_PATH</classname> environment variable is
+ set to the correct location (<filename>$libdir/pkgconfig</filename>).
application against the uninstalled location.
</para>
<para>
- You can run the example with
- (substitute helloworld.mp3 with you favorite MP3 file):
+ You can run this example application with <command>./helloworld
+ file.ogg</command>. Substitute <filename>file.ogg</filename>
+ with your favourite Ogg/Vorbis file.
</para>
- <programlisting>
- ./helloworld helloworld.mp3
- </programlisting>
</sect1>
<sect1 id="section-hello-world-conclusion">
<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 the gnomevfssrc element, giving you instant streaming
- from any gnomevfs URL.
- </para>
- <para>
- We can also choose to use another type of sink instead of the audiosink.
- We could use a filesink 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.
+ you can create a more powerful media player with even less effort
+ using higher-level interfaces. We will discuss all that in <xref
+ linkend="part-highlevel"/>. We will first, however, go more in-depth
+ into more advanced &GStreamer; internals.
+ </para>
+ <para>
+ It should be clear from the example that we can very easily replace
+ the <quote>filesrc</quote> element with some other element that
+ reads data from a network, or some other data source element that
+ is better integrated with your desktop environment. Also, you can
+ use other decoders and parsers to support other media types. You
+ can use another audio sink if you're not running Linux, but Mac OS X,
+ Windows or FreeBSD, or you can instead use a filesink to write audio
+ files to disk instead of playing them back. By using an audio card
+ source, you can even do audio capture instead of playback. All this
+ shows the reusability of &GStreamer; elements, which is its greatest
+ advantage.
</para>
</sect1>
</chapter>
-<chapter id="chapter-initialisation">
- <title>Initializing <application>GStreamer</application></title>
+<chapter id="chapter-init">
+ <title>Initializing &GStreamer;</title>
<para>
- When writing a <application>GStreamer</application> application, you can
- simply include <filename class='headerfile'>gst/gst.h</filename> to get
- access to the library functions.
- </para>
- <para>
- Before the <application>GStreamer</application> libraries can be used,
- <function>gst_init</function> has to be called from the main application.
- This call will perform the necessary initialization of the library as
- well as parse the GStreamer-specific command line options.
- </para>
- <para>
- A typical program
- &EXAFOOT;
- would have code to initialize GStreamer that
- looks like this:
+ When writing a &GStreamer; application, you can simply include
+ <filename>gst/gst.h</filename> to get access to the library
+ functions. Besides that, you will also need to intialize the
+ &GStreamer; library.
</para>
- <programlisting>
-<!-- example-begin init.c a -->
-<![CDATA[
-#include <gst/gst.h>
+ <sect1 id="section-init-c">
+ <title>Simple initialization</title>
+ <para>
+ Before the &GStreamer; libraries can be used,
+ <function>gst_init</function> has to be called from the main
+ application. This call will perform the necessary initialization
+ of the library as well as parse the &GStreamer;-specific command
+ line options.
+ </para>
+ <para>
+ A typical program &EXAFOOT; would have code to initialize
+ &GStreamer; that looks like this:
+ </para>
+ <programlisting>
+<!-- example-begin init.c -->
+#include <gst/gst.h>
int
-main (int argc, char *argv[])
+main (int argc,
+ char *argv[])
{
guint major, minor, micro;
return 0;
}
-]]>
-<!-- example-end init.c a -->
- </programlisting>
- <para>
- Use the <symbol>GST_VERSION_MAJOR</symbol>,
- <symbol>GST_VERSION_MINOR</symbol> and <symbol>GST_VERSION_MICRO</symbol>
- macros to get the <application>GStreamer</application> version you are
- building against, or use the function <function>gst_version</function>
- to get the version your application is linked against.
-<!-- FIXME: include an automatically generated list of these options. -->
- </para>
- <para>
- It is also possible to call the <function>gst_init</function> function
- with two <symbol>NULL</symbol> arguments, in which case no command line
- options will be parsed by <application>GStreamer</application>.
- </para>
+<!-- example-end init.c -->
+ </programlisting>
+ <para>
+ Use the <symbol>GST_VERSION_MAJOR</symbol>,
+ <symbol>GST_VERSION_MINOR</symbol> and <symbol>GST_VERSION_MICRO</symbol>
+ macros to get the &GStreamer; version you are building against, or
+ use the function <function>gst_version</function> to get the version
+ your application is linked against. &GStreamer; currently uses a
+ scheme where versions with the same major and minor versions are
+ API-/ and ABI-compatible.
+ </para>
+ <para>
+ It is also possible to call the <function>gst_init</function> function
+ with two <symbol>NULL</symbol> arguments, in which case no command line
+ options will be parsed by <application>GStreamer</application>.
+ </para>
+ </sect1>
+
<sect1>
<title>The popt interface</title>
<para>
-You can also use a popt table to initialize your own parameters as shown in the
-next example:
+ You can also use a popt table to initialize your own parameters as
+ shown in the next example:
</para>
<programlisting>
-<!-- example-begin popt.c a -->
-<![CDATA[
-#include <gst/gst.h>
+<!-- example-begin popt.c -->
+#include <gst/gst.h>
int
-main(int argc, char *argv[])
+main (int argc,
+ char *argv[])
{
gboolean silent = FALSE;
gchar *savefile = NULL;
return 0;
}
-]]>
-<!-- example-end popt.c a -->
-
+<!-- example-end popt.c -->
</programlisting>
<para>
As shown in this fragment, you can use a <ulink
<application>GStreamer</application> options.
</para>
</sect1>
-
</chapter>
-<chapter id="chapter-pads">
- <title>Pads</title>
+<chapter id="chapter-pads" xreflabel="Pads and capabilities">
+ <title>Pads and capabilities</title>
<para>
- As we have seen in <xref linkend="chapter-elements"/>, the pads are the element's
- interface to the outside world.
- </para>
- <para>
- The specific type of media that the element can handle will be exposed by the pads.
- The description of this media type is done with capabilities(see
- <xref linkend="section-caps"/>)
+ As we have seen in <xref linkend="chapter-elements"/>, the pads are
+ the element's interface to the outside world. Data streams from one
+ element's source pad to another element's sink pad. The specific
+ type of media that the element can handle will be exposed by the
+ pad's capabilities. We will talk more on capabilities later in this
+ chapter (see <xref linkend="section-caps"/>).
</para>
- <para>
- Pads are either source or sink pads. The terminology is defined from the
- view of the element itself: elements accept data on their sink pads, and
- send data out on their source pads. Sink pads are drawn on the left,
- while source pads are drawn on the right of an element. In general,
- data flows from left to right in the graph.<footnote>
- <para>
- In reality, there is no objection to data flowing from a
- source pad to the sink pad of an element upstream. Data will, however,
- always flow from a source pad of one element to the sink pad of
- another.
- </para></footnote>
- </para>
+ <sect1 id="section-pads">
+ <title>Pads</title>
+ <para>
+ A pad type is defined by two properties: its direction and its
+ availability. As we've mentioned before, &GStreamer; defines two
+ pad directions: source pads and sink pads. This terminology is
+ defined from the view of within the element: elements receive data
+ on their sink pads and generate data on their source pads.
+ Schematically, sink pads are drawn on the left side of an element,
+ whereas source pads are drawn on the right side of an element. In
+ such graphs, data flows from left to right.
+ <footnote>
+ <para>
+ In reality, there is no objection to data flowing from a
+ source pad to the sink pad of an element upstream (to the
+ left of this element in drawings). Data will, however, always
+ flow from a source pad of one element to the sink pad of
+ another.
+ </para>
+ </footnote>
+ </para>
+
+ <para>
+ Pad directions are very simple compared to pad availability. A pad
+ can have any of three availabilities: always, sometimes and on
+ request. The meaning of those three types is exactly as it says:
+ always pads always exist, sometimes pad exist only in certain
+ cases (and can disappear randomly), and on-request pads appear
+ only if explicitely requested by applications.
+ </para>
- <sect1 id="section-pads-type">
- <title>Types of pad</title>
-
<sect2 id="section-pads-dynamic">
- <title>Dynamic pads</title>
- <para>
+ <title>Dynamic (or sometimes) pads</title>
+ <para>
Some elements might not have all of their pads when the element is
- created. This
- can happen, for example, with an MPEG system demultiplexer. The
- demultiplexer will create its pads at runtime when it detects the
- different elementary streams in the MPEG system stream.
+ created. This can happen, for example, with an Ogg demuxer element.
+ The element will read the Ogg stream and create dynamic pads for
+ each contained elementary stream (vorbis, theora) when it detects
+ such a stream in the Ogg stream. Likewise, it will delete the pad
+ when the stream ends. This principle is very useful for demuxer
+ elements, for example.
</para>
<para>
- Running <application>gst-inspect mpegdemux</application> will show that
- the element has only one pad: a sink pad called 'sink'. The other pads are
- "dormant". You can see this in the pad template because there is
- an 'Exists: Sometimes'
- property. Depending on the type of MPEG file you play, the pads will
- be created. We
- will see that this is very important when you are going to create dynamic
- pipelines later on in this manual.
+ Running <application>gst-inspect oggdemux</application> will show
+ that the element has only one pad: a sink pad called 'sink'. The
+ other pads are <quote>dormant</quote>. You can see this in the pad
+ template because there is an <quote>Exists: Sometimes</quote>
+ property. Depending on the type of Ogg file you play, the pads will
+ be created. We will see that this is very important when you are
+ going to create dynamic pipelines. You can attach a signal handler
+ to an element to inform you when the element has created a new pad
+ from one of its <quote>sometimes</quote> pad templates. The
+ following piece of code is an example of how to do this:
</para>
+ <programlisting><!-- example-begin pad.c a -->
+#include <gst/gst.h>
+
+static void
+cb_new_pad (GstElement *element,
+ GstPad *pad,
+ gpointer data)
+{
+ g_print ("A new pad %s was created\n", gst_pad_get_name (pad));
+
+ /* here, you would setup a new pad link for the newly created pad */
+<!-- example-end pad.c a -->[..]
+<!-- example-begin pad.c b -->
+}
+
+int
+main(int argc, char *argv[])
+{
+ GstElement *pipeline, *source, *demux;
+
+ /* init */
+ gst_init (&argc, &argv);
+
+ /* create elements */
+ pipeline = gst_pipeline_new ("my_pipeline");
+ source = gst_element_factory_make ("filesrc", "source");
+ g_object_set (source, "location", argv[1], NULL);
+ demux = gst_element_factory_make ("oggdemux", "demuxer");
+
+ /* you would normally check that the elements were created properly */
+
+ /* put together a pipeline */
+ gst_bin_add_many (GST_BIN (pipeline), source, demux, NULL);
+ gst_element_link (source, demux);
+
+ /* listen for newly created pads */
+ g_signal_connect (demux, "new-pad", G_CALLBACK (cb_new_pad), NULL);
+
+ /* start the pipeline */
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+ while (gst_bin_iterate (GST_BIN (pipeline)));
+<!--example-end pad.c b -->
+[..]<!-- example-begin pad.c c --><!--
+ return 0;
+--><!-- example-end pad.c c -->
+<!-- example-begin pad.c d -->
+}
+ <!-- example-end pad.c d --></programlisting>
</sect2>
+
<sect2 id="section-pads-request">
<title>Request pads</title>
<para>
An element can also have request pads. These pads are not created
automatically but are only created on demand. This is very useful
- for multiplexers, aggregators and tee elements.
+ for multiplexers, aggregators and tee elements. Aggregators are
+ elements that merge the content of several input streams together
+ into one output stream. Tee elements are the reverse: they are
+ elements that have one input stream and copy this stream to each
+ of their output pads, which are created on request. Whenever an
+ application needs another copy of the stream, it can simply request
+ a new output pad from the tee element.
</para>
<para>
- The tee element, for example, has one input pad and a request padtemplate for the
- output pads. Whenever an element wants to get an output pad from the tee element, it
- has to request the pad.
+ The following piece of code shows how you can request a new output
+ pad from a <quote>tee</quote> element:
+ </para>
+ <programlisting>
+static void
+some_function (GstElement *tee)
+{
+ GstPad * pad;
+
+ pad = gst_element_get_request_pad (tee, "src%d");
+ g_print ("A new pad %s was created\n", gst_pad_get_name (pad));
+
+ /* here, you would link the pad */
+[..]
+}
+ </programlisting>
+ <para>
+ The <function>gst_element_get_request_pad ()</function> method
+ can be used to get a pad from the element based on the name of
+ the pad template. It is also possible to request a pad that is
+ compatible with another pad template. This is very useful if
+ you want to link an element to a multiplexer element and you
+ need to request a pad that is compatible. The method
+ <function>gst_element_get_compatible_pad ()</function> can be
+ used to request a compatible pad, as shown in the next example.
+ It will request a compatible pad from an Ogg multiplexer from
+ any input.
</para>
- </sect2>
+ <programlisting>
+static void
+link_to_multiplexer (GstPad *tolink_pad,
+ GstElement *mux)
+{
+ GstPad *pad;
+
+ pad = gst_element_get_compatible_pad (mux, tolink_pad);
+ gst_pad_link (tolinkpad, pad);
+ g_print ("A new pad %s was created and linked to %s\n",
+ gst_pad_get_name (pad), gst_pad_get_name (tolink_pad));
+}
+ </programlisting>
+ </sect2>
</sect1>
<sect1 id="section-caps">
<title>Capabilities of a pad</title>
<para>
- Since the pads play a very important role in how the element is viewed by the
- outside world, a mechanism is implemented to describe the data that can
- flow through the pad by using capabilities.
+ Since the pads play a very important role in how the element is
+ viewed by the outside world, a mechanism is implemented to describe
+ the data that can flow or currently flows through the pad by using
+ capabilities. Here,w e will briefly describe what capabilities are
+ and how to use them, enough to get an understanding of the concept.
+ For an in-depth look into capabilities and a list of all capabilities
+ defined in &GStreamer;, see the <ulink type="http"
+ url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/index.html">Plugin
+ Writers Guide</ulink>.
</para>
- <para>
- We will briefly describe what capabilities are, enough for you to get a basic understanding
- of the concepts. You will find more information on how to create capabilities in the
- Plugin Writer's Guide.
+ <para>
+ Capabilities are attached to pad templates and to pads. For pad
+ templates, it will describe the types of media that may stream
+ over a pad created from this template. For pads, it can either
+ be a list of possible caps (usually a copy of the pad template's
+ capabilities), in which case the pad is not yet negotiated, or it
+ is the type of media that currently streams over this pad, in
+ which case the pad has been negotiated already.
</para>
- <sect2 id="section-pads-caps">
- <title>Capabilities</title>
- <para>
- Capabilities are attached to a pad in order to describe
- what type of media the pad can handle.
- </para>
- <para>
- Capabilities is shorthand for "capability chain". A capability chain
- is a chain of one capability or more.
- </para>
+ <sect2 id="section-caps-structure">
+ <title>Dissecting capabilities</title>
<para>
- The basic entity is a capability, and is defined by a name, a MIME
- type and a set of properties. A capability can be chained to
- another capability, which is why we commonly refer to a chain of
- capability entities as "capabilities".
- <footnote>
- <para>
- It is important to understand that the term "capabilities" refers
- to a chain of one capability or more. This will be clearer when
- you see the structure definition of a <ulink type="http"
- url="../../gstreamer/html/gstreamer-GstCaps.html"><classname>GstCaps
- </classname></ulink>element.
- </para>
- </footnote>
+ A pads capabilities are described in a <classname>GstCaps</classname>
+ object. Internally, a <ulink type="http"
+ url="../../gstreamer/html/gstreamer-GstCaps.html"><classname>GstCaps</classname></ulink>
+ will contain one or more <ulink type="http"
+ url="../../gstreamer/html/gstreamer-GstStructure.html"><classname>GstStructure</classname></ulink>
+ that will describe one media type. A negotiated pad will have
+ capabilities set that contain exactly <emphasis>one</emphasis>
+ structure. Also, this structure will contain only
+ <emphasis>fixed</emphasis> values. These constraints are not
+ true for unnegotiated pads or pad templates.
</para>
- <para>
- Below is a dump of the capabilities of the element mad, as shown by
- <command>gst-inspect</command>.
- You can see two pads: sink and src. Both pads have capability information attached to them.
- </para>
- <para>
- The sink pad (input pad) is called 'sink' and takes data of MIME type 'audio/mp3'. It also has
- three properties: layer, bitrate and framed.
- </para>
- <para>
- The source pad (output pad) is called 'src' and outputs data of
- MIME type 'audio/raw'. It also has four properties: format, depth,
- rate and channels.
+ <para>
+ As an example, below is a dump of the capabilities of the
+ <quote>vorbisdec</quote> element, which you will get by running
+ <command>gst-inspect vorbisdec</command>. You will see two pads:
+ a source and a sink pad. Both of these pads are always available,
+ and both have capabilities attached to them. The sink pad will
+ accept vorbis-encoded audio data, with the mime-type
+ <quote>audio/x-vorbis</quote>. The source pad will be used
+ to send raw (decoded) audio samples to the next element, with
+ a raw audio mime-type (either <quote>audio/x-raw-int</quote> or
+ <quote>audio/x-raw-float</quote>). The source pad will also
+ contain properties for the audio samplerate and the amount of
+ channels, plus some more that you don't need to worry about
+ for now.
</para>
<programlisting>
-Pads:
- SINK template: 'sink'
+Pad Templates:
+ SRC template: 'src'
Availability: Always
Capabilities:
- 'mad_sink':
- MIME type: 'audio/mp3':
-
- SRC template: 'src'
+ audio/x-raw-float
+ rate: [ 8000, 50000 ]
+ channels: [ 1, 2 ]
+ endianness: 1234
+ width: 32
+ buffer-frames: 0
+
+ SINK template: 'sink'
Availability: Always
Capabilities:
- 'mad_src':
- MIME type: 'audio/raw':
- format: String: int
- endianness: Integer: 1234
- width: Integer: 16
- depth: Integer: 16
- channels: Integer range: 1 - 2
- law: Integer: 0
- signed: Boolean: TRUE
- rate: Integer range: 11025 - 48000
+ audio/x-vorbis
</programlisting>
</sect2>
- <sect2 id="section-pads-props">
- <title>What are properties ?</title>
+
+ <sect2 id="section-caps-props">
+ <title>Properties and values</title>
<para>
Properties are used to describe extra information for
capabilities. A property consists of a key (a string) and
a value. There are different possible value types that can be used:
</para>
-
<itemizedlist>
<listitem>
<para>
- basic types:
+ Basic types, this can be pretty much any
+ <classname>GType</classname> registered with Glib. Those
+ properties indicate a specific, non-dynamic value for this
+ property. Examples include:
</para>
<itemizedlist>
<listitem>
<para>
- an integer value: the property has this exact value.
+ An integer value (<classname>G_TYPE_INT</classname>):
+ the property has this exact value.
</para>
</listitem>
<listitem>
<para>
- a boolean value: the property is either TRUE or FALSE.
+ A boolean value (<classname>G_TYPE_BOOLEAN</classname>):
+ the property is either TRUE or FALSE.
</para>
</listitem>
<listitem>
<para>
- a fourcc value: this is a value that is commonly used to
- describe an encoding for video,
- as used for example by the AVI specification.
- <footnote><para>
- fourcc values consist of four bytes.
- <ulink url="http://www.fourcc.org" type="http">The FOURCC
- Definition List</ulink> is the most complete resource
- on the allowed fourcc values.
- </para></footnote>
+ A float value (<classname>G_TYPE_FLOAT</classname>):
+ the property has this exact floating point value.
</para>
</listitem>
<listitem>
<para>
- a float value: the property has this exact floating point value.
- </para>
- </listitem>
- <listitem>
- <para>
- a string value.
+ A string value (<classname>G_TYPE_STRING</classname>):
+ the property contains a UTF-8 string.
</para>
</listitem>
</itemizedlist>
</listitem>
-
<listitem>
<para>
- range types:
+ Range types are <classname>GType</classname>s registered by
+ &GStreamer; to indicate a range of possible values. They are
+ used for indicating allowed audio samplerate values or
+ supported video sizes. The two types defined in &GStreamer;
+ are:
</para>
<itemizedlist>
<listitem>
<para>
- an integer range value: the property denotes a range of
- possible integers. For example, the wavparse element has
- a source pad where the "rate" property can go from 8000 to
- 48000.
+ An integer range value
+ (<classname>GST_TYPE_INT_RANGE</classname>): the property
+ denotes a range of possible integers, with a lower and an
+ upper boundary. The <quote>vorbisdec</quote> element, for
+ example, has a rate property that can be between 8000 and
+ 50000.
</para>
</listitem>
<listitem>
<para>
- a float range value: the property denotes a range of possible
- floating point values.
+ A float range value
+ (<classname>GST_TYPE_FLOAT_RANGE</classname>): the property
+ denotes a range of possible floating point values, with a
+ lower and an upper boundary.
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>
- a list value: the property can take any value from a list of
- basic value types or range types.
+ A list value (<classname>GST_TYPE_LIST</classname>): the
+ property can take any value from a list of basic values
+ given in this list.
</para>
</listitem>
</itemizedlist>
+ </sect2>
+ </sect1>
+
+ <sect1 id="section-caps-api">
+ <title>What capabilities are used for</title>
+ <para>
+ Capabilities describe the type of data that is streamed between
+ two pads, or that one pad (template) supports. This makes them
+ very useful for various purposes:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Autoplugging: automatically finding elements to link to a
+ pad based on its capabilities. All autopluggers use this
+ method.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Compatibility detection: when two pads are linked, &GStreamer;
+ can verify if the two pads are talking about the same media
+ type. The process of linking two pads and checking if they
+ are compatible is called <quote>caps negotiation</quote>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Metadata: by reading the capabilities from a pad, applications
+ can provide information about the type of media that is being
+ streamed over the pad, which is information about the stream
+ thatis currently being played back.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Filtering: an application can use capabilities to limit the
+ possible media types that can stream between two pads to a
+ specific subset of their supported stream types. An application
+ can, for example, use <quote>filtered caps</quote> to set a
+ specific (non-fixed) video size that will stream between two
+ pads.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <sect2 id="section-caps-metadata">
+ <title>Using capabilities for metadata</title>
+ <para>
+ A pad can have a set (i.e. one or more) of capabilities attached
+ to it. You can get values of properties in a set of capabilities
+ by querying individual properties of one structure. You can get
+ a structure from a caps using
+ <function>gst_caps_get_structure ()</function>:
+ </para>
+ <programlisting>
+static void
+read_video_props (GstCaps *caps)
+{
+ gint width, height;
+ const GstStructure *str;
+
+ str = gst_caps_get_structure (caps);
+ if (!gst_structure_get_int (str, "width", &width) ||
+ !gst_structure_get_int (str, "height", &height)) {
+ g_print ("No width/height available\n");
+ return;
+ }
+
+ g_print ("The video size of this set of capabilities is %dx%d\n",
+ width, height);
+}
+ </programlisting>
</sect2>
- <sect2 id="section-pads-caps-use">
- <title>What capabilities are used for</title>
+
+ <sect2 id="section-caps-filter">
+ <title>Creating capabilities for filtering</title>
<para>
- Capabilities describe in great detail the type of media that is handled by the pads.
- They are mostly used for:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Autoplugging: automatically finding plugins for a set of capabilities
- </para>
- </listitem>
- <listitem>
- <para>
- Compatibility detection: when two pads are linked, <application>GStreamer</application>
- can verify if the two pads are talking about the same media types.
- The process of linking two pads and checking if they are compatible
- is called "caps negotiation".
- </para>
- </listitem>
- </itemizedlist>
+ While capabilities are mainly used inside a plugin to describe the
+ media type of the pads, the application programmer also has to have
+ basic understanding of capabilities in order to interface with the
+ plugins, especially when using filtered caps. When you're using
+ filtered caps or fixation, you're limiting the allowed types of
+ media that can stream between two pads to a subset of their supported
+ media types. You do this by filtering using your own set of
+ capabilities. In order to do this, you need to create your own
+ <classname>GstCaps</classname>. The simplest way to do this is by
+ using the convenience function <function>gst_caps_new_simple
+ ()</function>:
+ </para>
+ <programlisting>
+static void
+link_pads_with_filter (GstPad *one,
+ GstPad *other)
+{
+ GstCaps *caps;
+
+ caps = gst_caps_new_simple ("video/x-raw-yuv",
+ "width", G_TYPE_INT, 384,
+ "height", G_TYPE_INT, 288,
+ "framerate", G_TYPE_DOUBLE, 25.,
+ NULL);
+ gst_pad_link_filtered (one, other, caps);
+}
+ </programlisting>
+ <para>
+ In some cases, you will want to create a more elaborate set of
+ capabilities to filter a link between two pads. Then, this function
+ is too simplistic and you'll want to use the method
+ <function>gst_caps_new_full ()</function>:
+ </para>
+ <programlisting>
+static void
+link_pads_with_filter (GstPad *one,
+ GstPad *other)
+{
+ GstCaps *caps;
+
+ caps = gst_caps_new_full (
+ gst_structure_new ("video/x-raw-yuv",
+ "width", G_TYPE_INT, 384,
+ "height", G_TYPE_INT, 288,
+ "framerate", G_TYPE_DOUBLE, 25.,
+ NULL),
+ gst_structure_new ("video/x-raw-rgb",
+ "width", G_TYPE_INT, 384,
+ "height", G_TYPE_INT, 288,
+ "framerate", G_TYPE_DOUBLE, 25.,
+ NULL),
+ NULL);
+
+ gst_pad_link_filtered (one, other, caps);
+}
+ </programlisting>
+ <para>
+ See the API references for the full API of
+ <classname>GstStructure</classname> and
+ <classname>GstCaps</classname>.
+ </para>
</sect2>
</sect1>
+
+ <sect1 id="section-pads-ghost">
+ <title>Ghost pads</title>
+ <para>
+ You can see from <xref linkend="section-bin-noghost-img"/> how a bin
+ has no pads of its own. This is where "ghost pads" come into play.
+ </para>
+ <figure float="1" id="section-bin-noghost-img">
+ <title>Visualisation of a <ulink type="http"
+ url="../../gstreamer/html/GstBin.html"><classname>GstBin</classname></ulink>
+ element without ghost pads</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/bin-element-noghost.ℑ"
+ format="&IMAGE;"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ A ghost pad is a pad from some element in the bin that can be
+ accessed directly from the bin as well. Compare it to a symbolic
+ link in UNIX filesystems. Using ghost pads on bins, the bin also
+ has a pad and can transparently be used as an element in other
+ parts of your code.
+ </para>
+
+ <figure float="1" id="section-bin-ghost-img">
+ <title>Visualisation of a <ulink type="http"
+ url="../../gstreamer/html/GstBin.html"><classname>GstBin</classname></ulink>
+ element with a ghost pad</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/bin-element-ghost.ℑ"
+ format="&IMAGE;"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ <xref linkend="section-bin-ghost-img"/> is a representation of a
+ ghost pad. The sink pad of element one is now also a pad of the bin.
+ Obviously, ghost pads can be added to any type of elements, not just
+ to a <classname>GstBin</classname>.
+ </para>
+ <para>
+ A ghostpad is created using the function
+ <function>gst_element_add_ghost_pad ()</function>:
+ </para>
+ <programlisting><!-- example-begin ghostpad.c a -->
+#include <gst/gst.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ GstElement *bin, *sink;
+
+ /* init */
+ gst_init (&argc, &argv);
+
+ /* create element, add to bin, add ghostpad */
+ sink = gst_element_factory_make ("fakesink", "sink");
+ bin = gst_bin_new ("mybin");
+ gst_bin_add (GST_BIN (bin), sink);
+ gst_element_add_ghost_pad (bin,
+ gst_element_get_pad (sink, "sink"), "sink");
+<!-- example-end ghostpad.c a -->
+[..]<!-- example-begin ghostpad.c b --><!--
+ return 0;
+--><!-- example-end ghostpad.c b -->
+<!-- example-begin ghostpad.c c -->
+}
+ <!-- example-end ghostpad.c c --></programlisting>
+ <para>
+ In the above example, the bin now also has a pad: the pad called
+ <quote>sink</quote> of the given element. The bin can, from here
+ on, be used as a substitute for the sink element. You could, for
+ example, link another element to the bin.
+ </para>
+ </sect1>
</chapter>
</para>
</listitem>
</itemizedlist>
+
+ <para>
+ All plugins should implement one function, <function>plugin_init</function>,
+ that creates all the element factories and registers all the type
+ definitions contained in the plugin.
+ Without this function, a plugin cannot be registered.
+ </para>
+ <para>
+ The plugins are maintained in the plugin system. Optionally, the
+ type definitions and the element factories can be saved into an XML
+ representation so that the plugin system does not have to load all
+ available plugins in order to know their definition.
+ </para>
+
+ <para>
+ The basic plugin structure has the following fields:
+ </para>
+ <programlisting>
+typedef struct _GstPlugin GstPlugin;
+
+struct _GstPlugin {
+ gchar *name; /* name of the plugin */
+ gchar *longname; /* long name of plugin */
+ gchar *filename; /* filename it came from */
+
+ GList *types; /* list of types provided */
+ gint numtypes;
+ GList *elements; /* list of elements provided */
+ gint numelements;
+ GList *autopluggers; /* list of autopluggers provided */
+ gint numautopluggers;
+
+ gboolean loaded; /* if the plugin is in memory */
+};
+ </programlisting>
+
+ <para>
+ You can query a <classname>GList</classname> of available plugins with the
+ function <function>gst_plugin_get_list</function> as this example shows:
+ </para>
+ <programlisting>
+ GList *plugins;
+
+ plugins = gst_plugin_get_list ();
+
+ while (plugins) {
+ GstPlugin *plugin = (GstPlugin *)plugins->data;
+
+ g_print ("plugin: %s\n", gst_plugin_get_name (plugin));
+
+ plugins = g_list_next (plugins);
+ }
+ </programlisting>
</chapter>
+++ /dev/null
-<chapter id="chapter-bins-api">
- <title>Bins</title>
- <sect1 id="section-bin-create">
- <title>Creating a bin</title>
- <para>
- Bins are created in the same way that other elements are created. ie.
- using an element factory, or any of the associated convenience functions:
- </para>
- <programlisting>
- GstElement *bin, *thread, *pipeline;
-
- /* create a new bin called 'mybin'. this bin will be only for organizational purposes; a normal
- GstBin doesn't affect plan generation */
- bin = gst_element_factory_make ("bin", "mybin");
-
- /* create a new thread, and give it a unique name */
- thread = gst_element_factory_make ("thread", NULL);
-
- /* the core bins (GstBin, GstThread, GstPipeline) also have convenience APIs,
- gst_<bintype>_new (). these are equivalent to the gst_element_factory_make () syntax. */
- pipeline = gst_pipeline_new ("pipeline_name");
- </programlisting>
- </sect1>
-
- <sect1 id="section-bin-adding">
- <title>Adding elements to a bin</title>
- <para>
- Elements are added to a bin with the following code sample:
- </para>
- <programlisting>
- GstElement *element;
- GstElement *bin;
-
- bin = gst_bin_new ("mybin");
-
- element = gst_element_factory_make ("mad", "decoder");
- gst_bin_add (GST_BIN (bin), element);
- ...
- </programlisting>
- <para>
- Bins and threads can be added to other bins too. This allows you to create nested bins. Pipelines shouldn't be added to any other element, though.
- They are toplevel bins and they are directly linked to the scheduler.
- </para>
- <para>
- To get an element from the bin you can use:
- </para>
- <programlisting>
- GstElement *element;
-
- element = gst_bin_get_by_name (GST_BIN (bin), "decoder");
- ...
- </programlisting>
- <para>
- You can see that the name of the element becomes very handy
- for retrieving the element from a bin by using the element's
- name. gst_bin_get_by_name () will recursively search nested bins.
- </para>
- <para>
- To get a list of elements in a bin, use:
- </para>
- <programlisting>
- GList *elements;
-
- elements = gst_bin_get_list (GST_BIN (bin));
-
- while (elements) {
- GstElement *element = GST_ELEMENT (elements->data);
-
- g_print ("element in bin: %s\n", GST_OBJECT_NAME (GST_OBJECT (element)));
-
- elements = g_list_next (elements);
- }
- ...
- </programlisting>
- <para>
- To remove an element from a bin, use:
- </para>
- <programlisting>
- GstElement *element;
-
- gst_bin_remove (GST_BIN (bin), element);
- ...
- </programlisting>
- <para>
- To add many elements to a bin at the same time, use the gst_bin_add_many
- () function. Remember to pass NULL as the last argument.
- </para>
- <programlisting>
- GstElement *filesrc, *decoder, *audiosink;
- GstBin *bin;
-
- /* instantiate the elements and the bins... */
-
- gst_bin_add_many (bin, filesrc, decoder, audiosink, NULL);
- </programlisting>
- </sect1>
-
- <sect1 id="section-bin-custom">
- <title>Custom bins</title>
- <para>
- The application programmer can create custom bins packed with elements
- to perform a specific task. This allows you to write an MPEG audio
- decoder with just the following lines of code:
- </para>
- <programlisting>
-
- /* create the mp3player element */
- GstElement *mp3player = gst_element_factory_make ("mp3player", "mp3player");
- /* set the source mp3 audio file */
- g_object_set (G_OBJECT (mp3player), "location", "helloworld.mp3", NULL);
- /* start playback */
- gst_element_set_state (GST_ELEMENT (mp3player), GST_STATE_PLAYING);
- ...
- /* pause playback */
- gst_element_set_state (GST_ELEMENT (mp3player), GST_STATE_PAUSED);
- ...
- /* stop */
- gst_element_set_state (GST_ELEMENT (mp3player), GST_STATE_NULL);
- </programlisting>
- <para>
- Note that the above code assumes that the mp3player bin derives itself
- from a <ulink type="http"
- url="../../gstreamer/html/GstThread.html"><classname>GstThread</classname></ulink>, which begins to play as soon
- as its state is set to PLAYING. Other bin types may need explicit
- iteration. For more information, see <xref linkend="chapter-threads"/>.
- </para>
- <para>
- Custom bins can be created with a plugin or an XML description. You
- will find more information about creating custom bin in the Plugin
- Writers Guide (FIXME ref).
- </para>
- </sect1>
-
- <sect1 id="section-bin-ghostpads">
- <title>Ghost pads</title>
- <para>
- You can see from <xref linkend="section-bin-noghost-img"/> how a bin has no pads of its own.
- This is where "ghost pads" come into play.
- </para>
- <figure float="1" id="section-bin-noghost-img">
- <title>Visualisation of a <ulink type="http"
- url="../../gstreamer/html/GstBin.html"><classname>GstBin</classname></ulink> element without ghost pads</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/bin-element-noghost.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- A ghost pad is a pad from some element in the bin that has been promoted to the bin.
- This way, the bin also has a pad. The bin becomes just another element with a pad and
- you can then use the bin just like any other element. This is a very important feature
- for creating custom bins.
- </para>
-
- <figure float="1" id="section-bin-ghost-img">
- <title>Visualisation of a <ulink type="http"
- url="../../gstreamer/html/GstBin.html"><classname>GstBin</classname></ulink> element with a ghost pad</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/bin-element-ghost.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- <xref linkend="section-bin-ghost-img"/>
- is a representation of a ghost pad. The sink pad of element one is now also a pad
- of the bin.
- </para>
- <para>
- Ghost pads can actually be added to all <ulink type="http"
- url="../../gstreamer/html/GstElement.html"><classname>GstElement</classname></ulink>s and not just
- <ulink type="http" url="../../gstreamer/html/GstBin.html"><classname>GstBin</classname></ulink>s. Use the following code example to add a ghost pad to a bin:
- </para>
- <programlisting>
- GstElement *bin;
- GstElement *element;
-
- element = gst_element_factory_create ("mad", "decoder");
- bin = gst_bin_new ("mybin");
-
- gst_bin_add (GST_BIN (bin), element);
-
- gst_element_add_ghost_pad (bin, gst_element_get_pad (element, "sink"), "sink");
-
- </programlisting>
- <para>
- In the above example, the bin now also has a pad: the pad called 'sink'
- of the given element.
- </para>
- <para>
- We can now, for example, link the source pad of a filesrc element
- to the bin with:
- </para>
- <programlisting>
- GstElement *filesrc;
-
- filesrc = gst_element_factory_create ("filesrc", "disk_reader");
-
- gst_element_link_pads (filesrc, "src", bin, "sink");
- ...
- </programlisting>
- </sect1>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-bins">
- <title>Bins</title>
- <para>
- A bin is a container element. You can add elements to a bin. Since a bin is
- an element itself, it can also be added to another bin.
- </para>
- <para>
- Bins allow you to combine a group of linked elements into one logical element. You do
- not deal with the individual elements anymore but with just one element, the bin.
- We will see that this is extremely powerful when you are going to construct
- complex pipelines since it allows you to break up the pipeline in smaller chunks.
- </para>
- <para>
- The bin will also manage the elements contained in it. It will figure out how
- the data will flow in the bin and generate an optimal plan for that data flow. Plan
- generation is one of the most complicated procedures in GStreamer.
- </para>
-
- <figure float="1" id="section-bin-img">
- <title>Visualisation of a bin with some elements in it</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/bin-element.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>
- There are two specialized bins available to the GStreamer programmer:
-
- <itemizedlist>
- <listitem>
- <para>
- a pipeline: a generic container that allows scheduling of the
- containing elements. The toplevel bin has to be a pipeline.
- Every application thus needs at least one of these.
- </para>
- </listitem>
- <listitem>
- <para>
- a thread: a bin that will be run in a separate execution thread.
- You will have to use this bin if you have to carefully
- synchronize audio and video, or for buffering. You will learn
- more about threads in <xref linkend="chapter-threads"/>.
- </para>
- </listitem>
- </itemizedlist>
- </para>
-</chapter>
+++ /dev/null
-<chapter id="chapter-buffers-api">
- <title>Buffers</title>
- <para>
- </para>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-buffers">
- <title>Buffers</title>
- <para>
- Buffers contain the data that will flow through the pipeline you have
- created. A source element will typically create a new buffer and pass
- it through a pad to the next element in the chain. When using the
- GStreamer infrastructure to create a media pipeline you will not have
- to deal with buffers yourself; the elements will do that for you.
- </para>
- <para>
- A buffer consists of:
-
- <itemizedlist>
- <listitem>
- <para>
- a pointer to a piece of memory.
- </para>
- </listitem>
- <listitem>
- <para>
- the size of the memory.
- </para>
- </listitem>
- <listitem>
- <para>
- a timestamp for the buffer.
- </para>
- </listitem>
- <listitem>
- <para>
- A refcount that indicates how many elements are using this
- buffer. This refcount will be used to destroy the buffer when no
- element has a reference to it.
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>
- <!-- FIXME: this is outdated, there is no GstBufferPool in gst-0.8.X -->
- GStreamer provides functions to create custom buffer create/destroy algorithms, called
- a <classname>GstBufferPool</classname>. This makes it possible to efficiently
- allocate and destroy buffer memory. It also makes it possible to exchange memory between
- elements by passing the <classname>GstBufferPool</classname>. A video element can,
- for example, create a custom buffer allocation algorithm that creates buffers with XSHM
- as the buffer memory. An element can use this algorithm to create and fill the buffer
- with data.
- </para>
-
- <para>
- The simple case is that a buffer is created, memory allocated, data put
- in it, and passed to the next element. That element reads the data, does
- something (like creating a new buffer and decoding into it), and
- unreferences the buffer. This causes the data to be freed and the buffer
- to be destroyed. A typical MPEG audio decoder works like this.
- </para>
-
- <para>
- A more complex case is when the filter modifies the data in place. It
- does so and simply passes on the buffer to the next element. This is just
- as easy to deal with. An element that works in place has to be careful when
- the buffer is used in more than one element; a copy on write has to made in this
- situation.
- </para>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-clocks">
- <title>Clocks in GStreamer</title>
- <para>
- </para>
-</chapter>
+++ /dev/null
-<chapter id="chapter-components">
- <title>Components</title>
-
- <para>
- FIXME: This chapter is way out of date.
- </para>
-
- <para>
- <application>GStreamer</application> includes components that people can include
- in their programs.
- </para>
-
- <sect1 id="section-components-gst-play">
- <title>GstPlay</title>
- <para>
- GstPlay is a GtkWidget with a simple API to play, pause and stop a media file.
- </para>
-
- </sect1>
-
- <sect1 id="section-components-gst-media-play">
- <title>GstMediaPlay</title>
- <para>
- GstMediaPlay is a complete player widget.
- </para>
-
- </sect1>
-
- <sect1 id="section-components-gst-editor">
- <title>GstEditor</title>
- <para>
- GstEditor is a set of widgets to display a graphical representation of a
- pipeline.
- </para>
- </sect1>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-cothreads">
- <title>Cothreads</title>
- <para>
- Cothreads are user-space threads that greatly reduce context switching overhead introduced by
- regular kernel threads. Cothreads are also used to handle the more complex elements. They differ
- from other user-space threading libraries in that they are scheduled explictly by GStreamer.
- </para>
- <para>
- A cothread is created by a <ulink type="http"
- url="../../gstreamer/html/GstBin.html"><classname>GstBin</classname></ulink>
- whenever an element is found
- inside the bin that has one or more of the following properties:
- <itemizedlist>
- <listitem>
- <para>
- The element is loop-based instead of chain-based
- </para>
- </listitem>
- <listitem>
- <para>
- The element has multiple input pads
- </para>
- </listitem>
- <listitem>
- <para>
- The element has the MULTI_IN flag set
- </para>
- </listitem>
- </itemizedlist>
- The <ulink type="http" url="../../gstreamer/html/GstBin.html"><classname>GstBin
- </classname></ulink> will create a cothread context for all the elements
- in the bin so that the elements will interact in cooperative
- multithreading.
- </para>
- <para>
- Before proceding to the concept of loop-based elements we will first
- explain the chain-based elements.
- </para>
-
- <sect1 id="section-chain-based">
- <title>Chain-based elements</title>
- <para>
- Chain based elements receive a buffer of data and are supposed
- to handle the data and perform a gst_pad_push.
- </para>
- <para>
- The basic main function of a chain-based element is like:
- </para>
- <programlisting>
-static void
-chain_function (GstPad *pad, GstBuffer *buffer)
-{
- GstBuffer *outbuffer;
-
- ....
- // process the buffer, create a new outbuffer
- ...
-
- gst_pad_push (srcpad, outbuffer);
-}
- </programlisting>
- <para>
- Chain based function are mainly used for elements that have a one to one
- relation between their input and output behaviour. An example of such an
- element can be a simple video blur filter. The filter takes a buffer in, performs
- the blur operation on it and sends out the resulting buffer.
- </para>
- <para>
- Another element, for example, is a volume filter. The filter takes audio samples as
- input, performs the volume effect and sends out the resulting buffer.
- </para>
-
- </sect1>
-
- <sect1 id="section-loop-based">
- <title>Loop-based elements</title>
- <para>
- As opposed to chain-based elements, loop-based elements enter an
- infinite loop that looks like this:
-
- <programlisting>
- GstBuffer *buffer, *outbuffer;
-
- while (1) {
- buffer = gst_pad_pull (sinkpad);
- ...
- // process buffer, create outbuffer
- while (!done) {
- ....
- // optionally request another buffer
- buffer = gst_pad_pull (sinkpad);
- ....
- }
- ...
- gst_pad_push (srcpad, outbuffer);
- }
- </programlisting>
-
- The loop-based elements request a buffer whenever they need one.
- </para>
-
- <para>
- When the request for a buffer cannot be immediately satisfied, the control
- will be given to the source element of the loop-based element until it
- performs a push on its source pad. At that time the control is handed
- back to the loop-based element, etc... The execution trace can get
- fairly complex using cothreads when there are multiple input/output
- pads for the loop-based element. Cothread switches are performed within
- the call to gst_pad_pull and gst_pad_push; from the perspective of
- the loop-based element, it just "appears" that gst_pad_push (or _pull)
- might take a long time to return.
- </para>
- <para>
- Loop based elements are mainly used for the more complex elements
- that need a specific amount of data before they can start to produce
- output. An example of such an element is the MPEG video decoder. The
- element will pull a buffer, perform some decoding on it and optionally
- request more buffers to decode, and when a complete video frame has
- been decoded, a buffer is sent out. For example, any plugin using the
- bytestream library will need to be loop-based.
- </para>
- <para>
- There is no problem in putting cothreaded elements into a <ulink
- type="http" url="../../gstreamer/html/GstThread.html"><classname>GstThread
- </classname></ulink> to
- create even more complex pipelines with both user and kernel space threads.
- </para>
-
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-debugging">
- <title>Debugging</title>
- <para>
- GStreamer has an extensive set of debugging tools for
- plugin developers.
- </para>
-
- <sect1 id="section-debugging-command-line">
- <title>Command line options</title>
- <para>
- Applications using the GStreamer libraries accept the following set
- of command line argruments that help in debugging.
- </para>
-
- <para>
- <itemizedlist>
- <listitem>
- <para>
- <option>--gst-debug-help</option>
- Print available debug categories and exit
- </para>
- </listitem>
- <listitem>
- <para>
- <option>--gst-debug-level=<replaceable>LEVEL</replaceable></option>
- Sets the default debug level from 0 (no output) to 5 (everything)
- </para>
- </listitem>
- <listitem>
- <para>
- <option>--gst-debug=<replaceable>LIST</replaceable></option>
- Comma-separated list of category_name:level pairs to set specific
- levels for the individual categories.
- Example: GST_AUTOPLUG:5,GST_ELEMENT_*:3
- </para>
- </listitem>
- <listitem>
- <para>
- <option>--gst-debug-no-color</option>
- Disable color debugging output
- </para>
- </listitem>
- <listitem>
- <para>
- <option>--gst-debug-disable</option>
- Disable debugging
- </para>
- </listitem>
- <listitem>
- <para>
- <option>--gst-plugin-spew</option>
- Enable printout of errors while loading GStreamer plugins.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </sect1>
-
- <sect1 id="section-debugging-adding">
- <title>Adding debugging to a plugin</title>
- <para>
-Plugins can define their own categories for the debugging system.
-Three things need to happen:
- <itemizedlist>
- <listitem>
- <para>
-The debugging variable needs to be defined somewhere.
-If you only have one source file, you can Use GST_DEBUG_CATEGORY_STATIC to
-define a static debug category variable.
- </para>
- <para>
-If you have multiple source files, you should define the variable using
-GST_DEBUG_CATEGORY in the source file where you're initializing the debug
-category. The other source files should use GST_DEBUG_CATEGORY_EXTERN to
-declare the debug category variable, possibly by including a common header
-that has this statement.
- </para>
- </listitem>
- <listitem>
- <para>
-The debugging category needs to be initialized. This is done through
-GST_DEBUG_CATEGORY_INIT.
-If you're using a global debugging category for the complete plugin,
-you can call this in the
-plugin's <function>plugin_init</function>.
-If the debug category is only used for one of the elements, you can call it
-from the element's <function>_class_init</function> function.
- </para>
- </listitem>
- <listitem>
- <para>
-You should also define a default category to be used for debugging. This is
-done by defining GST_CAT_DEFAULT for the source files where you're using
-debug macros.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
-Elements can then log debugging information using the set of macros. There
-are five levels of debugging information:
- <orderedlist>
- <listitem>
-<para>ERROR for fatal errors (for example, internal errors)</para>
- </listitem>
- <listitem>
-<para>WARNING for warnings</para>
- </listitem>
- <listitem>
-<para>INFO for normal information</para>
- </listitem>
- <listitem>
-<para>DEBUG for debug information (for example, device parameters)</para>
- </listitem>
- <listitem>
-<para>LOG for regular operation information (for example, chain handlers)</para>
- </listitem>
- </orderedlist>
- </para>
- <para>
-For each of these levels, there are four macros to log debugging information.
-Taking the LOG level as an example, there is
- <itemizedlist>
- <listitem>
- <para>
- GST_CAT_LOG_OBJECT logs debug information in the given GstCategory
- and for the given GstObject
- </para>
- </listitem>
- <listitem>
- <para>
- GST_CAT_LOG logs debug information in the given GstCategory
- but without a GstObject (this is useful for libraries, for example)
- </para>
- </listitem>
- <listitem>
- <para>
- GST_LOG_OBJECT logs debug information in the default GST_CAT_DEFAULT
- category (as defined somewhere in the source), for the given GstObject
- </para>
- </listitem>
- <listitem>
- <para>
- GST_LOG logs debug information in the default GST_CAT_DEFAULT
- category, without a GstObject
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </sect1>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-dparams">
- <title>Dynamic Parameters</title>
-
- <sect1 id="section-dparams-getting-started">
- <title>Getting Started</title>
- <para>
- The Dynamic Parameters subsystem is contained within the
- <filename>gstcontrol</filename> library.
-
- You need to include the header in your application's source file:
- </para>
- <programlisting>
-...
-#include <gst/gst.h>
-#include <gst/control/control.h>
-...
- </programlisting>
- <para>
- Your application should link to the shared library <filename>gstcontrol</filename>.
- </para>
- <para>
- The <filename>gstcontrol</filename> library needs to be initialized
- when your application is run. This can be done after the the GStreamer
- library has been initialized.
- </para>
- <programlisting>
- ...
- gst_init(&argc,&argv);
- gst_control_init(&argc,&argv);
- ...
- </programlisting>
- </sect1>
-
- <sect1 id="section-dparams-creating">
- <title>Creating and Attaching Dynamic Parameters</title>
- <para>
- Once you have created your elements you can create and attach dparams to them.
- First you need to get the element's dparams manager. If you know exactly what kind of element
- you have, you may be able to get the dparams manager directly. However if this is not possible,
- you can get the dparams manager by calling <filename>gst_dpman_get_manager</filename>.
- </para>
- <para>
- Once you have the dparams manager, you must set the mode that the manager will run in.
- There is currently only one mode implemented called <filename>"synchronous"</filename> - this is used for real-time
- applications where the dparam value cannot be known ahead of time (such as a slider in a GUI).
- The mode is called <filename>"synchronous"</filename> because the dparams are polled by the element for changes before
- each buffer is processed. Another yet-to-be-implemented mode is <filename>"asynchronous"</filename>. This is used when
- parameter changes are known ahead of time - such as with a timelined editor. The mode is called
- <filename>"asynchronous"</filename> because parameter changes may happen in the middle of a buffer being processed.
- </para>
- <programlisting>
- GstElement *sinesrc;
- GstDParamManager *dpman;
- ...
- sinesrc = gst_element_factory_make("sinesrc","sine-source");
- ...
- dpman = gst_dpman_get_manager (sinesrc);
- gst_dpman_set_mode(dpman, "synchronous");
- </programlisting>
- <para>
- If you don't know the names of the required dparams for your element you can call
- <filename>gst_dpman_list_dparam_specs(dpman)</filename> to get a NULL terminated array of param specs.
- This array should be freed after use. You can find the name of the required dparam by calling
- <filename>g_param_spec_get_name</filename> on each param spec in the array. In our example,
- <filename>"volume"</filename> will be the name of our required dparam.
- </para>
- <para>
- Each type of dparam currently has its own <filename>new</filename> function. This may eventually
- be replaced by a factory method for creating new instances. A default dparam instance can be created
- with the <filename>gst_dparam_new</filename> function. Once it is created it can be attached to a
- required dparam in the element.
- </para>
- <programlisting>
- GstDParam *volume;
- ...
- volume = gst_dparam_new(G_TYPE_DOUBLE);
- if (gst_dpman_attach_dparam (dpman, "volume", volume)){
- /* the dparam was successfully attached */
- ...
- }
- </programlisting>
- </sect1>
-
- <sect1 id="section-dparams-changing">
- <title>Changing Dynamic Parameter Values</title>
- <para>
- All interaction with dparams to actually set the dparam value is done through simple GObject properties.
- There is a property value for each type that dparams supports - these currently being
- <filename>"value_double"</filename>, <filename>"value_float"</filename>, <filename>"value_int"</filename> and <filename>"value_int64"</filename>.
- To set the value of a dparam, simply set the property which matches the type of your dparam instance.
- </para>
- <programlisting>
-#define ZERO(mem) memset(&mem, 0, sizeof(mem))
-...
-
- gdouble set_to_value;
- GstDParam *volume;
- GValue set_val;
- ZERO(set_val);
- g_value_init(&set_val, G_TYPE_DOUBLE);
- ...
- g_value_set_double(&set_val, set_to_value);
- g_object_set_property(G_OBJECT(volume), "value_double", &set_val);
- </programlisting>
- <para>Or if you create an actual GValue instance:</para>
- <programlisting>
- gdouble set_to_value;
- GstDParam *volume;
- GValue *set_val;
- set_val = g_new0(GValue,1);
- g_value_init(set_val, G_TYPE_DOUBLE);
- ...
- g_value_set_double(set_val, set_to_value);
- g_object_set_property(G_OBJECT(volume), "value_double", set_val);
- </programlisting>
-
- </sect1>
-
- <sect1 id="section-dparams-types">
- <title>Different Types of Dynamic Parameter</title>
- <para>
- There are currently only two implementations of dparams so far. They are both for real-time use so
- should be run in the <filename>"synchronous"</filename> mode.
- </para>
- <sect2>
- <title>GstDParam - the base dparam type</title>
- <para>
- All dparam implementations will subclass from this type. It provides a basic implementation which simply
- propagates any value changes as soon as it can.
- A new instance can be created with the function <filename>GstDParam* gst_dparam_new (GType type)</filename>.
- It has the following object properties:
- </para>
- <itemizedlist>
- <listitem><para><filename>"value_double"</filename>
- - the property to set and get if it is a double dparam
- </para></listitem>
- <listitem><para><filename>"value_float"</filename>
- - the property to set and get if it is a float dparam
- </para></listitem>
- <listitem><para><filename>"value_int"</filename>
- - the property to set and get if it is an integer dparam
- </para></listitem>
- <listitem><para><filename>"value_int64"</filename>
- - the property to set and get if it is a 64 bit integer dparam
- </para></listitem>
- <listitem><para><filename>"is_log"</filename>
- - readonly boolean which is TRUE if the param should be displayed on a log scale
- </para></listitem>
- <listitem><para><filename>"is_rate"</filename>
- - readonly boolean which is TRUE if the value is a proportion of the sample rate.
- For example with a sample rate of 44100, 0.5 would be 22050 Hz and 0.25 would be 11025 Hz.
- </para></listitem>
- </itemizedlist>
- </sect2>
- <sect2>
- <title>GstDParamSmooth - smoothing real-time dparam</title>
- <para>
- Some parameter changes can create audible artifacts if they change too rapidly. The GstDParamSmooth
- implementation can greatly reduce these artifacts by limiting the rate at which the value can change.
- This is currently only supported for double and float dparams - the other types fall back to the default implementation.
- A new instance can be created with the function <filename>GstDParam* gst_dpsmooth_new (GType type)</filename>.
- It has the following object properties:
- </para>
- <itemizedlist>
- <listitem><para><filename>"update_period"</filename>
- - an int64 value specifying the number nanoseconds between updates. This will be ignored in
- <filename>"synchronous"</filename> mode since the buffer size dictates the update period.
- </para></listitem>
- <listitem><para><filename>"slope_time"</filename>
- - an int64 value specifying the time period to use in the maximum slope calculation
- </para></listitem>
- <listitem><para><filename>"slope_delta_double"</filename>
- - a double specifying the amount a double value can change in the given slope_time.
- </para></listitem>
- <listitem><para><filename>"slope_delta_float"</filename>
- - a float specifying the amount a float value can change in the given slope_time.
- </para></listitem>
- </itemizedlist>
- <para>
- Audible artifacts may not be completely eliminated by using this dparam. The only way to eliminate
- artifacts such as "zipper noise" would be for the element to implement its required dparams using the
- array method. This would allow dparams to change parameters at the sample rate which should eliminate
- any artifacts.
- </para>
-
- </sect2>
- <sect2>
- <title>Timelined dparams</title>
- <para>
- A yet-to-be-implemented subclass of GstDParam will add an API which allows the creation and manipulation
- of points on a timeline. This subclass will also provide a dparam implementation which uses linear
- interpolation between these points to find the dparam value at any given time. Further subclasses can
- extend this functionality to implement more exotic interpolation algorithms such as splines.
- </para>
- </sect2>
- </sect1>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-dynamic">
- <title>Dynamic pipelines</title>
- <para>
- In this chapter we will see how you can create a dynamic pipeline. A
- dynamic pipeline is a pipeline that is updated or created while data
- is flowing through it. We will create a partial pipeline first and add
- more elements while the pipeline is playing. Dynamic pipelines cause
- all sorts of scheduling issues and will remain a topic of research for
- a long time in GStreamer.
- </para>
- <para>
- We will show how to create an MPEG1 video player using dynamic pipelines.
- As you have seen in the pad section, we can attach a signal to an element
- when a pad is created. We will use this to create our MPEG1 player.
- </para>
-
- <para>
- We'll start with a simple main function:
- </para>
- <programlisting>
-<!-- example-begin dynamic.c a -->
-<![CDATA[
-#include <string.h>
-#include <gst/gst.h>
-
-void
-eof (GstElement *src)
-{
- g_print ("have eos, quitting\n");
- exit (0);
-}
-
-gboolean
-idle_func (gpointer data)
-{
- gst_bin_iterate (GST_BIN (data));
- return TRUE;
-}
-
-void
-new_pad_created (GstElement *parse, GstPad *pad, GstElement *pipeline)
-{
- GstElement *decode_video = NULL;
- GstElement *decode_audio, *play, *color, *show;
- GstElement *audio_queue, *video_queue;
- GstElement *audio_thread, *video_thread;
-
- g_print ("***** a new pad %s was created\n", gst_pad_get_name (pad));
-
- gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
-
- /* link to audio pad */
- if (strncmp (gst_pad_get_name (pad), "audio_", 6) == 0) {
-
- /* construct internal pipeline elements */
- decode_audio = gst_element_factory_make ("mad", "decode_audio");
- g_return_if_fail (decode_audio != NULL);
- play = gst_element_factory_make ("osssink", "play_audio");
- g_return_if_fail (play != NULL);
-
- /* create the thread and pack stuff into it */
- audio_thread = gst_thread_new ("audio_thread");
- g_return_if_fail (audio_thread != NULL);
-
- /* construct queue and link everything in the main pipeline */
- audio_queue = gst_element_factory_make ("queue", "audio_queue");
- g_return_if_fail (audio_queue != NULL);
-
- gst_bin_add_many (GST_BIN (audio_thread),
- audio_queue, decode_audio, play, NULL);
-
- /* set up pad links */
- gst_element_add_ghost_pad (audio_thread,
- gst_element_get_pad (audio_queue, "sink"),
- "sink");
- gst_element_link (audio_queue, decode_audio);
- gst_element_link (decode_audio, play);
-
- gst_bin_add (GST_BIN (pipeline), audio_thread);
-
- gst_pad_link (pad, gst_element_get_pad (audio_thread, "sink"));
-
- /* set up thread state and kick things off */
- g_print ("setting to READY state\n");
- gst_element_set_state (GST_ELEMENT (audio_thread), GST_STATE_READY);
-
- }
- else if (strncmp (gst_pad_get_name (pad), "video_", 6) == 0) {
-
- /* construct internal pipeline elements */
- decode_video = gst_element_factory_make ("mpeg2dec", "decode_video");
- g_return_if_fail (decode_video != NULL);
-
- color = gst_element_factory_make ("colorspace", "color");
- g_return_if_fail (color != NULL);
-
-
- show = gst_element_factory_make ("xvideosink", "show");
- g_return_if_fail (show != NULL);
-
- /* construct queue and link everything in the main pipeline */
- video_queue = gst_element_factory_make ("queue", "video_queue");
- g_return_if_fail (video_queue != NULL);
-
- /* create the thread and pack stuff into it */
- video_thread = gst_thread_new ("video_thread");
- g_return_if_fail (video_thread != NULL);
- gst_bin_add_many (GST_BIN (video_thread), video_queue,
- decode_video, color, show, NULL);
-
- /* set up pad links */
- gst_element_add_ghost_pad (video_thread,
- gst_element_get_pad (video_queue, "sink"),
- "sink");
- gst_element_link (video_queue, decode_video);
- gst_element_link_many (decode_video, color, show, NULL);
-
- gst_bin_add (GST_BIN (pipeline), video_thread);
-
- gst_pad_link (pad, gst_element_get_pad (video_thread, "sink"));
-
- /* set up thread state and kick things off */
- g_print ("setting to READY state\n");
- gst_element_set_state (GST_ELEMENT (video_thread), GST_STATE_READY);
- }
- gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
-}
-
-int
-main (int argc, char *argv[])
-{
- GstElement *pipeline, *src, *demux;
-
- gst_init (&argc, &argv);
-
- pipeline = gst_pipeline_new ("pipeline");
- g_return_val_if_fail (pipeline != NULL, -1);
-
- src = gst_element_factory_make ("filesrc", "src");
- g_return_val_if_fail (src != NULL, -1);
- if (argc < 2)
- g_error ("Please specify a video file to play !");
-
- g_object_set (G_OBJECT (src), "location", argv[1], NULL);
-
- demux = gst_element_factory_make ("mpegdemux", "demux");
- g_return_val_if_fail (demux != NULL, -1);
-
- gst_bin_add_many (GST_BIN (pipeline), src, demux, NULL);
-
- g_signal_connect (G_OBJECT (demux), "new_pad",
- G_CALLBACK (new_pad_created), pipeline);
-
- g_signal_connect (G_OBJECT (src), "eos",
- G_CALLBACK (eof), NULL);
-
- gst_element_link (src, demux);
-
- gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
-
- g_idle_add (idle_func, pipeline);
-
- gst_main ();
-
- return 0;
-}
-]]>
-<!-- example-end dynamic.c a -->
- </programlisting>
- <para>
- We create two elements: a file source and an MPEG demuxer.
- There's nothing special about this piece of code except for
- the signal 'new_pad' that we linked to the mpegdemux
- element using:
- </para>
- <programlisting>
- g_signal_connect (G_OBJECT (demux), "new_pad",
- G_CALLBACK (new_pad_created), pipeline);
- </programlisting>
- <para>
- When an elementary stream has been detected in the system stream,
- mpegdemux will create a new pad that will provide the data of the
- elementary stream. A function 'new_pad_created' will be called when
- the pad is created.
- </para>
- <para>
- In the above example, we created new elements based on the name of
- the newly created pad. We then added them to a new thread.
- There are other possibilities to check the type of the pad, for
- example by using the MIME type and the properties of the pad.
- </para>
-</chapter>
+++ /dev/null
-<chapter id="chapter-elements-api">
- <title>Elements</title>
- <sect1 id="section-elements-create">
- <title>Creating a GstElement</title>
- <para>
-The simplest way to create an element is to use
-<ulink type="http"
- url="&URLAPI;GstElementFactory.html#gst-element-factory-make">
-<function>gst_element_factory_make</function>
-</ulink>.
-This function takes a factory name and an element name for the newly created
-element.
- The name of the
-element is something you can use later on to look up the element in
-a bin, for example. You can pass <symbol>NULL</symbol> as the name
-argument to get a unique, default name.
- </para>
- <para>
-When you don't need the element anymore, you need to unref it using
-<ulink type="http"
- url="&URLAPI;GstObject.html#gst-object-unref">
-<function>gst_object_unref</function></ulink>.
-This decreases the reference count for the element by 1. An element has a
-refcount of 1 when it gets created. An element gets destroyed completely
-when the refcount is decreased to 0.
- </para>
- <para>
-The following example &EXAFOOT; shows how to create an element named
-<emphasis>source</emphasis> from the element factory named
-<emphasis>fakesrc</emphasis>. It checks if the creation succeeded.
-After checking, it unrefs the element.
- </para>
- <programlisting>
-<!-- example-begin elementmake.c a -->
-<![CDATA[
-
-#include <gst/gst.h>
-
-int
-main (int argc, char *argv[])
-{
- GstElement *element;
-
- gst_init (&argc, &argv);
-
- element = gst_element_factory_make ("fakesrc", "source");
-]]>
-<!-- example-end elementmake.c a -->
-
-<!-- example-begin elementmake.c b -->
-<![CDATA[
- if (!element) {
- g_error ("Could not create an element from 'fakesrc' factory.\n");
- }
-
- gst_object_unref (GST_OBJECT (element));
-
- return 0;
-}
-]]>
-<!-- example-end elementmake.c b -->
- </programlisting>
-<!-- example-begin elementmake.c c -->
-<!--
- /* Hi Ronald. Block c is an example of a piece of code that will end up
- * in the extracted code file, but is not shown in the docbook output */
--->
-<!-- example-end elementmake.c c -->
- <para>
-<function>gst_element_factory_make</function> is actually a shorthand
-for a combination of two functions.
-A
-<ulink type="http"
- url="&URLAPI;GstElement.html"><classname>GstElement</classname></ulink>
-object is created from a factory.
-To create the element, you have to get access to a
-<ulink type="http" url="&URLAPI;GstElementFactory.html">
-<classname>GstElementFactory</classname></ulink>
-object using a unique factory name.
-This is done with
-<ulink type="http"
- url="&URLAPI;GstElementFactory.html#gst-element-factory-find">
-<function>gst_element_factory_find</function></ulink>.
- </para>
- <para>
-The following code fragment is used to get a factory that can be used
-to create the <emphasis>fakesrc</emphasis> element, a fake data source.
- </para>
- <programlisting>
- GstElementFactory *factory;
-
- factory = gst_element_factory_find ("fakesrc");
- </programlisting>
- <para>
-Once you have the handle to the element factory, you can create a
-real element with the following code fragment:
- </para>
- <programlisting>
- GstElement *element;
-
- element = gst_element_factory_create (factory, "source");
- </programlisting>
- <para>
-<ulink type="http"
- url="&URLAPI;GstElementFactory.html#gst-element-factory-create">
-<function>gst_element_factory_create</function></ulink>
-will use the element factory to create an element with the given name.
- </para>
- </sect1>
- <sect1 id="section-elements-properties">
- <title>GstElement properties</title>
- <para>
- A <ulink type="http" url="&URLAPI;GstElement.html">
- <classname>GstElement</classname></ulink> can have several properties
- which are implemented using standard <classname>GObject</classname>
- properties. The usual <classname>GObject</classname> methods to query,
- set and get property values and <classname>GParamSpecs</classname>
- are therefore supported.
- </para>
- <para>
- Every <ulink type="http" url="&URLAPI;GstElementFactory.html">
- <classname>GstElement</classname></ulink> inherits at least
- one property of its parent <classname>GstObject</classname>:
- the "name" property. This is the name you provide to the
- functions <function>gst_element_factory_make</function> or
- <function>gst_element_factory_create</function>. You can get and set
- this property using the functions
- <function>gst_object_set_name</function>
- and <function>gst_object_get_name</function> or use the
- <classname>GObject</classname> property mechanism as shown below.
- </para>
- <programlisting>
-<!-- example-begin elementget.c a -->
-<![CDATA[
-#include <gst/gst.h>
-
-int
-main (int argc, char *argv[])
-{
- GstElement *element;
- GValue value = { 0, }; /* initialize the GValue for g_object_get() */
-
- gst_init (&argc, &argv);
- element = gst_element_factory_make ("fakesrc", "source");
- g_object_set (G_OBJECT (element), "name", "mysource", NULL);
-
- g_value_init (&value, G_TYPE_STRING);
- g_object_get_property (G_OBJECT (element), "name", &value);
-
- g_print ("The name of the source is '%s'.\n", g_value_get_string (&value));
-
- return 0;
-}
-]]>
-<!-- example-end elementget.c a -->
- </programlisting>
- <para>
- Most plugins provide additional properties to provide more information
- about their configuration or to configure the element.
- <command>gst-inspect</command> is a useful tool to query the properties
- of a particular element, it will also use property introspection to give
- a short explanation about the function of the property and about the
- parameter types and ranges it supports.
- </para>
- <para>
- For more information about <classname>GObject</classname>
- properties we recommend you read the <ulink
- url="http://developer.gnome.org/doc/API/2.0/gobject/index.html"
- type="http">GObject manual</ulink> and an introduction to <ulink
- url="http://le-hacker.org/papers/gobject/index.html" type="http">
- The Glib Object system</ulink>.
- </para>
- </sect1>
-
- <sect1 id="section-elements-signals">
- <title>GstElement signals</title>
- <para>
- A <ulink type="http" url="&URLAPI;gstreamer/html/GstElementFactory.html">
- <classname>GstElement</classname></ulink> also provides various
- <classname>GObject</classname> signals that can be used as a flexible
- callback mechanism.
- </para>
- </sect1>
-
- <sect1 id="section-elements-factories">
- <title>More about GstElementFactory</title>
- <para>
- We talk some more about the GstElementFactory object.
- </para>
-
- <sect2 id="section-elements-factories-details">
- <title>Getting information about an element using the factory details</title>
- <para>
- </para>
- </sect2>
-
- <sect2 id="section-elements-factories-padtemplates">
- <title>Finding out what pads an element can contain</title>
- <para>
- </para>
- </sect2>
-
- <sect2 id="section-elements-factories-query">
- <title>Different ways of querying the factories</title>
- <para>
- </para>
- </sect2>
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-elements">
- <title>Elements</title>
- <para>
- The most important object in <application>GStreamer</application> for the
- application programmer is the <ulink type="http"
- url="../../gstreamer/html/GstElement.html"><classname>GstElement</classname>
- </ulink>object.
- </para>
-
- <sect1 id="section-elements-design">
- <title>What is an element ?</title>
- <para>
- An element is the basic building block for the media pipeline.
- All the different high-level components you are going to use are
- derived from <ulink type="http" url="../../gstreamer/html/GstElement.html">
- <classname>GstElement</classname></ulink>. This means that a
- lot of functions you are going to use operate on objects of this class.
- </para>
- <para>
- Elements, from the perspective of GStreamer, are viewed as "black boxes"
- with a number of different aspects. One of these aspects is the presence
- of "pads" (see <xref linkend="chapter-pads"/>), or link points.
- This terminology arises from soldering; pads are where wires can be
- attached.
- </para>
- </sect1>
-
- <sect1 id="section-elements-types">
- <title>Types of elements</title>
-
- <sect2 id="section-elements-src">
- <title>Source elements</title>
- <para>
- Source elements generate data for use by a pipeline, for example
- reading from disk or from a sound card.
- </para>
- <para>
- <xref linkend="section-element-srcimg"/> shows how we will visualise
- a source element.
- We always draw a source pad to the right of the element.
- </para>
- <figure float="1" id="section-element-srcimg">
- <title>Visualisation of a source element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/src-element.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- Source elements do not accept data, they only generate data. You can
- see this in the figure because it only has a source pad. A source
- pad can only generate data.
- </para>
- </sect2>
-
- <sect2 id="section-elements-filter">
- <title>Filters and codecs</title>
- <para>
- Filter elements have both input and output pads. They operate on
- data they receive in their sink pads and produce data on their source
- pads. For example, MPEG decoders and volume filters would fall into
- this category.
- </para>
- <para>
- Elements are not constrained as to the number of pads they might have;
- for example, a video mixer might have two input pads (the images of
- the two different video streams) and one output pad.
- </para>
- <figure float="1" id="section-element-filterimg">
- <title>Visualisation of a filter element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/filter-element.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- <xref linkend="section-element-filterimg"/> shows how we will visualise
- a filter element.
- This element has one sink (input) pad and one source (output) pad.
- Sink pads are drawn on the left of the element.
- </para>
- <figure float="1" id="section-element-multifilterimg">
- <title>Visualisation of a filter element with
- more than one output pad</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/filter-element-multi.ℑ"
- format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- <xref linkend="section-element-multifilterimg"/> shows the visualisation of a filter element with
- more than one output pad. An example of such a filter is the AVI
- demultiplexer. This element will parse the input data and
- extract the audio and video data. Most of these filters dynamically
- send out a signal when a new pad is created so that the application
- programmer can link an arbitrary element to the newly created pad.
- </para>
- </sect2>
-
- <sect2 id="section-elements-sink">
- <title>Sink elements</title>
- <para>
- Sink elements are end points in a media pipeline. They accept
- data but do not produce anything. Disk writing, soundcard playback,
- and video output would all be implemented by sink elements.
- <xref linkend="section-element-sinkimg"/> shows a sink element.
- </para>
- <figure float="1" id="section-element-sinkimg">
- <title>Visualisation of a sink element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/sink-element.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
- </sect2>
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-factories">
- <title>More on factories</title>
- <para>
- The small application we created in the previous chapter used the
- concept of a factory to create the elements. In this chapter we will
- show you how to use the factory concepts to create elements based
- on what they do instead of what they are called.
- </para>
-
- <para>
- We will first explain the concepts involved before we move on
- to the reworked helloworld example using autoplugging.
- </para>
- <sect1 id="section-factories-helloworld-problems">
- <title>The problems with the helloworld example</title>
- <para>
- If we take a look at how the elements were created in the previous
- example we used a rather crude mechanism:
- </para>
-
- <programlisting>
- ...
- /* now it's time to get the parser */
- decoder = gst_element_factory_make ("mad", "decoder");
- ...
- </programlisting>
-
- <para>
- While this mechanism is quite effective it also has some big problems:
- The elements are created based on their name. Indeed, we create an
- element, mad, by explicitly stating the mad element's name. Our little
- program therefore always uses the mad decoder element to decode
- the MP3 audio stream, even if there are three other MP3 decoders in the
- system. We will see how we can use a more general way to create an
- MP3 decoder element.
- </para>
- <para>
- We have to introduce the concept of MIME types and capabilities
- added to the source and sink pads.
- </para>
- </sect1>
-
- <sect1 id="section-factories-mime">
- <title>More on MIME Types</title>
- <para>
- GStreamer uses MIME types to identify the different types of data
- that can be handled by the elements. They are the high level
- mechanisms to make sure that everyone is talking about the right
- kind of data.
- </para>
- <para>
- A MIME (Multipurpose Internet Mail Extension) type is a pair of
- strings that denote a certain type of data. Examples include:
- <itemizedlist>
- <listitem>
- <para>
- audio/x-raw-int : raw audio samples
- </para>
- </listitem>
- <listitem>
- <para>
- audio/mpeg : MPEG audio
- </para>
- </listitem>
- <listitem>
- <para>
- video/mpeg : MPEG video
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- An element must associate a MIME type to its source and sink pads
- when it is loaded into the system. GStreamer knows about the
- different elements and what type of data they expect and emit.
- This allows for very dynamic and extensible element creation as we
- will see.
- </para>
- <para>
- As we have seen in the previous chapter, MIME types are added
- to the Capability structure of a pad.
- </para>
-
- <para>
- <xref linkend="section-mime-img"/> shows the MIME types associated with
- each pad from the "hello world" example.
- </para>
- <figure float="1" id="section-mime-img">
- <title>The Hello world pipeline with MIME types</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/mime-world.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
-
- </figure>
- <para>
- We will see how you can create an element based on the MIME types
- of its source and sink pads. This way the end-user will have the
- ability to choose his/her favorite audio/mpeg decoder without
- you even having to care about it.
- </para>
- <para>
- The typing of the source and sink pads also makes it possible to
- 'autoplug' a pipeline. We will have the ability to say: "construct
- a pipeline that does an audio/mpeg to audio/x-raw-int conversion".
- </para>
- <note>
- <para>
- The basic GStreamer library does not try to solve all of your
- autoplug problems. It leaves the hard decisions to the application
- programmer, where they belong.
- </para>
- </note>
-
- </sect1>
-
- <sect1 id="section-factories-gstreamer-types">
- <title>GStreamer types</title>
- <para>
- GStreamer assigns a unique number to all registered MIME types.
- GStreamer also keeps a reference to
- a function that can be used to determine if a given buffer is of
- the given MIME type.
- </para>
- <para>
- There is also an association between a MIME type and a file extension,
- but the use of typefind functions (similar to file(1)) is preferred.
- </para>
- <para>
- The type information is maintained in a list of
- <classname>GstType</classname>. The definition of a
- <classname>GstType</classname> is like:
- </para>
- <para>
- <programlisting>
-typedef GstCaps (*GstTypeFindFunc) (GstBuffer *buf,gpointer *priv);
-
-typedef struct _GstType GstType;
-
-struct _GstType {
- guint16 id; /* type id (assigned) */
-
- gchar *mime; /* MIME type */
- gchar *exts; /* space-delimited list of extensions */
-
- GstTypeFindFunc typefindfunc; /* typefind function */
-};
- </programlisting>
- </para>
- <para>
- All operations on <classname>GstType</classname> occur
- via their <classname>guint16 id</classname> numbers, with
- the <classname>GstType</classname> structure private to the GStreamer
- library.
- </para>
-
- <sect2>
- <title>MIME type to id conversion</title>
-
- <para>
- We can obtain the id for a given MIME type
- with the following piece of code:
- </para>
- <programlisting>
- guint16 id;
-
- id = gst_type_find_by_mime ("audio/mpeg");
- </programlisting>
- <para>
- This function will return 0 if the type was not known.
- </para>
- </sect2>
-
- <sect2>
- <title>id to <classname>GstType</classname> conversion</title>
- <para>
- We can obtain the <classname>GstType</classname> for a given id
- with the following piece of code:
- </para>
- <programlisting>
- GstType *type;
-
- type = gst_type_find_by_id (id);
- </programlisting>
- <para>
- This function will return NULL if the id was not associated with
- any known <classname>GstType</classname>
- </para>
- </sect2>
-
- <sect2>
- <title>extension to id conversion</title>
- <para>
- We can obtain the id for a given file extension
- with the following piece of code:
- </para>
- <programlisting>
- guint16 id;
-
- id = gst_type_find_by_ext (".mp3");
- </programlisting>
- <para>
- This function will return 0 if the extension was not known.
- </para>
- <para>
- For more information, see <xref linkend="chapter-autoplug"/>.
- </para>
- </sect2>
- </sect1>
-
- <sect1 id="section-factories-create">
- <title>Creating elements with the factory</title>
- <para>
- In the previous section we described how you could obtain
- an element factory using MIME types. One the factory has been
- obtained, you can create an element using:
- </para>
- <programlisting>
- GstElementFactory *factory;
- GstElement *element;
-
- // obtain the factory
- factory = ...
-
- element = gst_element_factory_create (factory, "name");
- </programlisting>
- <para>
- This way, you do not have to create elements by name which
- allows the end-user to select the elements he/she prefers for the
- given MIME types.
- </para>
- </sect1>
-
- <sect1 id="section-factories-basic-types">
- <title>GStreamer basic types</title>
- <para>
- GStreamer only has two builtin types:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- audio/raw : raw audio samples
- </para>
- </listitem>
- <listitem>
- <para>
- video/raw and image/raw : raw video data
- </para>
- </listitem>
- </itemizedlist>
- <para>
- All other MIME types are maintained by the plugin elements.
- </para>
-
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-gnome">
- <title>GNOME integration</title>
- <para>
- GStreamer is fairly easy to integrate with GNOME applications.
- GStreamer uses libxml 2.0, GLib 2.0 and popt, as do all other
- GNOME applications.
- There are however some basic issues you need to address in your GNOME
- applications.
- </para>
-
- <sect1>
- <title>Command line options</title>
- <para>
- GNOME applications call gnome_program_init () to parse command-line
- options and initialize the necessary gnome modules.
- GStreamer applications normally call gst_init (&argc, &argv) to
- do the same for GStreamer.
- </para>
- <para>
- Each of these two swallows the program options passed to the program,
- so we need a different way to allow both GNOME and GStreamer to parse
- the command-line options. This is shown in the following example.
- </para>
-
- <programlisting>
-<!-- example-begin gnome.c a -->
-<![CDATA[
-#include <gnome.h>
-#include <gst/gst.h>
-
-int
-main (int argc, char **argv)
-{
- GstPoptOption options[] = {
- { NULL, '\0', POPT_ARG_INCLUDE_TABLE, NULL, 0, "GStreamer", NULL },
- POPT_TABLEEND
- };
- GnomeProgram *program;
- poptContext context;
- const gchar **argvn;
-
- GstElement *pipeline;
- GstElement *src, *sink;
-
- options[0].arg = (void *) gst_init_get_popt_table ();
- g_print ("Calling gnome_program_init with the GStreamer popt table\n");
- /* gnome_program_init will initialize GStreamer now
- * as a side effect of having the GStreamer popt table passed. */
- if (! (program = gnome_program_init ("my_package", "0.1", LIBGNOMEUI_MODULE,
- argc, argv,
- GNOME_PARAM_POPT_TABLE, options,
- NULL)))
- g_error ("gnome_program_init failed");
-
- g_print ("Getting gnome-program popt context\n");
- g_object_get (program, "popt-context", &context, NULL);
- argvn = poptGetArgs (context);
- if (!argvn) {
- g_print ("Run this example with some arguments to see how it works.\n");
- return 0;
- }
-
- g_print ("Printing rest of arguments\n");
- while (*argvn) {
- g_print ("argument: %s\n", *argvn);
- ++argvn;
- }
-
- /* do some GStreamer things to show everything's initialized properly */
- g_print ("Doing some GStreamer stuff to show that everything works\n");
- pipeline = gst_pipeline_new ("pipeline");
- src = gst_element_factory_make ("fakesrc", "src");
- sink = gst_element_factory_make ("fakesink", "sink");
- gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
- gst_element_link (src, sink);
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
- gst_bin_iterate (GST_BIN (pipeline));
- gst_element_set_state (pipeline, GST_STATE_NULL);
-
- return 0;
-}
-]]>
-<!-- example-end gnome.c a -->
- </programlisting>
- <para>
- If you try out this program, you will see that when called with
- --help, it will print out both GStreamer and GNOME help arguments.
- All of the arguments that didn't belong to either end up in the
- argvn pointer array.
- </para>
- <para>
- FIXME: flesh this out more. How do we get the GStreamer arguments
- at the end ?
- FIXME: add a GConf bit.
- </para>
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-goals">
- <title>Goals</title>
- <para>
- GStreamer was designed to provide a solution to the current Linux media
- problems.
- </para>
-
- <sect1 id="section-goals-design">
- <title>The design goals</title>
- <para>
- We describe what we try to achieve with GStreamer.
- </para>
- <sect2 id="section-goals-clean">
- <title>Clean and powerful</title>
- <para>
- GStreamer wants to provide a clean interface to:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- The application programmer who wants to build a media pipeline.
- The programmer can use an extensive set of powerful tools to create
- media pipelines without writing a single line of code. Performing
- complex media manipulations becomes very easy.
- </para>
- </listitem>
- <listitem>
- <para>
- The plugin programmer. Plugin programmers are provided a clean and
- simple API to create self contained plugins. An extensive debugging
- and tracing mechanism has been integrated. GStreamer also comes with
- an extensive set of real-life plugins that serve as examples too.
- </para>
- </listitem>
- </itemizedlist>
-
- </sect2>
- <sect2 id="section-goals-object">
- <title>Object oriented</title>
- <para>
- GStreamer adheres to the GLib 2.0 object model. A programmer familiar with GLib 2.0 or older versions
- of GTK+ will be comfortable with GStreamer.
- </para>
- <para>
- GStreamer uses the mechanism of signals and object properties.
- </para>
- <para>
- All objects can be queried at runtime for their various properties and
- capabilities.
- </para>
- <para>
- GStreamer intends to be similar in programming methodology to GTK+.
- This applies to the object model, ownership of objects, reference
- counting, ...
- </para>
- </sect2>
-
- <sect2 id="section-goals-extensible">
- <title>Extensible</title>
- <para>
- All GStreamer Objects can be extended using the GObject inheritance methods.
- </para>
- <para>
- All plugins are loaded dynamically and can be extended and upgraded
- independently.
- </para>
- </sect2>
-
- <sect2 id="section-goals-binary">
- <title>Allow binary only plugins</title>
- <para>
- Plugins are shared libraries that are loaded at runtime. Since all the properties of the
- plugin can be set using the GObject properties, there is no need (and in fact no way) to
- have any header files installed for the plugins.
- </para>
- <para>
- Special care has been taken to make plugins completely selfcontained.
- All relevant aspects of plugins can be queried at run-time.
- </para>
- </sect2>
-
- <sect2 id="section-goals-performance">
- <title>High performance</title>
- <para>
- High performance is obtained by:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- using GLib's <function>g_mem_chunk</function> and fast non-blocking allocation algorithms
- where possible to minimize dynamic memory allocation.
- </para>
- </listitem>
- <listitem>
- <para>
- extremely light-weight links between plugins. Data can travel
- the pipeline with minimal overhead. Data passing between plugins only involves
- a pointer dereference in a typical pipeline.
- </para>
- </listitem>
- <listitem>
- <para>
- providing a mechanism to directly work on the target memory. A plugin can for example
- directly write to the X server's shared memory space. Buffers can also point to
- arbitrary memory, such as a sound card's internal hardware buffer.
- </para>
- </listitem>
- <listitem>
- <para>
- refcounting and copy on write minimize usage of memcpy.
- Sub-buffers efficiently split buffers into manageable pieces.
- </para>
- </listitem>
- <listitem>
- <para>
- the use of cothreads to minimize the threading overhead. Cothreads are a simple and fast
- user-space method for switching between subtasks. Cothreads were measured to
- consume as little as 600 cpu cycles.
- </para>
- </listitem>
- <listitem>
- <para>
- allowing hardware acceleration by using specialized plugins.
- </para>
- </listitem>
- <listitem>
- <para>
- using a plugin registry with the specifications of the plugins so
- that the plugin loading can be delayed until the plugin is actually
- used.
- </para>
- </listitem>
- <listitem>
- <para>
- all critical data passing is free of locks and mutexes.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
-
- <sect2 id="section-goals-separation">
- <title>Clean core/plugins separation</title>
- <para>
- The core of GStreamer is essentially media-agnostic. It only knows
- about bytes and blocks, and only contains basic elements.
- The core of GStreamer is functional enough to even implement low-level
- system tools, like cp.
- </para>
- <para>
- All of the media handling functionality is provided by plugins external
- to the core. These tell the core how to handle specific types of media.
- </para>
- </sect2>
-
- <sect2 id="section-goals-testbed">
- <title>Provide a framework for codec experimentation</title>
- <para>
- GStreamer also wants to be an easy framework where codec
- developers can experiment with different algorithms, speeding up
- the development of open and free multimedia codecs like <ulink
- url="http://www.xiph.org/ogg/index.html" type="http">tarkin and
- vorbis</ulink>.
- </para>
- </sect2>
-
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-hello-world">
- <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 id="section-hello-world">
- <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>
-<!-- example-begin helloworld.c a -->
-<![CDATA[
-#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 <mp3 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);
-
- /* link src to sink */
- gst_element_link_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);
-}
-]]>
-<!-- example-end helloworld.c a -->
- </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, <ulink type="http"
- url="../../gstreamer/html/GstElement.html"><classname>GstElement</classname></ulink>,
- 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 ("osssink", "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 link the different pads of the elements together like this:
- </para>
- <programlisting>
- /* link src to sink */
- gst_element_link_many (filesrc, decoder, audiosink, NULL);
- </programlisting>
-
- <para>
- We now have created a complete pipeline. We can visualise the
- pipeline as follows:
- </para>
- <figure float="1" id="section-hello-img">
- <title>The "hello world" pipeline</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/hello-world.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
-
- </figure>
-
- <para>
- Everything is now set up to start 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 id="section-hello-world-compile">
- <title>Compiling helloworld.c</title>
- <para>
- To compile the helloworld example, use:
- </para>
- <programlisting>
- gcc -Wall `pkg-config gstreamer-&GST_MAJORMINOR; --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 id="section-hello-world-conclusion">
- <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 the gnomevfssrc element, giving you instant streaming
- from any gnomevfs URL.
- </para>
- <para>
- We can also choose to use another type of sink instead of the audiosink.
- We could use a filesink 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>
+++ /dev/null
-<chapter id="chapter-hello2">
- <title>Your second application</title>
- <para>
- FIXME: delete this section, talk more about the spider. 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 and the autoplugger.
- </para>
-
- <sect1>
- <title>Autoplugging helloworld </title>
- <para>
- We will create a second version of the helloworld application using
- autoplugging. Its source code is a bit more complicated but
- it can handle many more data types. It can even play the audio track
- of a video file.
- </para>
- <para>
- Here is the full program listing. Start by looking at the main ()
- function.
- </para>
-
- <programlisting>
-<!-- example-begin helloworld2.c a -->
-<![CDATA[
-#include <gst/gst.h>
-
-static void gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline);
-static void gst_play_cache_empty (GstElement *element, GstElement *pipeline);
-
-static void
-gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline)
-{
- GstElement *osssink;
- GstElement *new_element;
- GstAutoplug *autoplug;
- GstElement *autobin;
- GstElement *filesrc;
- GstElement *cache;
-
- g_print ("GstPipeline: play have type\n");
-
- gst_element_set_state (pipeline, GST_STATE_PAUSED);
-
- filesrc = 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");
-
- /* unlink the typefind from the pipeline and remove it */
- gst_element_unlink (cache, typefind);
- gst_bin_remove (GST_BIN (autobin), typefind);
-
- /* and an audio sink */
- osssink = gst_element_factory_make ("osssink", "play_audio");
- g_assert (osssink != NULL);
-
- autoplug = gst_autoplug_factory_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_link (cache, new_element);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-}
-
-static void
-gst_play_cache_empty (GstElement *element, GstElement *pipeline)
-{
- GstElement *autobin;
- GstElement *filesrc;
- GstElement *cache;
- GstElement *new_element;
-
- g_print ("have cache empty\n");
-
- gst_element_set_state (pipeline, GST_STATE_PAUSED);
-
- filesrc = 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_unlink (filesrc, cache);
- gst_element_unlink (cache, new_element);
- gst_bin_remove (GST_BIN (autobin), cache);
- gst_element_link (filesrc, new_element);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- g_print ("done with cache_empty\n");
-}
-
-int
-main (int argc, char *argv[])
-{
- GstElement *filesrc;
- GstElement *pipeline;
- GstElement *autobin;
- GstElement *typefind;
- GstElement *cache;
-
- gst_init (&argc, &argv);
-
- if (argc != 2) {
- g_print ("usage: %s <filename with audio>\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 */
- filesrc = gst_element_factory_make ("filesrc", "disk_source");
- g_assert (filesrc != NULL);
- g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
- gst_bin_add (GST_BIN (pipeline), filesrc);
-
- autobin = gst_bin_new ("autobin");
- cache = gst_element_factory_make ("autoplugcache", "cache");
- g_signal_connect (G_OBJECT (cache), "cache_empty",
- G_CALLBACK (gst_play_cache_empty), pipeline);
-
- typefind = gst_element_factory_make ("typefind", "typefind");
- g_signal_connect (G_OBJECT (typefind), "have_type",
- G_CALLBACK (gst_play_have_type), pipeline);
- gst_bin_add (GST_BIN (autobin), cache);
- gst_bin_add (GST_BIN (autobin), typefind);
-
- gst_element_link (cache, typefind);
- gst_element_add_ghost_pad (autobin,
- gst_element_get_pad (cache, "sink"), "sink");
-
- gst_bin_add (GST_BIN( pipeline), autobin);
- gst_element_link (filesrc, autobin);
-
- /* start playing */
- gst_element_set_state( GST_ELEMENT (pipeline), GST_STATE_PLAYING);
-
- while (gst_bin_iterate (GST_BIN (pipeline)));
-
- /* stop the pipeline */
- gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
-
- gst_object_unref (GST_OBJECT (pipeline));
-
- exit(0);
-}
-]]>
-<!-- example-end helloworld2.c a -->
- </programlisting>
- <para>
- We start by constructing a 'filesrc' element and an 'autobin' element that
- holds the autoplugcache and the typefind element.
- </para>
- <para>
- We attach the "cache_empty" signal to gst_play_cache_empty and the
- "have_type" to our gst_play_have_type function.
- </para>
-
- <para>
- 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:
- </para>
- <programlisting>
- filesrc = 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");
- </programlisting>
-
- <para>
- Now we have a handle to the elements we are going to manipulate in
- the next step.
- </para>
- <para>
- We don't need the typefind element anymore so we remove it from
- the pipeline:
- </para>
- <programlisting>
- /* unlink the typefind from the pipeline and remove it */
- gst_element_unlink (cache, "src", typefind, "sink");
- gst_bin_remove (GST_BIN (autobin), typefind);
- </programlisting>
-
- <para>
- 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
- links the type to an osssink. We add the new element to our
- autobin.
- </para>
-
- <programlisting>
- /* and an audio sink */
- osssink = gst_element_factory_make("osssink", "play_audio");
- g_assert(osssink != NULL);
-
- autoplug = gst_autoplug_factory_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);
- </programlisting>
-
- <para>
- 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.
- </para>
- <programlisting>
- g_object_set (G_OBJECT (cache), "reset", TRUE, NULL);
-
- gst_element_link (cache, "src", new_element, "sink");
- </programlisting>
- <para>
- 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
- by the gst_play_cache_empty callback function.
- </para>
-
- <para>
- The cache empty function simply removes the autoplugcache element from
- the pipeline and relinks the filesrc to the autoplugged element.
- </para>
-
- <para>
- To compile the helloworld2 example, use:
- </para>
- <programlisting>
- gcc -Wall `pkg-config gstreamer-&GST_MAJORMINOR; --cflags --libs` helloworld2.c \
- -o helloworld2
- </programlisting>
- <para>
- You can run the example with
- (substitute helloworld.mp3 with you favorite audio file):
- </para>
- <programlisting>
- ./helloworld2 helloworld.mp3
- </programlisting>
- <para>
- You can also try to use an AVI or MPEG file as its input.
- Using autoplugging,
- <application>GStreamer</application>
- will automatically figure out how to
- handle the stream.
- Remember that only the audio part will be played because
- we have only added an osssink to the pipeline.
- </para>
- <programlisting>
- ./helloworld2 mymovie.mpeg
- </programlisting>
-
- </sect1>
-</chapter>
<title>Components</title>
<para>
- FIXME: This chapter is way out of date.
+ &GStreamer; includes several higher-level components to simplify your
+ applications life. All of the components discussed here (for now) are
+ targetted at media playback. The idea of each of these components is
+ to integrate as closely as possible with a &GStreamer; pipeline, but
+ to hide the complexity of media type detection and several other
+ rather complex topics that have been discussed in <xref
+ linkend="part-advanced"/>.
</para>
- <para>
- <application>GStreamer</application> includes components that people can include
- in their programs.
+ <para>
+ We currently recommend people to use either playbin (see <xref
+ linkend="section-components-playbin"/>) or decodebin (see <xref
+ linkend="section-components-decodebin"/>), depending on their needs. The
+ other components discussed here are either outdated or deprecated. The
+ documentation is provided for legacy purposes. Use of those other
+ components is not recommended.
</para>
- <sect1 id="section-components-gst-play">
- <title>GstPlay</title>
- <para>
- GstPlay is a GtkWidget with a simple API to play, pause and stop a media file.
+ <sect1 id="section-components-playbin">
+ <title>Playbin</title>
+
+ <para>
+ Playbin is an element that can be created using the standard &GStreamer;
+ API (e.g. <function>gst_element_factory_make ()</function>). The factory
+ is conveniently called <quote>playbin</quote>. By being a
+ <classname>GstElement</classname>, playbin automatically supports all
+ of the features of this class, including error handling, tag support,
+ state handling, getting stream positions, seeking, and so on.
+ </para>
+
+ <para>
+ Setting up a playbin pipeline is as simple as creating an instance of
+ the playbin element, setting a file location (this has to be a valid
+ URI, so <quote><protocol>://<location></quote>, e.g.
+ file:///tmp/my.ogg or http://www.example.org/stream.ogg) using the
+ <quote>uri</quote> property on playbin, and then setting the element
+ to the <classname>GST_STATE_PLAYING</classname> state. Internally,
+ playbin uses threads, so there's no need to iterate the element or
+ anything. However, one thing to keep in mind is that signals fired
+ by playbin might come from another than the main thread, so be sure
+ to keep this in mind in your signal handles. Most application
+ programmers will want to use a function such as <function>g_idle_add
+ ()</function> to make sure that the signal is handled in the main
+ thread.
+ </para>
+
+ <programlisting><!-- example-begin playbin.c -->
+#include <gst/gst.h>
+
+static void
+cb_eos (GstElement *play,
+ gpointer data)
+{
+ gst_main_quit ();
+}
+
+static void
+cb_error (GstElement *play,
+ GstElement *src,
+ GError *err,
+ gchar *debug,
+ gpointer data)
+{
+ g_print ("Error: %s\n", err->message);
+}
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ GstElement *play;
+
+ /* init GStreamer */
+ gst_init (&argc, &argv);
+
+ /* make sure we have a URI */
+ if (argc != 2) {
+ g_print ("Usage: %s <URI>\n", argv[0]);
+ return -1;
+ }
+
+ /* set up */
+ play = gst_element_factory_make ("playbin", "play");
+ g_object_set (G_OBJECT (play), "uri", argv[1], NULL);
+ g_signal_connect (play, "eos", G_CALLBACK (cb_eos), NULL);
+ g_signal_connect (play, "error", G_CALLBACK (cb_error), NULL);
+ if (gst_element_set_state (play, GST_STATE_PLAYING) != GST_STATE_SUCCESS) {
+ g_print ("Failed to play\n");
+ return -1;
+ }
+
+ /* now run */
+ gst_main ();
+
+ /* also clean up */
+ gst_element_set_state (play, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (play));
+
+ return 0;
+}
+ <!-- example-end playbin.c --></programlisting>
+
+ <para>
+ Playbin has several features that have been discussed previously:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Settable video and audio output (using the <quote>video-sink</quote>
+ and <quote>audio-sink</quote> properties).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Mostly controllable and trackable as a
+ <classname>GstElement</classname>, including error handling, eos
+ handling, tag handling, state handling, media position handling and
+ seeking.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Buffers network-sources.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Supports visualizations for audio-only media.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1 id="section-components-decodebin">
+ <title>Decodebin</title>
+
+ <para>
+ Decodebin is the actual autoplugger backend of playbin, which was
+ discussed in the previous section. Decodebin will, in short, accept
+ input from a source that is linked to its sinkpad and will try to
+ detect the media type contained in the stream, and set up decoder
+ routines for each of those. It will automatically select decoders.
+ For each decoded stream, it will emit the <quote>new-decoded-pad</quote>
+ signal, to let the client know about the newly found decoded stream.
+ For unknown streams (which might be the whole stream), it will emit
+ the <quote>unknown-type</quote> signal. The application is then
+ responsible for reporting the error to the user.
+ </para>
+
+ <para>
+ The example code below will play back an audio stream of an input
+ file. For readability, it does not include any error handling of
+ any sort.
+ </para>
+
+ <programlisting><!-- example-begin decodebin.c -->
+#include <gst/gst.h>
+
+GstElement *pipeline, *audio;
+GstPad *audiopad;
+
+static void
+cb_newpad (GstElement *decodebin,
+ GstPad *pad,
+ gboolean last,
+ gpointer data)
+{
+ GstCaps *caps;
+ GstStructure *str;
+
+ /* only link audio; only link once */
+ if (GST_PAD_IS_LINKED (audiopad))
+ return;
+ caps = gst_pad_get_caps (pad);
+ str = gst_caps_get_structure (caps, 0);
+ if (!g_strrstr (gst_structure_get_name (str), "audio"))
+ return;
+
+ /* link'n'play */
+ gst_pad_link (pad, audiopad);
+ gst_bin_add (GST_BIN (pipeline), audio);
+ gst_bin_sync_children_state (GST_BIN (pipeline));
+}
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ GstElement *src, *dec, *conv, *scale, *sink;
+
+ /* init GStreamer */
+ gst_init (&argc, &argv);
+
+ /* make sure we have input */
+ if (argc != 2) {
+ g_print ("Usage: %s <filename>\n", argv[0]);
+ return -1;
+ }
+
+ /* setup */
+ pipeline = gst_pipeline_new ("pipeline");
+ src = gst_element_factory_make ("filesrc", "source");
+ g_object_set (G_OBJECT (src), "location", argv[1], NULL);
+ dec = gst_element_factory_make ("decodebin", "decoder");
+ g_signal_connect (dec, "new-decoded-pad", G_CALLBACK (cb_newpad), NULL);
+ audio = gst_bin_new ("audiobin");
+ conv = gst_element_factory_make ("audioconvert", "aconv");
+ audiopad = gst_element_get_pad (conv, "sink");
+ scale = gst_element_factory_make ("audioscale", "scale");
+ sink = gst_element_factory_make ("alsasink", "sink");
+ gst_bin_add_many (GST_BIN (audio), conv, scale, sink, NULL);
+ gst_element_link_many (conv, scale, sink, NULL);
+ gst_bin_add_many (GST_BIN (pipeline), src, dec, NULL);
+ gst_element_link (src, dec);
+
+ /* run */
+ gst_element_set_state (audio, GST_STATE_PAUSED);
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ while (gst_bin_iterate (GST_BIN (pipeline))) ;
+
+ /* cleanup */
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (pipeline));
+
+ return 0;
+}
+ <!-- example-end decodebin.c --></programlisting>
+
+ <para>
+ Although decodebin is a good autoplugger, there's a whole lot of
+ things that it does not do and is not intended to do:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Taking care of input streams with a known media type (e.g. a DVD,
+ an audio-CD or such).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Selection of streams (e.g. which audio track to play in case of
+ multi-language media streams).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Overlaying subtitles over a decoded video stream.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect1>
+
+ <sect1 id="section-components-spider">
+ <title>Spider</title>
+
+ <para>
+ Bla
</para>
-
</sect1>
- <sect1 id="section-components-gst-media-play">
- <title>GstMediaPlay</title>
+ <sect1 id="section-components-gst-play">
+ <title>GstPlay</title>
<para>
- GstMediaPlay is a complete player widget.
+ GstPlay is a GtkWidget with a simple API to play, pause and stop a media file.
</para>
</sect1>
</para>
<programlisting>
-
-<!-- example-begin xml-mp3.c a -->
-<![CDATA[
-#include <stdlib.h>
-#include <gst/gst.h>
+<!-- example-begin xml-mp3.c -->
+#include <stdlib.h>
+#include <gst/gst.h>
gboolean playing;
exit (0);
}
-]]>
-<!-- example-end xml-mp3.c a -->
+<!-- example-end xml-mp3.c -->
</programlisting>
<para>
The most important line is:
+++ /dev/null
-<chapter id="chapter-initialisation">
- <title>Initializing <application>GStreamer</application></title>
- <para>
- When writing a <application>GStreamer</application> application, you can
- simply include <filename class='headerfile'>gst/gst.h</filename> to get
- access to the library functions.
- </para>
- <para>
- Before the <application>GStreamer</application> libraries can be used,
- <function>gst_init</function> has to be called from the main application.
- This call will perform the necessary initialization of the library as
- well as parse the GStreamer-specific command line options.
- </para>
- <para>
- A typical program
- &EXAFOOT;
- would have code to initialize GStreamer that
- looks like this:
- </para>
-
- <programlisting>
-<!-- example-begin init.c a -->
-<![CDATA[
-#include <gst/gst.h>
-
-int
-main (int argc, char *argv[])
-{
- guint major, minor, micro;
-
- gst_init (&argc, &argv);
-
- gst_version (&major, &minor, &micro);
- printf ("This program is linked against GStreamer %d.%d.%d\n",
- major, minor, micro);
-
- return 0;
-}
-]]>
-<!-- example-end init.c a -->
- </programlisting>
- <para>
- Use the <symbol>GST_VERSION_MAJOR</symbol>,
- <symbol>GST_VERSION_MINOR</symbol> and <symbol>GST_VERSION_MICRO</symbol>
- macros to get the <application>GStreamer</application> version you are
- building against, or use the function <function>gst_version</function>
- to get the version your application is linked against.
-<!-- FIXME: include an automatically generated list of these options. -->
- </para>
- <para>
- It is also possible to call the <function>gst_init</function> function
- with two <symbol>NULL</symbol> arguments, in which case no command line
- options will be parsed by <application>GStreamer</application>.
- </para>
- <sect1>
- <title>The popt interface</title>
- <para>
-You can also use a popt table to initialize your own parameters as shown in the
-next example:
- </para>
- <programlisting>
-<!-- example-begin popt.c a -->
-<![CDATA[
-#include <gst/gst.h>
-
-int
-main(int argc, char *argv[])
-{
- gboolean silent = FALSE;
- gchar *savefile = NULL;
- struct poptOption options[] = {
- {"silent", 's', POPT_ARG_NONE|POPT_ARGFLAG_STRIP, &silent, 0,
- "do not output status information", NULL},
- {"output", 'o', POPT_ARG_STRING|POPT_ARGFLAG_STRIP, &savefile, 0,
- "save xml representation of pipeline to FILE and exit", "FILE"},
- POPT_TABLEEND
- };
-
- gst_init_with_popt_table (&argc, &argv, options);
-
- printf ("Run me with --help to see the Application options appended.\n");
-
- return 0;
-}
-]]>
-<!-- example-end popt.c a -->
-
- </programlisting>
- <para>
- As shown in this fragment, you can use a <ulink
- url="http://developer.gnome.org/doc/guides/popt/"
- type="http">popt</ulink> table to define your application-specific
- command line options, and pass this table to the
- function <function>gst_init_with_popt_table</function>. Your
- application options will be parsed in addition to the standard
- <application>GStreamer</application> options.
- </para>
- </sect1>
-
-</chapter>
--- /dev/null
+<chapter id="chapter-intro-basics">
+ <title>Foundations</title>
+ <para>
+ This chapter of the guide introduces the basic concepts of &GStreamer;.
+ Understanding these concepts will be important in reading any of the
+ rest of this guide, all of them assume understanding of these basic
+ concepts.
+ </para>
+
+ <sect1 id="section-intro-basics-elements">
+ <title>Elements</title>
+ <para>
+ An <emphasis>element</emphasis> is the most important class of objects
+ in &GStreamer;. You will usually create a chain of elements linked
+ together and let data flow through this chain of elements. An element
+ has one specific function, which can be the reading of data from a
+ file, decoding of this data or outputting this data to your sound
+ card (or anything else). By chaining together several such elements,
+ you create a <emphasis>pipeline</emphasis> that can do a specific task,
+ for example media playback or capture. &GStreamer; ships with a large
+ collection of elements by default, making the development of a large
+ variety of media applications possible. If needed, you can also write
+ new elements. That topic is explained in great deal in the Plugin
+ Writer's Guide.
+ </para>
+ </sect1>
+
+ <sect1 id="section-intro-basics-bins">
+ <title>Bins and pipelines</title>
+
+ <para>
+ A <emphasis>bin</emphasis> is a container for a collection of elements.
+ A pipeline is a special subtype of a bin that allows execution of all
+ of its contained child elements. Since bins are subclasses of elements
+ themselves, you can mostly control a bin as if it where an element,
+ thereby abstracting away a lot of complexity for your application. You
+ can, for example change state on all elements in a bin by changing the
+ state of that bin itself. Bins also forward some signals from their
+ contained childs (such as errors and tags).
+ </para>
+ <para>
+ A pipeline is a bin that allows to <emphasis>run</emphasis> (technically
+ referred to as <quote>iterating</quote>) its contained childs. By
+ iterating a pipeline, data flow will start and media processing will
+ take place. A pipeline requires iterating for anything to happen. you
+ can also use threads, which automatically iterate the contained childs
+ in a newly created threads. We will go into this in detail later on.
+ </para>
+ </sect1>
+
+ <sect1 id="section-intro-basics-pads">
+ <title>Pads</title>
+ <para>
+ <emphasis>Pads</emphasis> are used to negotiate links and data flow
+ between elements in &GStreamer;. A pad can be viewed as a
+ <quote>plug</quote> or <quote>port</quote> on an element where
+ links may be made with other elements, and through which data can
+ flow to or from those elements. Pads have specific data handling
+ capabilities: A pad can restrict the type of data that flows
+ through it. Links are only allowed between two pads when the
+ allowed data types of the two pads are compatible. Data types are
+ negotiated between pads using a process called <emphasis>caps
+ negotiation</emphasis>. Data types are described as a
+ <classname>GstCaps</classname>.
+ </para>
+ <para>
+ An analogy may be helpful here. A pad is similar to a plug or jack on a
+ physical device. Consider, for example, a home theater system consisting
+ of an amplifier, a DVD player, and a (silent) video projector. Linking
+ the DVD player to the amplifier is allowed because both devices have audio
+ jacks, and linking the projector to the DVD player is allowed because
+ both devices have compatible video jacks. Links between the
+ projector and the amplifier may not be made because the projector and
+ amplifier have different types of jacks. Pads in &GStreamer; serve the
+ same purpose as the jacks in the home theater system.
+ </para>
+ <para>
+ For the most part, all data in &GStreamer; flows one way through a link
+ between elements. Data flows out of one element through one or more
+ <emphasis>source pads</emphasis>, and elements accept incoming data
+ through one or more <emphasis>sink pads</emphasis>. Source and sink
+ elements have only source and sink pads, respectively. Data is
+ embodied in a <classname>GstData</classname> structure.
+ </para>
+ </sect1>
+</chapter>
<chapter id="chapter-motivation">
- <title>Motivation</title>
+ <title>Motivation & Goals</title>
<para>
- Linux has historically lagged behind other operating systems in the multimedia
- arena. Microsoft's <trademark>Windows</trademark> and Apple's <trademark>MacOS</trademark> both have strong support
- for multimedia devices, multimedia content creation,
- playback, and realtime processing. Linux, on the other hand, has a poorly integrated
- collection of multimedia utilities and applications available, which can hardly compete
- with the professional level of software available for MS Windows and MacOS.
+ Linux has historically lagged behind other operating systems in the
+ multimedia arena. Microsoft's <trademark>Windows</trademark> and
+ Apple's <trademark>MacOS</trademark> both have strong support for
+ multimedia devices, multimedia content creation, playback, and
+ realtime processing. Linux, on the other hand, has a poorly integrated
+ collection of multimedia utilities and applications available, which
+ can hardly compete with the professional level of software available
+ for MS Windows and MacOS.
+ </para>
+ <para>
+ GStreamer was designed to provide a solution to the current Linux media
+ problems.
</para>
<sect1 id="section-motivation-problems">
<sect2 id="section-motivation-duplicate">
<title>Multitude of duplicate code</title>
<para>
- The Linux user who wishes to hear a sound file must hunt through their collection of
- sound file players in order to play the tens of sound file formats in wide use today.
- Most of these players basically reimplement the same code over and over again.
+ The Linux user who wishes to hear a sound file must hunt through
+ their collection of sound file players in order to play the tens
+ of sound file formats in wide use today. Most of these players
+ basically reimplement the same code over and over again.
</para>
<para>
- The Linux developer who wishes to embed a video clip in their application must use
- crude hacks to run an external video player. There is no library available that a
- developer can use to create a custom media player.
+ The Linux developer who wishes to embed a video clip in their
+ application must use crude hacks to run an external video player.
+ There is no library available that a developer can use to create
+ a custom media player.
</para>
-
</sect2>
+
<sect2 id="section-motivation-goal">
<title>'One goal' media players/libraries</title>
<para>
- Your typical MPEG player was designed to play MPEG video and audio. Most of
- these players have implemented a complete infrastructure focused on
- achieving their only goal: playback. No provisions were made to add
- filters or special effects to the video or audio data.
+ Your typical MPEG player was designed to play MPEG video and audio.
+ Most of these players have implemented a complete infrastructure
+ focused on achieving their only goal: playback. No provisions were
+ made to add filters or special effects to the video or audio data.
</para>
<para>
- If you want to convert an MPEG2 video stream into an AVI file, your best
- option would be to take all of the MPEG2 decoding algorithms out
- of the player and duplicate them into your own AVI encoder. These
- algorithms cannot easily be shared across applications.
+ If you want to convert an MPEG-2 video stream into an AVI file,
+ your best option would be to take all of the MPEG-2 decoding
+ algorithms out of the player and duplicate them into your own
+ AVI encoder. These algorithms cannot easily be shared across
+ applications.
</para>
<para>
- Attempts have been made to create libraries for handling various media types.
- Because they focus on a very specific media type (avifile, libmpeg2, ...),
- significant work is needed to integrate them due to a lack of a common API.
- GStreamer allows you to wrap these libraries with a common API, which
- significantly simplifies integration and reuse.
+ Attempts have been made to create libraries for handling various
+ media types. Because they focus on a very specific media type
+ (avifile, libmpeg2, ...), significant work is needed to integrate
+ them due to a lack of a common API. &GStreamer; allows you to
+ wrap these libraries with a common API, which significantly
+ simplifies integration and reuse.
</para>
</sect2>
<para>
Your typical media player might have a plugin for different media
types. Two media players will typically implement their own plugin
- mechanism so that the codecs cannot be easily exchanged. The plugin system
- of the typical media player is also very tailored to the specific needs
- of the application.
+ mechanism so that the codecs cannot be easily exchanged. The plugin
+ system of the typical media player is also very tailored to the
+ specific needs of the application.
</para>
<para>
The lack of a unified plugin mechanism also seriously hinders the
code to all the different plugin mechanisms.
</para>
<para>
- While GStreamer also uses it own plugin system it offers a very rich
+ While &GStreamer; also uses it own plugin system it offers a very rich
framework for the plugin developper and ensures the plugin can be used
in a wide range of applications, transparently interacting with other
- plugins. The framework that GStreamer provides for the plugins is
+ plugins. The framework that &GStreamer; provides for the plugins is
flexible enough to host even the most demanding plugins.
</para>
</sect2>
+ <sect2 id="section-motivation-experience">
+ <title>Poor user experience</title>
+ <para>
+ Because of the problems mentioned above, application authors have
+ so far often been urged to spend a considerable amount of time in
+ writing their own backends, plugin mechanisms and so on. The result
+ has often been, unfortunately, that both the backend as well as the
+ user interface were only half-finished. Demotivated, the application
+ authors would start rewriting the whole thing and complete the circle.
+ This leads to a <emphasis>poor end user experience</emphasis>.
+ </para>
+ </sect2>
+
<sect2 id="section-motivation-network">
<title>Provision for network transparency</title>
<para>
<para>
No provisions have been made for technologies such as
the <ulink url="http://developer.gnome.org/arch/component/bonobo.html"
- type="http">GNOME object embedding using Bonobo</ulink>.
+ type="http">GNOME object embedding using Bonobo</ulink>.
</para>
<para>
- The GStreamer core does not use network transparent technologies at the
- lowest level as it only adds overhead for the local case.
+ The &GStreamer; core does not use network transparent technologies
+ at the lowest level as it only adds overhead for the local case.
That said, it shouldn't be hard to create a wrapper around the
- core components. There are tcp plugins now that implement a GStreamer
- Data Protocol that allows pipelines to be slit over TCP. These are
- located in the gst-plugins module directory gst/tcp.
+ core components. There are tcp plugins now that implement a
+ &GStreamer; Data Protocol that allows pipelines to be slit over
+ TCP. These are located in the gst-plugins module directory gst/tcp.
</para>
</sect2>
</para>
</sect2>
</sect1>
+
+ <sect1 id="section-goals-design">
+ <title>The design goals</title>
+ <para>
+ We describe what we try to achieve with &GStreamer;.
+ </para>
+ <sect2 id="section-goals-clean">
+ <title>Clean and powerful</title>
+ <para>
+ &GStreamer; wants to provide a clean interface to:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ The application programmer who wants to build a media pipeline.
+ The programmer can use an extensive set of powerful tools to create
+ media pipelines without writing a single line of code. Performing
+ complex media manipulations becomes very easy.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The plugin programmer. Plugin programmers are provided a clean and
+ simple API to create self contained plugins. An extensive debugging
+ and tracing mechanism has been integrated. GStreamer also comes with
+ an extensive set of real-life plugins that serve as examples too.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </sect2>
+ <sect2 id="section-goals-object">
+ <title>Object oriented</title>
+ <para>
+ &GStreamer; adheres to the GLib 2.0 object model. A programmer
+ familiar with GLib 2.0 or older versions of GTK+ will be
+ comfortable with &GStreamer;.
+ </para>
+ <para>
+ &GStreamer; uses the mechanism of signals and object properties.
+ </para>
+ <para>
+ All objects can be queried at runtime for their various properties and
+ capabilities.
+ </para>
+ <para>
+ &GStreamer; intends to be similar in programming methodology to GTK+.
+ This applies to the object model, ownership of objects, reference
+ counting, ...
+ </para>
+ </sect2>
+
+ <sect2 id="section-goals-extensible">
+ <title>Extensible</title>
+ <para>
+ All &GStreamer; Objects can be extended using the GObject
+ inheritance methods.
+ </para>
+ <para>
+ All plugins are loaded dynamically and can be extended and upgraded
+ independently.
+ </para>
+ </sect2>
+
+ <sect2 id="section-goals-binary">
+ <title>Allow binary only plugins</title>
+ <para>
+ Plugins are shared libraries that are loaded at runtime. Since all
+ the properties of the plugin can be set using the GObject properties,
+ there is no need (and in fact no way) to have any header files
+ installed for the plugins.
+ </para>
+ <para>
+ Special care has been taken to make plugins completely selfcontained.
+ All relevant aspects of plugins can be queried at run-time.
+ </para>
+ </sect2>
+
+ <sect2 id="section-goals-performance">
+ <title>High performance</title>
+ <para>
+ High performance is obtained by:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ using GLib's <function>g_mem_chunk</function> and fast
+ non-blocking allocation algorithms where possible to
+ minimize dynamic memory allocation.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ extremely light-weight links between plugins. Data can travel
+ the pipeline with minimal overhead. Data passing between
+ plugins only involves a pointer dereference in a typical
+ pipeline.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ providing a mechanism to directly work on the target memory.
+ A plugin can for example directly write to the X server's
+ shared memory space. Buffers can also point to arbitrary
+ memory, such as a sound card's internal hardware buffer.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ refcounting and copy on write minimize usage of memcpy.
+ Sub-buffers efficiently split buffers into manageable pieces.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the use of cothreads to minimize the threading overhead.
+ Cothreads are a simple and fast user-space method for
+ switching between subtasks. Cothreads were measured to
+ consume as little as 600 cpu cycles.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ allowing hardware acceleration by using specialized plugins.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ using a plugin registry with the specifications of the plugins so
+ that the plugin loading can be delayed until the plugin is actually
+ used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all critical data passing is free of locks and mutexes.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2 id="section-goals-separation">
+ <title>Clean core/plugins separation</title>
+ <para>
+ The core of &GStreamer; is essentially media-agnostic. It only knows
+ about bytes and blocks, and only contains basic elements.
+ The core of &GStreamer; is functional enough to even implement
+ low-level system tools, like cp.
+ </para>
+ <para>
+ All of the media handling functionality is provided by plugins
+ external to the core. These tell the core how to handle specific
+ types of media.
+ </para>
+ </sect2>
+
+ <sect2 id="section-goals-testbed">
+ <title>Provide a framework for codec experimentation</title>
+ <para>
+ &GStreamer; also wants to be an easy framework where codec
+ developers can experiment with different algorithms, speeding up
+ the development of open and free multimedia codecs like <ulink
+ url="http://www.xiph.org/ogg/index.html" type="http">Theora and
+ Vorbis</ulink>.
+ </para>
+ </sect2>
+
+ </sect1>
</chapter>
</para>
<sect1 id="section-intro-what">
- <title>What is GStreamer?</title>
+ <title>What is &GStreamer;?</title>
<para>
- GStreamer is a framework for creating streaming media applications.
+ &GStreamer; is a framework for creating streaming media applications.
The fundamental design comes from the video pipeline at Oregon Graduate
Institute, as well as some ideas from DirectShow.
</para>
<para>
- GStreamer's development framework makes it possible to write any type of
- streaming multimedia application. The GStreamer framework is designed
- to make it easy to write applications that handle audio or video or both.
- It isn't restricted to audio and video, and can process any kind of
- data flow.
+ &GStreamer;'s development framework makes it possible to write any
+ type of streaming multimedia application. The &GStreamer; framework
+ is designed to make it easy to write applications that handle audio
+ or video or both. It isn't restricted to audio and video, and can
+ process any kind of data flow.
The pipeline design is made to have little overhead above what the
- applied filters induce. This makes GStreamer a good framework for designing
- even high-end audio applications which put high demands on latency.
+ applied filters induce. This makes &GStreamer; a good framework for
+ designing even high-end audio applications which put high demands on
+ latency.
</para>
<para>
- One of the the most obvious uses of GStreamer is using it to build
- a media player. GStreamer already includes components for building a
+ One of the the most obvious uses of &GStreamer; is using it to build
+ a media player. &GStreamer; already includes components for building a
media player that can support a very wide variety of formats, including
- MP3, Ogg Vorbis, MPEG1, MPEG2, AVI, Quicktime, mod, and more. GStreamer,
+ MP3, Ogg/Vorbis, MPEG-1/2, AVI, Quicktime, mod, and more. &GStreamer;,
however, is much more than just another media player. Its main advantages
are that the pluggable components can be mixed and matched into arbitrary
pipelines so that it's possible to write a full-fledged video or audio
</para>
<para>
- The GStreamer core function is to provide a framework for plugins, data flow
- and media type handling/negotiation.
- It also provides an API to write applications using the various plugins.
+ The &GStreamer; core function is to provide a framework for plugins,
+ data flow and media type handling/negotiation. It also provides an
+ API to write applications using the various plugins.
</para>
+ </sect1>
+ <sect1 id="section-intro-structure">
+ <title>Structure of this Manual</title>
<para>
- This book is about GStreamer from a developer's point of view; it describes
- how to write a GStreamer application using the GStreamer libraries and tools.
- For an explanation about writing plugins, we suggest the Plugin Writers Guide.
+ This book is about &GStreamer; from a developer's point of view; it
+ describes how to write a &GStreamer; application using the &GStreamer;
+ libraries and tools. For an explanation about writing plugins, we
+ suggest the <ulink type="http"
+ url="http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/index.html">Plugin
+ Writers Guide</ulink>.
</para>
+ <para>
+ <xref linkend="part-overview"/> gives you an overview of &GStreamer;'s
+ motivation design goals.
+ </para>
+
+ <para>
+ <xref linkend="part-basics"/> rapidly covers the basics of &GStreamer;
+ application programming. At the end of that chapter, you should be
+ able to build your own audio player using &GStreamer;
+ </para>
+
+ <para>
+ In <xref linkend="part-advanced"/>, we will move on to complicated
+ subjects which make &GStreamer; stand out of its competitors. We
+ will discuss application-pipeline interaction using dynamic parameters
+ and interfaces, we will discuss threading and threaded pipelines,
+ scheduling and clocks (and synchronization). Most of those topics are
+ not just there to introduce you to their API, but primarily to give
+ a deeper insight in solving application programming problems with
+ &GStreamer; and understanding their concepts.
+ </para>
+
+ <para>
+ Next, in <xref linkend="part-highlevel"/>, we will go into higher-level
+ programming APIs for &GStreamer;. You don't exactly need to know all
+ the details from the previous parts to understand this, but you will
+ need to understand basic &GStreamer; concepts nevertheless. We will,
+ amongst others, discuss XML, playbin and autopluggers.
+ </para>
+
+ <para>
+ In <xref linkend="part-appendices"/>, you will find some random
+ information on integrating with GNOME, KDE, OS X or Windows, some
+ debugging help and general tips to improve and simplify &GStreamer;
+ programming.
+ </para>
+
+ <para>
+ In order to understand this manual, you will need to have a basic
+ understanding of the C language. Since &GStreamer; uses <ulink
+ url="http://developer.gnome.org/arch/gtk/glib.html" type="http">GLib
+ 2.0</ulink>, the reader is assumed to understand the basics of the
+ <ulink url="http://developer.gnome.org/doc/API/2.0/gobject/index.html"
+ type="http">GObject object model</ulink>. It is recommended to have
+ skimmed through the introduction of the <ulink type="http"
+ url="http://www.le-hacker.org/papers/gobject/index.html">GObject
+ tutorial</ulink> before reading this. You may also want to have a look
+ at Eric Harlow's book <emphasis>Developing Linux Applications with
+ GTK+ and GDK</emphasis>.
+ </para>
+
</sect1>
</chapter>
+++ /dev/null
-<chapter id="chapter-intro">
- <title>Introduction</title>
- <para>
- This chapter gives you an overview of the technologies described in this
- book.
- </para>
-
- <sect1 id="section-intro-what">
- <title>What is GStreamer?</title>
- <para>
- GStreamer is a framework for creating streaming media applications.
- The fundamental design comes from the video pipeline at Oregon Graduate
- Institute, as well as some ideas from DirectShow.
- </para>
-
- <para>
- GStreamer's development framework makes it possible to write any type of
- streaming multimedia application. The GStreamer framework is designed
- to make it easy to write applications that handle audio or video or both.
- It isn't restricted to audio and video, and can process any kind of
- data flow.
- The pipeline design is made to have little overhead above what the
- applied filters induce. This makes GStreamer a good framework for designing
- even high-end audio applications which put high demands on latency.
- </para>
-
- <para>
- One of the the most obvious uses of GStreamer is using it to build
- a media player. GStreamer already includes components for building a
- media player that can support a very wide variety of formats, including
- MP3, Ogg Vorbis, MPEG1, MPEG2, AVI, Quicktime, mod, and more. GStreamer,
- however, is much more than just another media player. Its main advantages
- are that the pluggable components can be mixed and matched into arbitrary
- pipelines so that it's possible to write a full-fledged video or audio
- editing application.
- </para>
-
- <para>
- The framework is based on plugins that will provide the various codec
- and other functionality. The plugins can be linked and arranged in
- a pipeline. This pipeline defines the flow of the data. Pipelines can
- also be edited with a GUI editor and saved as XML so that pipeline
- libraries can be made with a minimum of effort.
- </para>
-
- <para>
- The GStreamer core function is to provide a framework for plugins, data flow
- and media type handling/negotiation.
- It also provides an API to write applications using the various plugins.
- </para>
-
- <para>
- This book is about GStreamer from a developer's point of view; it describes
- how to write a GStreamer application using the GStreamer libraries and tools.
- For an explanation about writing plugins, we suggest the Plugin Writers Guide.
- </para>
-
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-links-api">
- <title>Linking elements</title>
- <sect1 id="section-link-basic">
- <title>Making simple links</title>
- <para>
- You can link two pads with:
- </para>
- <programlisting>
- GstPad *srcpad, *sinkpad;
-
- srcpad = gst_element_get_pad (element1, "src");
- sinpad = gst_element_get_pad (element2, "sink");
-
- // link them
- gst_pad_link (srcpad, sinkpad);
- ....
- // and unlink them
- gst_pad_unlink (srcpad, sinkpad);
-
- </programlisting>
- <para>
- A convenient shortcut for the above code is done with the gst_element_link_pads ()
- function:
- </para>
- <programlisting>
-
- // link them
- gst_element_link_pads (element1, "src", element2, "sink");
- ....
- // and unlink them
- gst_element_unlink_pads (element1, "src", element2, "sink");
-
- </programlisting>
- <para>
- An even more convenient shortcut but only works for single-source, single-sink elements is the
- gst_element_link () function:
- </para>
- <programlisting>
-
- // link them
- gst_element_link (element1, element2);
- ....
- // and unlink them
- gst_element_unlink (element1, element2);
-
- </programlisting>
- <para>
- If you have more than one element to link, the gst_element_link_many () function takes
- a NULL-terminated list of elements. Again this only works for single-source single-sink
- elements:
- </para>
- <programlisting>
-
- // link them
- gst_element_link_many (element1, element2, element3, element4, NULL);
- ....
- // and unlink them
- gst_element_unlink_many (element1, element2, element3, element4, NULL);
-
- </programlisting>
- <para>
- You can query if a pad is linked with
- <function>GST_PAD_IS_LINKED (pad)</function>.
- </para>
- <para>
- To query for the <ulink type="http"
- url="../../gstreamer/html/GstPad.html"><classname>GstPad</classname></ulink>
- a pad is linked to, use <function>gst_pad_get_peer (pad)</function>.
- </para>
- </sect1>
-
- <sect1 id="section-link-filtered">
- <title>Making filtered links</title>
- <para>
- You can also force a specific media type on the link by using
- <function>gst_pad_link_filtered ()</function>
- and <function>gst_element_link_filtered ()</function> with capabilities.
- See <xref linkend="section-caps"/> for
- an explanation of capabilities.
- </para>
- </sect1>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-links">
- <title>Linking elements</title>
- <para>
- You can link the different pads of elements together so that the elements
- form a chain.
- </para>
-
- <figure float="1" id="section-link">
- <title>Visualisation of three linked elements</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/linked-elements.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- By linking these three elements, we have created a very simple
- chain. The effect of this will be that the output of the source element
- (element1) will be used as input for the filter element (element2). The
- filter element will do something with the data and send the result to
- the final sink element (element3).
- </para>
- <para>
- Imagine the above graph as a simple MPEG audio decoder. The source
- element is a disk source, the filter element is the MPEG decoder and
- the sink element is your audiocard. We will use this simple graph to
- construct an MPEG player later in this manual.
- </para>
-</chapter>
<!ENTITY EXAFOOT "
<footnote>
-<para>
-The code for this example is automatically extracted from
-the documentation and built under <filename>examples/manual</filename>
-in the GStreamer tarball.
-</para>
+ <para>
+ The code for this example is automatically extracted from
+ the documentation and built under <filename>examples/manual</filename>
+ in the GStreamer tarball.
+ </para>
</footnote>
">
<!-- Part 1: Overview -->
-<!ENTITY INTRO SYSTEM "intro.xml">
-<!ENTITY MOTIVATION SYSTEM "motivation.xml">
-<!ENTITY GOALS SYSTEM "goals.xml">
+<!ENTITY INTRO SYSTEM "intro-preface.xml">
+<!ENTITY MOTIVATION SYSTEM "intro-motivation.xml">
+<!ENTITY CONCEPTS SYSTEM "intro-basics.xml">
<!-- Part 2: Basic Concepts -->
-<!ENTITY ELEMENTS SYSTEM "elements.xml">
-<!ENTITY PADS SYSTEM "pads.xml">
-<!ENTITY LINKS SYSTEM "links.xml">
-<!ENTITY BINS SYSTEM "bins.xml">
-<!ENTITY BUFFERS SYSTEM "buffers.xml">
-<!ENTITY STATES SYSTEM "states.xml">
-<!ENTITY PLUGINS SYSTEM "plugins.xml">
-
-<!-- Part 3: Basic API -->
-<!ENTITY INIT-API SYSTEM "init-api.xml">
-<!ENTITY ELEMENTS-API SYSTEM "elements-api.xml">
-<!ENTITY PADS-API SYSTEM "pads-api.xml">
-<!ENTITY LINKS-API SYSTEM "links-api.xml">
-<!ENTITY BINS-API SYSTEM "bins-api.xml">
-<!ENTITY BUFFERS-API SYSTEM "buffers-api.xml">
-<!ENTITY STATES-API SYSTEM "states-api.xml">
-<!ENTITY PLUGINS-API SYSTEM "plugins-api.xml">
-
-<!-- Part 4: Building An Application -->
-<!ENTITY HELLOWORLD SYSTEM "helloworld.xml">
-<!ENTITY FACTORIES SYSTEM "factories.xml">
-<!ENTITY AUTOPLUGGING SYSTEM "autoplugging.xml">
-<!ENTITY HELLOWORLD2 SYSTEM "helloworld2.xml">
-
-<!-- Part 5: Advanced Concepts -->
-<!ENTITY THREADS SYSTEM "threads.xml">
-<!ENTITY QUEUES SYSTEM "queues.xml">
-<!ENTITY COTHREADS SYSTEM "cothreads.xml">
-<!ENTITY SCHEDULERS SYSTEM "schedulers.xml">
-<!ENTITY CLOCKS SYSTEM "clocks.xml">
-<!ENTITY DYNAMIC SYSTEM "dynamic.xml">
-<!ENTITY TYPEDETECTION SYSTEM "typedetection.xml">
-<!ENTITY UTILITY SYSTEM "utility.xml">
-<!ENTITY DPARAMS SYSTEM "dparams-app.xml">
-
-<!ENTITY XML SYSTEM "xml.xml">
-<!ENTITY DEBUGGING SYSTEM "debugging.xml">
-<!ENTITY PROGRAMS SYSTEM "programs.xml">
-<!ENTITY COMPONENTS SYSTEM "components.xml">
-<!ENTITY GNOME SYSTEM "gnome.xml">
-<!ENTITY WIN32 SYSTEM "win32.xml">
-<!ENTITY QUOTES SYSTEM "quotes.xml">
+<!ENTITY INIT SYSTEM "basics-init.xml">
+<!ENTITY ELEMENTS SYSTEM "basics-elements.xml">
+<!ENTITY BINS SYSTEM "basics-bins.xml">
+<!ENTITY PADS SYSTEM "basics-pads.xml">
+<!ENTITY DATA SYSTEM "basics-data.xml">
+<!ENTITY HELLOWORLD SYSTEM "basics-helloworld.xml">
+
+<!-- Part 3: Advanced Concepts -->
+<!ENTITY QUERYEVENTS SYSTEM "advanced-position.xml">
+<!ENTITY METADATA SYSTEM "advanced-metadata.xml">
+<!ENTITY INTERFACES SYSTEM "advanced-interfaces.xml">
+<!ENTITY CLOCKS SYSTEM "advanced-clocks.xml">
+<!ENTITY DPARAMS SYSTEM "advanced-dparams.xml">
+<!ENTITY THREADS SYSTEM "advanced-threads.xml">
+<!ENTITY SCHEDULERS SYSTEM "advanced-schedulers.xml">
+<!ENTITY AUTOPLUGGING SYSTEM "advanced-autoplugging.xml">
+<!ENTITY DATAACCESS SYSTEM "advanced-dataaccess.xml">
+
+<!-- Part 4: Higher-level interfaces -->
+<!ENTITY XML SYSTEM "highlevel-xml.xml">
+<!ENTITY COMPONENTS SYSTEM "highlevel-components.xml">
+
+<!-- Appendices -->
+<!ENTITY DEBUGGING SYSTEM "appendix-debugging.xml">
+<!ENTITY PROGRAMS SYSTEM "appendix-programs.xml">
+<!ENTITY GNOME SYSTEM "appendix-gnome.xml">
+<!ENTITY WIN32 SYSTEM "appendix-win32.xml">
+<!ENTITY QUOTES SYSTEM "appendix-quotes.xml">
+
+<!ENTITY GStreamer "<application>GStreamer</application>">
]>
<book id="index">
</para>
</authorblurb>
</author>
+ <author>
+ <firstname>Ronald</firstname>
+ <othername>S.</othername>
+ <surname>Bultje</surname>
+ <authorblurb>
+ <para>
+ <email>rbultje@ronald.bitfreak.net</email>
+ </para>
+ </authorblurb>
+ </author>
</authorgroup>
<legalnotice id="misc-legalnotice">
conditions set forth in the Open Publication License, v1.0 or later (the
latest version is presently available at <ulink url="
http://www.opencontent.org/opl.shtml"
- type="http">http://www.opencontent.org/opl.shtml</ulink> )
+ type="http">http://www.opencontent.org/opl.shtml</ulink>).
</para>
</legalnotice>
- <title><application>GStreamer</application> Application Development Manual (&GST_VERSION;)</title>
+ <title>&GStreamer; Application Development Manual (&GST_VERSION;)</title>
</bookinfo>
-<!-- ############# Overview - part ############### -->
+<!-- ############# Introduction & Overview - part ############### -->
- <part id="part-overview"><title>Overview</title>
+ <part id="part-overview">
+ <title>Overview</title>
<partintro>
<para>
- <xref linkend="part-overview"/> gives you an overview of
- <application>GStreamer</application> design goals.
-
- <xref linkend="part-basic-concepts"/> rapidly covers the basics of
- <application>GStreamer</application> programming.
-
- In <xref linkend="part-build-app"/> we will move on to the
- examples. Since <application>GStreamer</application> uses <ulink
- url="http://developer.gnome.org/arch/gtk/glib.html" type="http">GLib
- 2.0</ulink>, the reader is assumed to understand the basics of the
- <ulink url="http://developer.gnome.org/doc/API/2.0/gobject/index.html"
- type="http">GObject object model</ulink>.
-
- For a gentle introduction to this system, you may wish to read the
- <emphasis><ulink url="http://www.gtk.org/tutorial/" type="http">GTK+
- Tutorial</ulink></emphasis>, Eric Harlow's book <emphasis>Developing
- Linux Applications with GTK+ and GDK</emphasis> and the <emphasis>
- <ulink type="http"
- url="http://www.le-hacker.org/papers/gobject/index.html">Glib Object
- system</ulink></emphasis>.
+ &GStreamer; is an exremely powerful and versatile framework for
+ creating streaming media applications. Many of the virtues of the
+ &GStreamer; framework come from its modularity: &GStreamer; can
+ seamlessly incorporate new plugin modules. But because modularity
+ and power often come at a cost of greater complexity (consider,
+ for example, <ulink
+ type="http" url="http://www.omg.org/">CORBA</ulink>), writing new
+ applications is not always easy.
+ </para>
+ <para>
+ This guide is intended to help you understand the &GStreamer;
+ framework (version &GST_VERSION;) so you can develop applications
+ based on it. The first chapters will focus on development of a
+ simple audio player, with much effort going into helping you
+ understand &GStreamer; concepts. Later chapters will go into
+ more advanced topics related to media playback, but also at
+ other forms of media processing (capture, editing, etc.).
</para>
</partintro>
-<!-- ############ Introduction - chapter ############# -->
- &INTRO;
+ &INTRO;
+ &MOTIVATION;
+ &CONCEPTS;
- &MOTIVATION;
-
- &GOALS;
</part>
<!-- ############ Basic concepts - part ############# -->
- <part id="part-basic-concepts">
+ <part id="part-basics">
<title>Basic Concepts</title>
<partintro>
- <para>
- We will first describe the basics of
- <application>GStreamer</application> programming by introducing the
- different objects needed to create a media pipeline.
- </para>
- <para>
- We will use a visual representation of these objects so that we can
- visualize the more complex pipelines you will learn to build later on.
- </para>
- </partintro>
-
- &ELEMENTS;
-
- &PADS;
-
- &PLUGINS;
-
- &LINKS;
-
- &BINS;
-
- &BUFFERS;
-
- &STATES;
- </part>
-
-<!-- ############ Basic API - part ############# -->
- <part id="part-basic-api">
- <title>Basic API</title>
- <partintro>
- <para>
-This chapter will describe the basics of programming with GStreamer.
-Most of the concepts from the previous chapter will be illustrated with code
-fragments.
- </para>
- <para>
-Most of the code examples in this manual are automatically extracted as part
-of the build process of the GStreamer tarball. After building GStreamer from
-source, you will find the examples in <filename>examples/manual</filename>.
-Each example has a comment on the first line giving the name of the file
-it will be extracted as.
- </para>
- </partintro>
-
- &INIT-API;
-
- &ELEMENTS-API;
-
- &PADS-API;
-
- &PLUGINS-API;
-
- &LINKS-API;
-
- &BINS-API;
-
- &BUFFERS-API;
-
- &STATES-API;
-
-
- </part>
-
-<!-- ############ Building Apps - part ############# -->
-
- <part id="part-build-app"><title>Building an application</title>
-
- <partintro>
<para>
- With the basic concepts out of the way, you're ready to start building a
- full-scale <application>GStreamer</application> application.
+ In these chapters, we will discuss the basic concepts of &GStreamer;
+ and the most-used objects, such as elements, pads and buffers. We
+ will use a visual representation of these objects so that we can
+ visualize the more complex pipelines you will learn to build later
+ on. You will get a first glance at the &GStreamer; API, which should
+ be enough for building elementary applications. Later on in this
+ part, you will also learn to build a basic command-line application.
</para>
<para>
- We assume the reader is familiar with GTK+/GNOME programming.
+ Note that this part will give a look into the low-level API and
+ concepts of &GStreamer;. Once you're going to build applications,
+ you might want to use higher-level APIs. Those will be discussed
+ later on in this manual.
</para>
</partintro>
- &HELLOWORLD;
-
- &FACTORIES;
+ &INIT;
+ &ELEMENTS;
+ &BINS;
+ &PADS;
+ &DATA;
+ &HELLOWORLD;
</part>
<!-- ############ Advanced GStreamer - part ############# -->
- <part id="part-advanced"><title>Advanced <application>GStreamer</application> concepts</title>
-
+ <part id="part-advanced">
+ <title>Advanced &GStreamer; concepts</title>
<partintro>
<para>
- In this part we will cover the more advanced features of <application>GStreamer</application>.
- With the basics you learned in the prevous part you should be
- able to create a 'simple' pipeline. If you want more control over
- the media types and the pipeline you should use the more
- low-level features of <application>GStreamer</application>.
+ In this part we will cover the more advanced features of &GStreamer;.
+ With the basics you learned in the previous part you should be
+ able to create a <emphasis>simple</emphasis> application. However,
+ &GStreamer; provides much more candy than just the basics of playing
+ back audio files. In this chapter, you will learn more of the
+ low-level features and internals of &GStreamer;, such as threads,
+ scheduling, synchronization, metadata, interfaces and dynamic
+ parameters.
</para>
</partintro>
- &THREADS;
-
- &QUEUES;
-
- &COTHREADS;
+<!--
+Idea:
+* Querying and events
+ - seeking
+ - getting stream length
+ - prerolls and why
+* Stream info
+ - pads info (see 2.4)
+ - tags
+ - inserting tags
+* Interfaces
+ - each
+* Clocks & Synchronization
+ - stress that it's automated
+* Dynamic parameters
+ - ..
+* Threading
+ - gstthread & queues
+ - buffering (network, live network/video/audio source)
+ - when 1-to-N, N-to-1 and N-to-N elements need threads
+* Scheduling
+ - loop/chain/get etc. (internals)
+ - opt
+* Autoplugging principles
+ - type detection
+ - dynamic element lookup (registry, factories and categories)
+ - reference part4!
+ - Hello world 2
+* Pipeline manipulation
+ - data manipulation (identity, fakesrc, fakesink)
+ - probes (both events and data)
+ - length manipulation (managers, PWG)
+ - explain how to embed elements in applications
+ - explain why separate elements are to be preferred
+-->
+
+ &QUERYEVENTS;
+ &METADATA;
+ &INTERFACES;
+ &CLOCKS;
+ &DPARAMS;
+ &THREADS;
+ &SCHEDULERS;
+ &AUTOPLUGGING;
+ &DATAACCESS;
- &SCHEDULERS;
-
- &CLOCKS;
-
- &DYNAMIC;
-
- &TYPEDETECTION;
-
- &AUTOPLUGGING;
-
- &HELLOWORLD2;
-
- &DPARAMS;
</part>
-<!-- ############ XML in GStreamer - part ############# -->
-
- <part id="part-xml-gstreamer"><title>XML in <application>GStreamer</application></title>
+<!-- ############ Higher-level APIs in GStreamer - part ############# -->
+ <part id="part-highlevel">
+ <title>Higher-level interfaces for &GStreamer; applications</title>
<partintro>
<para>
- <application>GStreamer</application> has the possibility to serialize the pipelines you
- create using an XML format. You can load a previously created pipeline by loading the XML
- file.
+ In the previous two parts, you have learned many of the internals
+ and their corresponding low-level interfaces into &GStreamer;
+ application programming. Many people will, however, not need so
+ much control (and as much code), but will prefer to use a standard
+ playback interface that does most of the difficult internals for
+ them. In this chapter, we will introduce you into the concept of
+ autopluggers, playback managing elements, XML-based pipelines and
+ other such things. Those higher-level interfaces are intended to
+ simplify &GStreamer;-based application programming. They do, however,
+ also reduce the flexibility. It is up to the application developer
+ to choose which interface he will want to use.
</para>
</partintro>
- &XML;
- </part>
+ &COMPONENTS;
+ &XML;
+ </part>
<!-- ############ Appendices - part ############# -->
<part id="part-appendices">
<title>Appendices</title>
-
<partintro>
<para>
- <application>GStreamer</application> comes prepackaged with a few
- programs, and some useful debugging options.
+ By now, you've learned all about the internals of &GStreamer; and
+ application programming using the &GStreamer; framework. This part
+ will go into some random bits that are useful to know if you're
+ going to use &GStreamer; for serious application programming. It
+ will touch upon things related to integration with popular desktop
+ environments that we run on (GNOME, KDE, OS X, Windows), it will
+ shortly explain how applications included with &GStreamer; can help
+ making your life easier, and some information on debugging.
</para>
</partintro>
- &DEBUGGING;
-
- &PROGRAMS;
-
- &COMPONENTS;
-
- &GNOME;
-
- &WIN32;
-
- "ES;
+<!--
+Idea:
+* Debugging and error handling
+ - 'error' signal in pipelines
+ - checking return values and how to handle them
+ - using signals for pipeline states
+ - gst-debug
+ - programs
+* Desktop integration
+ - Linux/UNIX
+ . {x,xv}imagesink
+ . {oss,alsa}sink
+ . {v4l,v4l2,oss,alsa}src
+ - GNOME
+ . GConf ({video,audio}{src,sink})
+ . gnomevfssrc, gnomevfssink
+ . popt
+ . app examples (RB, Totem, gnome-media, ...)
+ - KDE
+ . kiosrc
+ . app examples (JuK, AmaroK)
+ . ask Scott/Mark
+ - Mac OS X
+ . native video/audio sink
+ - Windows
+ . build etc.
+* Quotes from devs
+ - table please...
+-->
+
+ &DEBUGGING;
+ &PROGRAMS;
+ &GNOME;
+ &WIN32;
+ "ES;
</part>
</book>
-
-
-
-
-
-
+++ /dev/null
-<chapter id="chapter-motivation">
- <title>Motivation</title>
- <para>
- Linux has historically lagged behind other operating systems in the multimedia
- arena. Microsoft's <trademark>Windows</trademark> and Apple's <trademark>MacOS</trademark> both have strong support
- for multimedia devices, multimedia content creation,
- playback, and realtime processing. Linux, on the other hand, has a poorly integrated
- collection of multimedia utilities and applications available, which can hardly compete
- with the professional level of software available for MS Windows and MacOS.
- </para>
-
- <sect1 id="section-motivation-problems">
- <title>Current problems</title>
- <para>
- We describe the typical problems in today's media handling on Linux.
- </para>
- <sect2 id="section-motivation-duplicate">
- <title>Multitude of duplicate code</title>
- <para>
- The Linux user who wishes to hear a sound file must hunt through their collection of
- sound file players in order to play the tens of sound file formats in wide use today.
- Most of these players basically reimplement the same code over and over again.
- </para>
- <para>
- The Linux developer who wishes to embed a video clip in their application must use
- crude hacks to run an external video player. There is no library available that a
- developer can use to create a custom media player.
- </para>
-
- </sect2>
- <sect2 id="section-motivation-goal">
- <title>'One goal' media players/libraries</title>
- <para>
- Your typical MPEG player was designed to play MPEG video and audio. Most of
- these players have implemented a complete infrastructure focused on
- achieving their only goal: playback. No provisions were made to add
- filters or special effects to the video or audio data.
- </para>
- <para>
- If you want to convert an MPEG2 video stream into an AVI file, your best
- option would be to take all of the MPEG2 decoding algorithms out
- of the player and duplicate them into your own AVI encoder. These
- algorithms cannot easily be shared across applications.
- </para>
- <para>
- Attempts have been made to create libraries for handling various media types.
- Because they focus on a very specific media type (avifile, libmpeg2, ...),
- significant work is needed to integrate them due to a lack of a common API.
- GStreamer allows you to wrap these libraries with a common API, which
- significantly simplifies integration and reuse.
- </para>
- </sect2>
-
- <sect2 id="section-motivation-plugin">
- <title>Non unified plugin mechanisms</title>
- <para>
- Your typical media player might have a plugin for different media
- types. Two media players will typically implement their own plugin
- mechanism so that the codecs cannot be easily exchanged. The plugin system
- of the typical media player is also very tailored to the specific needs
- of the application.
- </para>
- <para>
- The lack of a unified plugin mechanism also seriously hinders the
- creation of binary only codecs. No company is willing to port their
- code to all the different plugin mechanisms.
- </para>
- <para>
- While GStreamer also uses it own plugin system it offers a very rich
- framework for the plugin developper and ensures the plugin can be used
- in a wide range of applications, transparently interacting with other
- plugins. The framework that GStreamer provides for the plugins is
- flexible enough to host even the most demanding plugins.
- </para>
- </sect2>
-
- <sect2 id="section-motivation-network">
- <title>Provision for network transparency</title>
- <para>
- No infrastructure is present to allow network transparent media
- handling. A distributed MPEG encoder will typically duplicate the
- same encoder algorithms found in a non-distributed encoder.
- </para>
- <para>
- No provisions have been made for technologies such as
- the <ulink url="http://developer.gnome.org/arch/component/bonobo.html"
- type="http">GNOME object embedding using Bonobo</ulink>.
- </para>
- <para>
- The GStreamer core does not use network transparent technologies at the
- lowest level as it only adds overhead for the local case.
- That said, it shouldn't be hard to create a wrapper around the
- core components. There are tcp plugins now that implement a GStreamer
- Data Protocol that allows pipelines to be slit over TCP. These are
- located in the gst-plugins module directory gst/tcp.
- </para>
- </sect2>
-
- <sect2 id="section-motivation-catchup">
- <title>Catch up with the <trademark>Windows</trademark> world</title>
- <para>
- We need solid media handling if we want to see Linux succeed on
- the desktop.
- </para>
- <para>
- We must clear the road for commercially backed codecs and multimedia
- applications so that Linux can become an option for doing multimedia.
- </para>
- </sect2>
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-pads-api">
- <title>Pads</title>
- <para>
- As we have seen in <xref linkend="chapter-elements"/>, the pads are the element's
- interface to the outside world.
- </para>
- <para>
- The specific type of media that the element can handle will be exposed by the pads.
- The description of this media type is done with capabilities(see
- <xref linkend="section-caps"/>)
- </para>
-
- <para>
- Pads are either source or sink pads. The terminology is defined from the
- view of the element itself: elements accept data on their sink pads, and
- send data out on their source pads. Sink pads are drawn on the left,
- while source pads are drawn on the right of an element. In general,
- data flows from left to right in the graph.<footnote>
- <para>
- In reality, there is no objection to data flowing from a
- source pad to the sink pad of an element upstream. Data will, however,
- always flow from a source pad of one element to the sink pad of
- another.
- </para></footnote>
- </para>
-
- <sect1 id="section-pads-api-type">
- <title>Types of pad</title>
-
- <sect2 id="section-pads-api-dynamic">
- <title>Dynamic pads</title>
- <para>
- You can attach a signal to an element to inform you when the element has created
- a new pad from one of its padtemplates. The following piece of code is an example
- of how to do this:
- </para>
- <programlisting>
-static void
-pad_link_func (GstElement *parser, GstPad *pad, GstElement *pipeline)
-{
- g_print("***** a new pad %s was created\n", gst_pad_get_name(pad));
-
- gst_element_set_state (pipeline, GST_STATE_PAUSED);
-
- if (strncmp (gst_pad_get_name (pad), "private_stream_1.0", 18) == 0) {
- // set up an AC3 decoder pipeline
- ...
- // link pad to the AC3 decoder pipeline
- ...
- }
- gst_element_set_state (GST_ELEMENT (audio_thread), GST_STATE_READY);
-}
-
-int
-main(int argc, char *argv[])
-{
- GstElement *pipeline;
- GstElement *mpeg2parser;
-
- // create pipeline and do something useful
- ...
-
- mpeg2parser = gst_element_factory_make ("mpegdemux", "mpegdemux");
- g_signal_connect (G_OBJECT (mpeg2parser), "new_pad", pad_link_func, pipeline);
- ...
-
- // start the pipeline
- gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
- ...
-}
- </programlisting>
- <note>
- <para>
- A pipeline cannot be changed in the PLAYING state.
- </para>
- </note>
- </sect2>
- <sect2 id="section-pads-api-request">
- <title>Request pads</title>
- <para>
- The following piece of code can be used to get a pad from the tee element. After
- the pad has been requested, it can be used to link another element to it.
- </para>
- <programlisting>
- ...
- GstPad *pad;
- ...
- element = gst_element_factory_make ("tee", "element");
-
- pad = gst_element_get_request_pad (element, "src%d");
- g_print ("new pad %s\n", gst_pad_get_name (pad));
- ...
- </programlisting>
- <para>
- The gst_element_get_request_pad method can be used to get a pad
- from the element based on the name_template of the padtemplate.
- </para>
- <para>
- It is also possible to request a pad that is compatible with another
- pad template. This is very useful if you want to link an element
- to a multiplexer element and you need to request a pad that is
- compatible. The gst_element_get_compatible_pad is used to request
- a compatible pad, as is shown in the next example.
- </para>
- <programlisting>
- ...
- GstPadTemplate *templ;
- GstPad *pad;
- ...
- element = gst_element_factory_make ("tee", "element");
- mad = gst_element_factory_make ("mad", "mad");
-
- templ = gst_element_get_pad_template_by_name (mad, "sink");
-
- pad = gst_element_get_compatible_pad (element, templ);
- g_print ("new pad %s\n", gst_pad_get_name (pad));
- ...
- </programlisting>
- </sect2>
-
- </sect1>
-
- <sect1 id="section-api-caps">
- <title>Capabilities of a pad</title>
- <para>
- Since the pads play a very important role in how the element is viewed by the
- outside world, a mechanism is implemented to describe the data that can
- flow through the pad by using capabilities.
- </para>
- <para>
- We will briefly describe what capabilities are, enough for you to get a basic understanding
- of the concepts. You will find more information on how to create capabilities in the
- Plugin Writer's Guide.
- </para>
-
- <sect2 id="section-pads-api-caps">
- <title>Capabilities</title>
- <para>
- Capabilities are attached to a pad in order to describe
- what type of media the pad can handle.
- </para>
- <para>
- Its structure is:
- </para>
- <programlisting>
-struct _GstCaps {
- gchar *name; /* the name of this caps */
- guint16 id; /* type id (major type) */
-
- guint refcount; /* caps are refcounted */
-
- GstProps *properties; /* properties for this capability */
-
- GstCaps *next; /* caps can be chained together */
-};
- </programlisting>
- </sect2>
-
- <sect2 id="section-pads-api-caps-get">
- <title>Getting the capabilities of a pad</title>
- <para>
- A pad can have a chain of capabilities attached to it. You can get the capabilities chain
- with:
- </para>
- <programlisting>
- GstCaps *caps;
- ...
- caps = gst_pad_get_caps (pad);
-
- g_print ("pad name %s\n", gst_pad_get_name (pad));
-
- while (caps) {
- g_print (" Capability name %s, MIME type %s\n",
- gst_caps_get_name (cap),
- gst_caps_get_mime (cap));
-
- caps = caps->next;
- }
- ...
- </programlisting>
- </sect2>
- <sect2 id="section-pads-api-caps-create">
- <title>Creating capability structures</title>
- <para>
- While capabilities are mainly used inside a plugin to describe the
- media type of the pads, the application programmer also has to have
- basic understanding of capabilities in order to interface with the
- plugins, especially when using the autopluggers.
- </para>
- <para>
- As we said, a capability has a name, a mime-type and some
- properties. The signature of the function to create a new
- <ulink type="http" url="../../gstreamer/html/gstreamer-GstCaps.html">
- <classname>GstCaps</classname></ulink> structure is:
- <!-- FIXME: GstProbs are deprecated, in gst-0.8.X -->
- <programlisting>
-GstCaps* gst_caps_new (const gchar *name, const gchar *mime, GstProps *props);
- </programlisting>
- </para>
- <para>
- You can therefore create a new capability with no properties like this:
- <programlisting>
- GstCaps *newcaps;
-
- newcaps = gst_caps_new ("my_caps", "audio/x-wav", NULL);
- </programlisting>
- </para>
- <para>
- <classname>GstProps</classname> basically consist of a set of key-value pairs
- and are created with a function with this signature:
- <programlisting>
-GstProps* gst_props_new (const gchar *firstname, ...);
- </programlisting>
- </para>
- <para>
- The keys are given as strings and the values are given with a set of macros:
- <itemizedlist>
- <listitem>
- <para>
- GST_PROPS_INT(a): An integer value
- </para>
- </listitem>
- <listitem>
- <para>
- GST_PROPS_FLOAT(a): A floating point value
- </para>
- </listitem>
- <listitem>
- <para>
- GST_PROPS_FOURCC(a): A fourcc value
- </para>
- </listitem>
- <listitem>
- <para>
- GST_PROPS_BOOLEAN(a): A boolean value
- </para>
- </listitem>
- <listitem>
- <para>
- GST_PROPS_STRING(a): A string value
- </para>
- </listitem>
- </itemizedlist>
- The values can also be specified as ranges with:
- <itemizedlist>
- <listitem>
- <para>
- GST_PROPS_INT_RANGE(a,b): An integer range from a to b
- </para>
- </listitem>
- <listitem>
- <para>
- GST_PROPS_FLOAT_RANGE(a,b): A float range from a to b
- </para>
- </listitem>
- </itemizedlist>
- All of the above values can be given with a list too, using:
- <itemizedlist>
- <listitem>
- <para>
- GST_PROPS_LIST(a,...): A list of property values.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- A more complex capability with properties is created like this:
- <programlisting>
- GstCaps *newcaps;
-
- newcaps = gst_caps_new ("my_caps",
- "audio/x-wav",
- gst_props_new (
- "bitrate", GST_PROPS_INT_RANGE (11025,22050),
- "depth", GST_PROPS_INT (16),
- "signed", GST_PROPS_LIST (
- GST_PROPS_BOOLEAN (TRUE),
- GST_PROPS_BOOLEAN (FALSE)
- ),
- NULL
- );
- </programlisting>
- Optionally, the convenient shortcut macro can be used. The above complex
- capability can be created with:
- <programlisting>
- GstCaps *newcaps;
-
- newcaps = GST_CAPS_NEW ("my_caps",
- "audio/x-wav",
- "bitrate", GST_PROPS_INT_RANGE (11025,22050),
- "depth", GST_PROPS_INT (16),
- "signed", GST_PROPS_LIST (
- GST_PROPS_BOOLEAN (TRUE),
- GST_PROPS_BOOLEAN (FALSE)
- )
- );
- </programlisting>
- </para>
- </sect2>
-
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-pads">
- <title>Pads</title>
- <para>
- As we have seen in <xref linkend="chapter-elements"/>, the pads are the element's
- interface to the outside world.
- </para>
- <para>
- The specific type of media that the element can handle will be exposed by the pads.
- The description of this media type is done with capabilities(see
- <xref linkend="section-caps"/>)
- </para>
-
- <para>
- Pads are either source or sink pads. The terminology is defined from the
- view of the element itself: elements accept data on their sink pads, and
- send data out on their source pads. Sink pads are drawn on the left,
- while source pads are drawn on the right of an element. In general,
- data flows from left to right in the graph.<footnote>
- <para>
- In reality, there is no objection to data flowing from a
- source pad to the sink pad of an element upstream. Data will, however,
- always flow from a source pad of one element to the sink pad of
- another.
- </para></footnote>
- </para>
-
- <sect1 id="section-pads-type">
- <title>Types of pad</title>
-
- <sect2 id="section-pads-dynamic">
- <title>Dynamic pads</title>
- <para>
- Some elements might not have all of their pads when the element is
- created. This
- can happen, for example, with an MPEG system demultiplexer. The
- demultiplexer will create its pads at runtime when it detects the
- different elementary streams in the MPEG system stream.
- </para>
- <para>
- Running <application>gst-inspect mpegdemux</application> will show that
- the element has only one pad: a sink pad called 'sink'. The other pads are
- "dormant". You can see this in the pad template because there is
- an 'Exists: Sometimes'
- property. Depending on the type of MPEG file you play, the pads will
- be created. We
- will see that this is very important when you are going to create dynamic
- pipelines later on in this manual.
- </para>
- </sect2>
- <sect2 id="section-pads-request">
- <title>Request pads</title>
- <para>
- An element can also have request pads. These pads are not created
- automatically but are only created on demand. This is very useful
- for multiplexers, aggregators and tee elements.
- </para>
- <para>
- The tee element, for example, has one input pad and a request padtemplate for the
- output pads. Whenever an element wants to get an output pad from the tee element, it
- has to request the pad.
- </para>
- </sect2>
-
- </sect1>
-
- <sect1 id="section-caps">
- <title>Capabilities of a pad</title>
- <para>
- Since the pads play a very important role in how the element is viewed by the
- outside world, a mechanism is implemented to describe the data that can
- flow through the pad by using capabilities.
- </para>
- <para>
- We will briefly describe what capabilities are, enough for you to get a basic understanding
- of the concepts. You will find more information on how to create capabilities in the
- Plugin Writer's Guide.
- </para>
-
- <sect2 id="section-pads-caps">
- <title>Capabilities</title>
- <para>
- Capabilities are attached to a pad in order to describe
- what type of media the pad can handle.
- </para>
- <para>
- Capabilities is shorthand for "capability chain". A capability chain
- is a chain of one capability or more.
- </para>
- <para>
- The basic entity is a capability, and is defined by a name, a MIME
- type and a set of properties. A capability can be chained to
- another capability, which is why we commonly refer to a chain of
- capability entities as "capabilities".
- <footnote>
- <para>
- It is important to understand that the term "capabilities" refers
- to a chain of one capability or more. This will be clearer when
- you see the structure definition of a <ulink type="http"
- url="../../gstreamer/html/gstreamer-GstCaps.html"><classname>GstCaps
- </classname></ulink>element.
- </para>
- </footnote>
- </para>
- <para>
- Below is a dump of the capabilities of the element mad, as shown by
- <command>gst-inspect</command>.
- You can see two pads: sink and src. Both pads have capability information attached to them.
- </para>
- <para>
- The sink pad (input pad) is called 'sink' and takes data of MIME type 'audio/mp3'. It also has
- three properties: layer, bitrate and framed.
- </para>
- <para>
- The source pad (output pad) is called 'src' and outputs data of
- MIME type 'audio/raw'. It also has four properties: format, depth,
- rate and channels.
- </para>
- <programlisting>
-Pads:
- SINK template: 'sink'
- Availability: Always
- Capabilities:
- 'mad_sink':
- MIME type: 'audio/mp3':
-
- SRC template: 'src'
- Availability: Always
- Capabilities:
- 'mad_src':
- MIME type: 'audio/raw':
- format: String: int
- endianness: Integer: 1234
- width: Integer: 16
- depth: Integer: 16
- channels: Integer range: 1 - 2
- law: Integer: 0
- signed: Boolean: TRUE
- rate: Integer range: 11025 - 48000
- </programlisting>
- </sect2>
- <sect2 id="section-pads-props">
- <title>What are properties ?</title>
- <para>
- Properties are used to describe extra information for
- capabilities. A property consists of a key (a string) and
- a value. There are different possible value types that can be used:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- basic types:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- an integer value: the property has this exact value.
- </para>
- </listitem>
- <listitem>
- <para>
- a boolean value: the property is either TRUE or FALSE.
- </para>
- </listitem>
- <listitem>
- <para>
- a fourcc value: this is a value that is commonly used to
- describe an encoding for video,
- as used for example by the AVI specification.
- <footnote><para>
- fourcc values consist of four bytes.
- <ulink url="http://www.fourcc.org" type="http">The FOURCC
- Definition List</ulink> is the most complete resource
- on the allowed fourcc values.
- </para></footnote>
- </para>
- </listitem>
- <listitem>
- <para>
- a float value: the property has this exact floating point value.
- </para>
- </listitem>
- <listitem>
- <para>
- a string value.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <listitem>
- <para>
- range types:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- an integer range value: the property denotes a range of
- possible integers. For example, the wavparse element has
- a source pad where the "rate" property can go from 8000 to
- 48000.
- </para>
- </listitem>
- <listitem>
- <para>
- a float range value: the property denotes a range of possible
- floating point values.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <para>
- a list value: the property can take any value from a list of
- basic value types or range types.
- </para>
- </listitem>
- </itemizedlist>
-
- </sect2>
- <sect2 id="section-pads-caps-use">
- <title>What capabilities are used for</title>
- <para>
- Capabilities describe in great detail the type of media that is handled by the pads.
- They are mostly used for:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Autoplugging: automatically finding plugins for a set of capabilities
- </para>
- </listitem>
- <listitem>
- <para>
- Compatibility detection: when two pads are linked, <application>GStreamer</application>
- can verify if the two pads are talking about the same media types.
- The process of linking two pads and checking if they are compatible
- is called "caps negotiation".
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-plugins-api">
- <title>Plugins</title>
- <!-- FIXME: introduce type definitions before this chapter -->
- <para>
- All plugins should implement one function, <function>plugin_init</function>,
- that creates all the element factories and registers all the type
- definitions contained in the plugin.
- Without this function, a plugin cannot be registered.
- </para>
- <para>
- The plugins are maintained in the plugin system. Optionally, the
- type definitions and the element factories can be saved into an XML
- representation so that the plugin system does not have to load all
- available plugins in order to know their definition.
- </para>
-
- <para>
- The basic plugin structure has the following fields:
- </para>
- <programlisting>
-typedef struct _GstPlugin GstPlugin;
-
-struct _GstPlugin {
- gchar *name; /* name of the plugin */
- gchar *longname; /* long name of plugin */
- gchar *filename; /* filename it came from */
-
- GList *types; /* list of types provided */
- gint numtypes;
- GList *elements; /* list of elements provided */
- gint numelements;
- GList *autopluggers; /* list of autopluggers provided */
- gint numautopluggers;
-
- gboolean loaded; /* if the plugin is in memory */
-};
- </programlisting>
-
- <para>
- You can query a <classname>GList</classname> of available plugins with the
- function <function>gst_plugin_get_list</function> as this example shows:
- </para>
- <programlisting>
- GList *plugins;
-
- plugins = gst_plugin_get_list ();
-
- while (plugins) {
- GstPlugin *plugin = (GstPlugin *)plugins->data;
-
- g_print ("plugin: %s\n", gst_plugin_get_name (plugin));
-
- plugins = g_list_next (plugins);
- }
- </programlisting>
-</chapter>
+++ /dev/null
-<chapter id="chapter-plugins">
- <title>Plugins</title>
- <!-- FIXME: introduce type definitions before this chapter -->
- <para>
- A plugin is a shared library that contains at least one of the following
- items:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- one or more element factories
- </para>
- </listitem>
- <listitem>
- <para>
- one or more type definitions
- </para>
- </listitem>
- <listitem>
- <para>
- one or more auto-pluggers
- </para>
- </listitem>
- <listitem>
- <para>
- exported symbols for use in other plugins
- </para>
- </listitem>
- </itemizedlist>
-</chapter>
+++ /dev/null
-<chapter id="chapter-programs">
- <title>Programs</title>
- <para>
- </para>
-
- <sect1 id="section-programs-gst-register">
- <title><command>gst-register</command></title>
- <para>
- <command>gst-register</command> is used to rebuild the database of plugins.
- It is used after a new plugin has been added to the system. The plugin database
- can be found, by default, in <filename>/etc/gstreamer/reg.xml</filename>.
- </para>
- </sect1>
-
- <sect1 id="section-programs-gst-launch">
- <title><command>gst-launch</command></title>
- <para>
- This is a tool that will construct pipelines based on a command-line
- syntax.
- </para>
- <para>
- A simple commandline to play a mp3 audio file looks like:
-
- <screen>
-gst-launch filesrc location=hello.mp3 ! mad ! osssink
- </screen>
-
- A more complex pipeline looks like:
-
- <screen>
-gst-launch filesrc location=redpill.vob ! mpegdemux name=demux \
- demux.audio_00! { ac3parse ! a52dec ! osssink } \
- demux.video_00! { mpeg2dec ! xvideosink }
- </screen>
-
- <xref linkend="section-programs-gst-launch-more-examples"/> lists more gst-launch commandlines.
-
- </para>
- <para>
- You can also use the parser in you own
- code. <application>GStreamer</application> provides a function
- gst_parse_launch () that you can use to construct a pipeline.
- The following program lets you create an MP3 pipeline using the
- gst_parse_launch () function:
- </para>
- <programlisting>
-#include <gst/gst.h>
-
-int
-main (int argc, char *argv[])
-{
- GstElement *pipeline;
- GstElement *filesrc;
- GError *error = NULL;
-
- gst_init (&argc, &argv);
-
- if (argc != 2) {
- g_print ("usage: %s <filename>\n", argv[0]);
- return -1;
- }
-
- pipeline = gst_parse_launch ("filesrc name=my_filesrc ! mad ! osssink", &error);
- if (!pipeline) {
- g_print ("Parse error: %s\n", error->message);
- exit (1);
- }
-
- filesrc = gst_bin_get_by_name (GST_BIN (pipeline), "my_filesrc");
- g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
-
- while (gst_bin_iterate (GST_BIN (pipeline)));
-
- gst_element_set_state (pipeline, GST_STATE_NULL);
-
- return 0;
-}
- </programlisting>
- <para>
- Note how we can retrieve the filesrc element from the constructed bin using the
- element name.
- </para>
- <sect2>
- <title>Grammar Reference</title>
- <para>
- The <command>gst-launch</command> syntax is processed by a flex/bison parser. This section
- is intended to provide a full specification of the grammar; any deviations from this
- specification is considered a bug.
- </para>
- <sect3>
- <title>Elements</title>
- <screen>
- ... mad ...
- </screen>
- <para>
- A bare identifier (a string beginning with a letter and containing
- only letters, numbers, dashes, underscores, percent signs, or colons)
- will create an element from a given element factory. In this example,
- an instance of the "mad" MP3 decoding plugin will be created.
- </para>
- </sect3>
- <sect3>
- <title>Links</title>
- <screen>
- ... !sink ...
- </screen>
- <para>
- An exclamation point, optionally having a qualified pad name (an the name of the pad,
- optionally preceded by the name of the element) on both sides, will link two pads. If
- the source pad is not specified, a source pad from the immediately preceding element
- will be automatically chosen. If the sink pad is not specified, a sink pad from the next
- element to be constructed will be chosen. An attempt will be made to find compatible
- pads. Pad names may be preceded by an element name, as in
- <computeroutput>my_element_name.sink_pad</computeroutput>.
- </para>
- </sect3>
- <sect3>
- <title>Properties</title>
- <screen>
- ... location="http://gstreamer.net" ...
- </screen>
- <para>
- The name of a property, optionally qualified with an element name, and a value,
- separated by an equals sign, will set a property on an element. If the element is not
- specified, the previous element is assumed. Strings can optionally be enclosed in
- quotation marks. Characters in strings may be escaped with the backtick
- (<literal>\</literal>). If the right-hand side is all digits, it is considered to be an
- integer. If it is all digits and a decimal point, it is a double. If it is "true",
- "false", "TRUE", or "FALSE" it is considered to be boolean. Otherwise, it is parsed as a
- string. The type of the property is determined later on in the parsing, and the value is
- converted to the target type. This conversion is not guaranteed to work, it relies on
- the g_value_convert routines. No error message will be displayed on an invalid
- conversion, due to limitations in the value convert API.
- </para>
- <para>
- The list of properties an element supports can be found out using
- <userinput>gst-inspect elemnt-name</userinput>.
- </para>
- </sect3>
- <sect3>
- <title>Bins, Threads, and Pipelines</title>
- <screen>
- ( ... )
- </screen>
- <para>
- A pipeline description between parentheses is placed into a bin. The open paren may be
- preceded by a type name, as in <computeroutput>jackbin.( ... )</computeroutput> to make
- a bin of a specified type. Square brackets '[ ]' make pipelines, and curly braces '{ }' make
- threads. The default toplevel bin type is a pipeline, although putting the whole
- description within parentheses or braces can override this default.
- </para>
- </sect3>
- </sect2>
- <sect2 id="section-programs-gst-launch-more-examples">
- <title>More Examples</title>
- <para>
- This chapter collects some more complex pipelines. The examples are split into several lines,
- so make sure to include the trailing backslashes.
- When modifying the pipelines and seeking for the right element to insert, a grep of the gst-inspect
- output often gives a starting point:
- <screen>
-gst-inspect | grep "avi"
- </screen>
- Another way is to do:
- <screen>
-gst-launch filesrc location=video.avi ! decodebin name=d ! xvimagesink d. ! { queue ! alsasink } -v
- </screen>
- and look on the output, which plugins it chooses.
- </para>
- <para>
- Play a remote mp3 audio file:
- <screen>
-gst-launch gnomevfssrc location=http://www.server.org/hello.mp3 ! mad ! alsasink
- </screen>
- </para>
- <para>
- Play a local mp3 audio file with visualisation:
- <screen>
-gst-launch filesrc location=Hello.mp3 ! mad ! tee name=t ! \
- { queue ! osssink } \
- { t. ! queue ! synaesthesia ! ffmpegcolorspace ! xvimagesink }
- </screen>
- </para>
- <para>
- Play a local ogg audio file:
- <screen>
-gst-launch filesrc location=file.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioscale ! alsasink
- </screen>
- </para>
- <para>
- Play a local ogg video file:
- <screen>
-gst-launch filesrc location=file.ogg ! oggdemux name=demux \
- { demux. ! queue ! theoradec ! ffmpegcolorspace ! videoscale ! xvimagesink } \
- { demux. ! queue ! vorbisdec ! audioconvert ! audioscale ! alsasink }
- </screen>
- </para>
- <para>
- Play a local avi video file:
- <screen>
-gst-launch filesrc location=video.avi ! mpegdemux name=demux \
- demux.audio_00! { queue ! ac3parse ! a52dec ! osssink } \
- demux.video_00! { queue ! mpeg2dec ! xvideosink }
- </screen>
- </para>
- <para>
- Transcoding an audio file from one format into another:
- <screen>
-gst-launch filesrc location=file.ogg ! oggdemux ! vorbisdec ! audioconvert ! flacenc ! filesink location=file.flac
- </screen>
- <screen>
-gst-launch filesrc location=file.mp3 ! id3demus ! mad ! audioconvert ! rawvorbisenc ! oggmux ! filesink location=file.ogg
- </screen>
- </para>
- <para>
- Transcoding an dvd video into a ogg video:
- <screen>
-gst-launch-0.8 oggmux name=mux ! filesink location=/tmp/file.ogg \
- { dvdreadsrc location=/dev/cdrom ! dvddemux name=demux.audio_00 ! \
- { queue ! a52dec ! audioconvert ! rawvorbisenc ! queue ! mux. } \
- { demux.video_00 ! queue ! mpeg2dec ! ffcolorspace ! videoscale ! video/x-raw-yuv,width=384,height=288 ! tee name=t ! \
- { queue ! theoraenc ! queue ! mux. } \
- } \
- } \
- { t. ! queue ! ffcolorspace ! ximagesink }
- </screen>
- </para>
-
- </sect2>
- </sect1>
-
- <sect1 id="section-programs-gst-inspect">
- <title><command>gst-inspect</command></title>
- <para>
- This is a tool to query a plugin or an element about its properties.
- </para>
- <para>
- To query the information about the element mad, you would specify:
- </para>
-
- <screen>
-gst-inspect mad
- </screen>
-
- <para>
- Below is the output of a query for the osssink element:
- </para>
-
- <screen>
-Factory Details:
- Long name: Audio Sink (OSS)
- Class: Sink/Audio
- Description: Output to a sound card via OSS
- Version: 0.3.3.1
- Author(s): Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim.taymans@chello.be>
- Copyright: (C) 1999
-
-GObject
- +----GstObject
- +----GstElement
- +----GstOssSink
-
-Pad Templates:
- SINK template: 'sink'
- Availability: Always
- Capabilities:
- 'osssink_sink':
- MIME type: 'audio/raw':
- format: String: int
- endianness: Integer: 1234
- width: List:
- Integer: 8
- Integer: 16
- depth: List:
- Integer: 8
- Integer: 16
- channels: Integer range: 1 - 2
- law: Integer: 0
- signed: List:
- Boolean: FALSE
- Boolean: TRUE
- rate: Integer range: 1000 - 48000
-
-
-Element Flags:
- GST_ELEMENT_THREADSUGGESTED
-
-Element Implementation:
- No loopfunc(), must be chain-based or not configured yet
- Has change_state() function: gst_osssink_change_state
- Has custom save_thyself() function: gst_element_save_thyself
- Has custom restore_thyself() function: gst_element_restore_thyself
-
-Clocking Interaction:
- element requires a clock
- element provides a clock: GstOssClock
-
-Pads:
- SINK: 'sink'
- Implementation:
- Has chainfunc(): 0x40056fc0
- Pad Template: 'sink'
-
-Element Arguments:
- name : String (Default "element")
- device : String (Default "/dev/dsp")
- mute : Boolean (Default false)
- format : Integer (Default 16)
- channels : Enum "GstAudiosinkChannels" (default 1)
- (0): Silence
- (1): Mono
- (2): Stereo
- frequency : Integer (Default 11025)
- fragment : Integer (Default 6)
- buffer-size : Integer (Default 4096)
-
-Element Signals:
- "handoff" : void user_function (GstOssSink* object,
- gpointer user_data);
- </screen>
-
- <para>
- To query the information about a plugin, you would do:
- </para>
-
- <screen>
-gst-inspect gstelements
- </screen>
- </sect1>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-queues">
- <title>Queues</title>
- <para>
- A queue is a filter element.
- Queues can be used to link two elements in such way that the data can
- be buffered.
- </para>
- <para>
- A buffer that is sinked to a Queue will not automatically be pushed to the
- next linked element but will be buffered. It will be pushed to the next
- element as soon as a gst_pad_pull () is called on the queue's source pad.
- </para>
- <para>
- Queues are mostly used in conjunction with a thread bin to
- provide an external link for the thread's elements. You could have one
- thread feeding buffers into a queue and another
- thread repeatedly pulling on the queue to feed its
- internal elements.
- </para>
-
- <para>
- Below is a figure of a two-threaded decoder. We have one thread (the main execution
- thread) reading the data from a file, and another thread decoding the data.
- </para>
- <figure float="1" id="section-queues-img">
- <title>a two-threaded decoder with a queue</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/queue.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>
- The standard <application>GStreamer</application> queue implementation has some
- properties that can be changed using the g_objet_set () method. To set the
- maximum number of buffers that can be queued to 30, do:
- </para>
- <programlisting>
- g_object_set (G_OBJECT (queue), "max_level", 30, NULL);
- </programlisting>
-
- <para>
- The following MP3 player shows you how to create the above pipeline
- using a thread and a queue.
- </para>
-
- <programlisting>
-<!-- example-begin queue.c a -->
-<![CDATA[
-#include <stdlib.h>
-#include <gst/gst.h>
-
-gboolean playing;
-
-/* eos will be called when the src element has an end of stream */
-void
-eos (GstElement *element, gpointer data)
-{
- g_print ("have eos, quitting\n");
-
- playing = FALSE;
-}
-
-int
-main (int argc, char *argv[])
-{
- GstElement *filesrc, *audiosink, *queue, *decode;
- GstElement *bin;
- GstElement *thread;
-
- gst_init (&argc,&argv);
-
- if (argc != 2) {
- g_print ("usage: %s <mp3 filename>\n", argv[0]);
- exit (-1);
- }
-
- /* create a new thread to hold the elements */
- thread = gst_thread_new ("thread");
- g_assert (thread != NULL);
-
- /* create a new bin to hold the elements */
- bin = gst_bin_new ("bin");
- g_assert (bin != NULL);
-
- /* create a disk reader */
- filesrc = gst_element_factory_make ("filesrc", "disk_source");
- g_assert (filesrc != NULL);
- g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
- g_signal_connect (G_OBJECT (filesrc), "eos",
- G_CALLBACK (eos), thread);
-
- queue = gst_element_factory_make ("queue", "queue");
- g_assert (queue != NULL);
-
- /* and an audio sink */
- audiosink = gst_element_factory_make ("osssink", "play_audio");
- g_assert (audiosink != NULL);
-
- decode = gst_element_factory_make ("mad", "decode");
-
- /* add objects to the main bin */
- gst_bin_add_many (GST_BIN (thread), decode, audiosink, NULL);
-
- gst_bin_add_many (GST_BIN (bin), filesrc, queue, thread, NULL);
-
-
- gst_element_link (filesrc, queue);
- gst_element_link_many (queue, decode, audiosink, NULL);
-
- /* start playing */
- gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
-
- playing = TRUE;
-
- while (playing) {
- gst_bin_iterate (GST_BIN (bin));
- }
-
- gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
-
- return 0;
-}
-]]>
-<!-- example-end queue.c a -->
- </programlisting>
-</chapter>
+++ /dev/null
-<chapter id="chapter-quotes">
- <title>Quotes from the Developers</title>
- <para>
- As well as being a cool piece of software,
- <application>GStreamer</application> is a lively project, with
- developers from around the globe very actively contributing.
- We often hang out on the #gstreamer IRC channel on
- irc.freenode.net: the following are a selection of amusing<footnote>
- <para>No guarantee of sense of humour compatibility is given.</para>
- </footnote> quotes from our conversations.
- </para>
-
- <variablelist>
-
-
- <varlistentry>
- <term>2 Nov 2004</term>
- <listitem>
- <para>
- <emphasis>zaheerm</emphasis>:
-wtay: unfair u fixed the bug i was using as a feature!
- </para>
- </listitem>
- </varlistentry>
-
-
- <varlistentry>
- <term>14 Oct 2004</term>
- <listitem>
- <para>
- <emphasis>* zaheerm</emphasis>
-wonders how he can break gstreamer today :)
- </para>
- <para>
- <emphasis>ensonic</emphasis>:
-zaheerm, spider is always a good starting point
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>14 Jun 2004</term>
- <listitem>
- <para>
- <emphasis>teuf</emphasis>: ok, things work much better when I don't write incredibly stupid and buggy code
- </para>
- <para>
- <emphasis>thaytan</emphasis>: I find that too
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>23 Nov 2003</term>
- <listitem>
- <para>
- <emphasis>Uraeus</emphasis>: ah yes, the sleeping part, my mind
- is not multitasking so I was still thinking about exercise
- </para>
- <para>
- <emphasis>dolphy</emphasis>: Uraeus: your mind is multitasking
- </para>
- <para>
- <emphasis>dolphy</emphasis>: Uraeus: you just miss low latency patches
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>14 Sep 2002</term>
- <listitem>
- <para>
- --- <emphasis>wingo-party</emphasis> is now known as
- <emphasis>wingo</emphasis>
- </para>
- <para>
- * <emphasis>wingo</emphasis> holds head
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>16 Feb 2001</term>
- <listitem>
- <para>
- <emphasis>wtay:</emphasis>
- I shipped a few commerical products to >40000 people now but
- GStreamer is way more exciting...
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>16 Feb 2001</term>
- <listitem>
- <para>
- *
- <emphasis>tool-man</emphasis>
- is a gstreamer groupie
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>14 Jan 2001</term>
- <listitem>
- <para>
- <emphasis>Omega:</emphasis>
- did you run ldconfig? maybe it talks to init?
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- not sure, don't think so...
- I did run gstreamer-register though :-)
- </para>
- <para>
- <emphasis>Omega:</emphasis>
- ah, that did it then ;-)
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- right
- </para>
- <para>
- <emphasis>Omega:</emphasis>
- probably not, but in case GStreamer starts turning into an OS, someone please let me know?
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>9 Jan 2001</term>
- <listitem>
- <para>
- <emphasis>wtay:</emphasis>
- me tar, you rpm?
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- hehe, forgot "zan"
- </para>
- <para>
- <emphasis>Omega:</emphasis>
- ?
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- me tar"zan", you ...
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>7 Jan 2001</term>
- <listitem>
- <para>
- <emphasis>Omega:</emphasis>
- that means probably building an agreggating, cache-massaging
- queue to shove N buffers across all at once, forcing cache
- transfer.
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- never done that before...
- </para>
- <para>
- <emphasis>Omega:</emphasis>
- nope, but it's easy to do in gstreamer <g>
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- sure, I need to rewrite cp with gstreamer too, someday :-)
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>7 Jan 2001</term>
- <listitem>
- <para>
- <emphasis>wtay:</emphasis>
- GStreamer; always at least one developer is awake...
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>5/6 Jan 2001</term>
- <listitem>
- <para>
- <emphasis>wtay:</emphasis>
- we need to cut down the time to create an mp3 player down to
- seconds...
- </para>
- <para>
- <emphasis>richardb:</emphasis>
- :)
- </para>
- <para>
- <emphasis>Omega:</emphasis>
- I'm wanting to something more interesting soon, I did the "draw an mp3
- player in 15sec" back in October '99.
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- by the time Omega gets his hands on the editor, you'll see a
- complete audio mixer in the editor :-)
- </para>
- <para>
- <emphasis>richardb:</emphasis>
- Well, it clearly has the potential...
- </para>
- <para>
- <emphasis>Omega:</emphasis>
- Working on it... ;-)
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>28 Dec 2000</term>
- <listitem>
- <para>
- <emphasis>MPAA:</emphasis>
- We will sue you now, you have violated our IP rights!
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- hehehe
- </para>
- <para>
- <emphasis>MPAA:</emphasis>
- How dare you laugh at us? We have lawyers! We have Congressmen! We have <emphasis>LARS</emphasis>!
- </para>
- <para>
- <emphasis>wtay:</emphasis>
- I'm so sorry your honor
- </para>
- <para>
- <emphasis>MPAA:</emphasis>
- Hrumph.
- </para>
- <para>
- *
- <emphasis>wtay</emphasis>
- bows before thy
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>4 Jun 2001</term>
- <listitem>
- <para><emphasis>taaz:</emphasis> you witchdoctors and your voodoo mpeg2 black magic... </para>
- <para><emphasis>omega_:</emphasis> um. I count three, no four different cults there <g> </para>
- <para><emphasis>ajmitch:</emphasis> hehe </para>
- <para><emphasis>omega_:</emphasis> witchdoctors, voodoo, black magic, </para>
- <para><emphasis>omega_:</emphasis> and mpeg </para>
- </listitem>
- </varlistentry>
- </variablelist>
-</chapter>
+++ /dev/null
-<chapter id="chapter-scheduler">
- <title>Understanding schedulers</title>
- <para>
- The scheduler is responsible for managing the plugins at runtime. Its
- main responsibilities are:
- <itemizedlist>
- <listitem>
- <para>
- Preparing the plugins so they can be scheduled.
- </para>
- </listitem>
- <listitem>
- <para>
- Monitoring state changes and enabling/disabling the element in the
- chain.
- </para>
- </listitem>
- <listitem>
- <para>
- Choosing an element as the entry point for the pipeline.
- </para>
- </listitem>
- <listitem>
- <para>
- Selecting and distributing the global clock.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- The scheduler is a pluggable component; this means that alternative
- schedulers can be written and plugged into GStreamer. The default scheduler
- uses cothreads to schedule the plugins in a pipeline. Cothreads are fast
- and lightweight user-space threads.
- </para>
- <para>
- There is usually no need to interact with the scheduler directly, however
- in some cases it is feasible to set a specific clock or force a specific
- plugin as the entry point in the pipeline.
- </para>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-states-api">
- <title>Element states</title>
- <sect1 id="section-states-api">
- <title>Changing element state</title>
- <para>
- The state of an element can be changed with the following code:
- </para>
- <programlisting>
- GstElement *bin;
-
- // create a bin, put elements in it and link them
- ...
- gst_element_set_state (bin, GST_STATE_PLAYING);
- ...
- </programlisting>
-
- <para>
- You can set the following states on an element:
- </para>
- <informaltable pgwide="1" frame="none" role="enum">
- <tgroup cols="2">
- <tbody>
- <row>
- <entry><literal>GST_STATE_NULL</literal></entry>
- <entry>Reset the state of an element.
- </entry>
- </row>
- <row>
- <entry><literal>GST_STATE_READY</literal></entry>
- <entry>will make the element ready to start processing data.
- </entry>
- </row>
- <row>
- <entry><literal>GST_STATE_PAUSED</literal></entry>
- <entry>temporary stops the data flow.
- </entry>
- </row>
- <row>
- <entry><literal>GST_STATE_PLAYING</literal></entry>
- <entry>means there really is data flowing through the graph.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-states">
- <title>Element states</title>
- <para>
- Once you have created a pipeline packed with elements, nothing will happen
- right away. This is where the different states come into play.
- </para>
-
- <sect1 id="section-states">
- <title>The different element states</title>
- <para>
- An element can be in one of the following four states:
- <itemizedlist>
- <listitem>
- <para>
- NULL: this is the default state all elements are in when they are created
- and are doing nothing.
- </para>
- </listitem>
- <listitem>
- <para>
- READY: An element is ready to start doing something.
- </para>
- </listitem>
- <listitem>
- <para>
- PAUSED: The element is paused for a period of time.
- </para>
- </listitem>
- <listitem>
- <para>
- PLAYING: The element is doing something.
- </para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>
- All elements start with the NULL state. The elements will go throught
- the following state changes: NULL -> READY -> PAUSED ->
- PLAYING. When going from NULL to PLAYING, GStreamer will
- internally go throught the intermediate states.
- </para>
-
- <para>
- You can set the following states on an element:
- </para>
- <informaltable pgwide="1" frame="none" role="enum">
- <tgroup cols="2">
- <tbody>
- <row>
- <entry><literal>GST_STATE_NULL</literal></entry>
- <entry>Reset the state of an element.
- </entry>
- </row>
- <row>
- <entry><literal>GST_STATE_READY</literal></entry>
- <entry>will make the element ready to start processing data.
- </entry>
- </row>
- <row>
- <entry><literal>GST_STATE_PAUSED</literal></entry>
- <entry>temporarily stops the data flow.
- </entry>
- </row>
- <row>
- <entry><literal>GST_STATE_PLAYING</literal></entry>
- <entry>means there really is data flowing through the graph.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- </sect1>
-
- <sect1 id="section-states-null">
- <title>The NULL state</title>
- <para>
- When you created the pipeline all of the elements will be in the NULL state. There is
- nothing special about the NULL state.
- </para>
- <note>
- <para>
- Don't forget to reset the pipeline to the NULL state when you are not going to use it
- anymore. This will allow the elements to free the resources they might use.
- </para>
- </note>
- </sect1>
-
- <sect1 id="section-states-ready">
- <title>The READY state</title>
- <para>
- You will start the pipeline by first setting it to the READY state. This will allow the
- pipeline and all the elements contained in it to prepare themselves for the actions
- they are about to perform.
- </para>
- <para>
- The typical actions that an element will perform in the READY state might be to open a file or
- an audio device. Some more complex elements might have a non trivial action to perform in
- the READY state such as connecting to a media server using a CORBA connection.
- </para>
- <note>
- <para>
- You can also go from the NULL to PLAYING state directly without
- going through the READY state. This is a shortcut; the framework
- will internally go through the READY and the PAUSED state for you.
- </para>
- </note>
- </sect1>
-
- <sect1 id="section-states-paused">
- <title>The PAUSED state</title>
- <para>
- A pipeline that is playing can be set to the PAUSED state. This will temporarily stop all
- data flowing through the pipeline.
- </para>
- <para>
- You can resume the data flow by setting the pipeline back to the PLAYING state.
- </para>
- <note>
- <para>
- The PAUSED state is available for temporarily freezing the pipeline.
- Elements will typically not free their resources in the PAUSED state.
- Use the NULL state if you want to stop the data flow permanently.
- </para>
- </note>
- <para>
- The pipeline has to be in the PAUSED or NULL state if you want to insert or modify an element
- in the pipeline. We will cover dynamic pipeline behaviour in <xref linkend="chapter-dynamic"/>.
- </para>
- </sect1>
- <sect1 id="section-states-playing">
- <title>The PLAYING state</title>
- <para>
- A pipeline can be started by setting it to the PLAYING state. At
- that time data will start to flow all the way through the pipeline.
- </para>
- </sect1>
-
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-threads">
- <title>Threads</title>
- <para>
- GStreamer has support for multithreading through the use of
- the <ulink type="http" url="../../gstreamer/html/GstThread.html"><classname>
- GstThread</classname></ulink> object. This object is in fact
- a special <ulink type="http" url="../../gstreamer/html/GstBin.html"><classname>
- GstBin</classname></ulink> that will become a thread when started.
- </para>
-
- <para>
- To construct a new thread you will perform something like:
- </para>
-
- <para>
- <programlisting>
- GstElement *my_thread;
-
- /* create the thread object */
- my_thread = gst_thread_new ("my_thread");
- /* you could have used gst_element_factory_make ("thread", "my_thread"); */
- g_return_if_fail (my_thread != NULL);
-
- /* add some plugins */
- gst_bin_add (GST_BIN (my_thread), GST_ELEMENT (funky_src));
- gst_bin_add (GST_BIN (my_thread), GST_ELEMENT (cool_effect));
-
- /* link the elements here... */
- ...
-
- /* start playing */
- gst_element_set_state (GST_ELEMENT (my_thread), GST_STATE_PLAYING);
-
- </programlisting>
- </para>
- <para>
- The above program will create a thread with two elements in it. As soon
- as it is set to the PLAYING state, the thread will start to iterate
- itself. You never need to explicitly iterate a thread.
- </para>
-
- <sect1 id="section-threads-constraints">
- <title>Constraints placed on the pipeline by the GstThread</title>
- <para>
- Within the pipeline, everything is the same as in any other bin. The
- difference lies at the thread boundary, at the link between the
- thread and the outside world (containing bin). Since GStreamer is
- fundamentally buffer-oriented rather than byte-oriented, the natural
- solution to this problem is an element that can "buffer" the buffers
- between the threads, in a thread-safe fashion. This element is the
- queue, described more fully in <xref linkend="chapter-queues"/>. It doesn't
- matter if the queue is placed in the containing bin or in the thread
- itself, but it needs to be present on one side or the other to enable
- inter-thread communication.
- </para>
- </sect1>
- <sect1 id="section-threads-when">
- <title>When would you want to use a thread?</title>
- <para>
- If you are writing a GUI application, making the top-level bin a thread will make your GUI
- more responsive. If it were a pipeline instead, it would have to be iterated by your
- application's event loop, which increases the latency between events (say, keyboard presses)
- and responses from the GUI. In addition, any slight hang in the GUI would delay iteration of
- the pipeline, which (for example) could cause pops in the output of the sound card, if it is
- an audio pipeline.
- </para>
- <para>
- <xref linkend="section-threads-img"/> shows how a thread can be visualised.
- </para>
- <figure float="1" id="section-threads-img">
- <title>A thread</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/thread.ℑ" format="&IMAGE;" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>
- As an example we show the helloworld program using a thread.
- </para>
-
- <para>
- <programlisting>
-<!-- example-begin threads.c a -->
-<![CDATA[
-#include <gst/gst.h>
-
-/* we set this to TRUE right before gst_main (), but there could still
- be a race condition between setting it and entering the function */
-gboolean can_quit = FALSE;
-
-/* eos will be called when the src element has an end of stream */
-void
-eos (GstElement *src, gpointer data)
-{
- GstThread *thread = GST_THREAD (data);
- g_print ("have eos, quitting\n");
-
- /* stop the bin */
- gst_element_set_state (GST_ELEMENT (thread), GST_STATE_NULL);
-
- while (!can_quit) /* waste cycles */ ;
- gst_main_quit ();
-}
-
-int
-main (int argc, char *argv[])
-{
- GstElement *filesrc, *demuxer, *decoder, *converter, *audiosink;
- GstElement *thread;
-
- if (argc < 2) {
- g_print ("usage: %s <Ogg/Vorbis filename>\n", argv[0]);
- exit (-1);
- }
-
- gst_init (&argc, &argv);
-
- /* create a new thread to hold the elements */
- thread = gst_thread_new ("thread");
- g_assert (thread != NULL);
-
- /* create a disk reader */
- filesrc = gst_element_factory_make ("filesrc", "disk_source");
- g_assert (filesrc != NULL);
- g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
- g_signal_connect (G_OBJECT (filesrc), "eos",
- G_CALLBACK (eos), thread);
-
- /* create an ogg demuxer */
- demuxer = gst_element_factory_make ("oggdemux", "demuxer");
- g_assert (demuxer != NULL);
-
- /* create a vorbis decoder */
- decoder = gst_element_factory_make ("vorbisdec", "decoder");
- g_assert (decoder != NULL);
-
- /* create an audio converter */
- converter = gst_element_factory_make ("audioconvert", "converter");
- g_assert (decoder != NULL);
-
- /* and an audio sink */
- audiosink = gst_element_factory_make ("osssink", "play_audio");
- g_assert (audiosink != NULL);
-
- /* add objects to the thread */
- gst_bin_add_many (GST_BIN (thread), filesrc, demuxer, decoder, converter, audiosink, NULL);
- /* link them in the logical order */
- gst_element_link_many (filesrc, demuxer, decoder, converter, audiosink, NULL);
-
- /* start playing */
- gst_element_set_state (thread, GST_STATE_PLAYING);
-
- /* do whatever you want here, the thread will be playing */
- g_print ("thread is playing\n");
-
- can_quit = TRUE;
- gst_main ();
-
- gst_object_unref (GST_OBJECT (thread));
-
- exit (0);
-}
-]]>
-<!-- example-end threads.c a -->
- </programlisting>
- </para>
- </sect1>
-</chapter>
+++ /dev/null
-<chapter id="chapter-typedetection">
- <title>Type Detection</title>
- <para>
- Sometimes the capabilities of a pad are not specificied. The filesrc
- element, for example, does not know what type of file it is reading. Before
- you can attach an element to the pad of the filesrc, you need to determine
- the media type in order to be able to choose a compatible element.
- </para>
- <para>
- To solve this problem, a plugin can provide the <application>GStreamer</application>
- core library with a type definition. The type definition
- will contain the following information:
- <itemizedlist>
- <listitem>
- <para>
- The MIME type we are going to define.
- </para>
- </listitem>
- <listitem>
- <para>
- An optional string with a list of possible file extensions this
- type usually is associated with. the list entries are separated with
- a space. eg, ".mp3 .mpa .mpg".
- </para>
- </listitem>
- <listitem>
- <para>
- An optional typefind function.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- The typefind functions give a meaning to the MIME types that are used
- in GStreamer. The typefind function is a function with the following definition:
- </para>
- <programlisting>
-typedef GstCaps *(*GstTypeFindFunc) (GstBuffer *buf, gpointer priv);
- </programlisting>
- <para>
- This typefind function will inspect a GstBuffer with data and will output
- a GstCaps structure describing the type. If the typefind function does not
- understand the buffer contents, it will return NULL.
- </para>
- <para>
- <application>GStreamer</application> has a typefind element in the set
- of core elements
- that can be used to determine the type of a given pad.
- </para>
- <para>
- The next example will show how a typefind element can be inserted into a pipeline
- to detect the media type of a file. It will output the capabilities of the pad into
- an XML representation.
- </para>
- <programlisting>
-#include <gst/gst.h>
-
-void type_found (GstElement *typefind, GstCaps* caps);
-
-int
-main(int argc, char *argv[])
-{
- GstElement *bin, *filesrc, *typefind;
-
- gst_init (&argc, &argv);
-
- if (argc != 2) {
- g_print ("usage: %s <filename>\n", argv[0]);
- exit (-1);
- }
-
- /* create a new bin to hold the elements */
- bin = gst_bin_new ("bin");
- g_assert (bin != NULL);
-
- /* create a disk reader */
- filesrc = gst_element_factory_make ("filesrc", "disk_source");
- g_assert (filesrc != NULL);
- g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
-
- /* create the typefind element */
- typefind = gst_element_factory_make ("typefind", "typefind");
- g_assert (typefind != NULL);
-
- /* add objects to the main pipeline */
- gst_bin_add_many (GST_BIN (bin), filesrc, typefind, NULL);
-
- g_signal_connect (G_OBJECT (typefind), "have_type",
- G_CALLBACK (type_found), NULL);
-
- gst_element_link (filesrc, typefind);
-
- /* start playing */
- gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
-
- gst_bin_iterate (GST_BIN (bin));
-
- gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
-
- exit (0);
-}
- </programlisting>
- <para>
- We create a very simple pipeline with only a filesrc and the typefind
- element in it. The sinkpad of the typefind element has been linked
- to the source pad of the filesrc.
- </para>
- <para>
- We attached a signal 'have_type' to the typefind element which will be called
- when the type of the media stream as been detected.
- </para>
- <para>
- The typefind function will loop over all the registered types and will
- execute each of the typefind functions. As soon as a function returns
- a GstCaps pointer, the type_found function will be called:
- </para>
-
- <programlisting>
-void
-type_found (GstElement *typefind, GstCaps* caps)
-{
- xmlDocPtr doc;
- xmlNodePtr parent;
-
- doc = xmlNewDoc ("1.0");
- doc->root = xmlNewDocNode (doc, NULL, "Capabilities", NULL);
-
- parent = xmlNewChild (doc->root, NULL, "Caps1", NULL);
- gst_caps_save_thyself (caps, parent);
-
- xmlDocDump (stdout, doc);
-}
- </programlisting>
- <para>
- In the type_found function we can print or inspect the type that has been
- detected using the GstCaps APIs. In this example, we just print out the
- XML representation of the caps structure to stdout.
- </para>
- <para>
- A more useful option would be to use the registry to look up an element
- that can handle this particular caps structure, or we can also use the
- autoplugger to link this caps structure to, for example, a videosink.
- </para>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-win32">
-<title>Windows support</title>
- <sect1 id="section-win32-build">
- <title>Building <application>GStreamer</application> under Win32</title>
-
-<para>There are different makefiles that can be used to build GStreamer with the usual Microsoft
-compiling tools.</para>
-
-<para>The Makefile is meant to be used with the GNU make program and the free
-version of the Microsoft compiler (<ulink url="http://msdn.microsoft.com/visualc/vctoolkit2003/">http://msdn.microsoft.com/visualc/vctoolkit2003/</ulink>). You also
-have to modify your system environment variables to use it from the command-line. You will also
-need a working Platform SDK for Windows that is available for free from Microsoft.</para>
-
-<para>The projects/makefiles will generate automatically some source files needed to compile
-GStreamer. That requires that you have installed on your system some GNU tools and that they are
-available in your system PATH.</para>
-
-<para>The GStreamer project depends on other libraries, namely :</para>
-<itemizedlist>
-<listitem><para>GLib</para></listitem>
-<listitem><para>popt</para></listitem>
-<listitem><para>libxml2</para></listitem>
-<listitem><para>libintl</para></listitem>
-<listitem><para>libiconv</para></listitem>
-</itemizedlist>
-
-<para>There is now an existing package that has all these dependencies built with MSVC7.1. It exists either as precompiled librairies
-and headers in both Release and Debug mode, or as the source package to build it yourself. You can
-find it on <ulink url="http://mukoli.free.fr/gstreamer/deps/">http://mukoli.free.fr/gstreamer/deps/</ulink>.</para>
-
-<note>
-<title>Notes</title>
-
-<para>GNU tools needed that you can find on <ulink url="http://gnuwin32.sourceforge.net/">http://gnuwin32.sourceforge.net/</ulink></para>
-<itemizedlist>
-<listitem><para>GNU flex (tested with 2.5.4)</para></listitem>
-<listitem><para>GNU bison (tested with 1.35)</para></listitem>
-</itemizedlist>
-
-<para>and <ulink url="http://www.mingw.org/">http://www.mingw.org/</ulink></para>
-<itemizedlist>
-<listitem><para>GNU make (tested with 3.80)</para></listitem>
-</itemizedlist>
-
-<para>the generated files from the -auto makefiles will be available soon separately on the net
-for convenience (people who don't want to install GNU tools).</para>
-</note>
-</sect1>
-
- <sect1 id="section-win32-install">
-<title>Installation on the system</title>
-
-<para>By default, GSTreamer needs a registry. You have to generate it using "gst-register.exe". It will create
-the file in c:\gstreamer\registry.xml that will hold all the plugins you can use.</para>
-
-<para>You should install the GSTreamer core in c:\gstreamer\bin and the plugins in c:\gstreamer\plugins. Both
-directories should be added to your system PATH. The library dependencies should be installed in c:\usr</para>
-
-<para>For example, my current setup is :</para>
-
-<itemizedlist>
-<listitem><para><filename>c:\gstreamer\registry.xml</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\bin\gst-inspect.exe</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\bin\gst-launch.exe</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\bin\gst-register.exe</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\bin\gstbytestream.dll</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\bin\gstelements.dll</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\bin\gstoptimalscheduler.dll</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\bin\gstspider.dll</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\bin\libgtreamer-0.8.dll</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\plugins\gst-libs.dll</filename></para></listitem>
-<listitem><para><filename>c:\gstreamer\plugins\gstmatroska.dll</filename></para></listitem>
-<listitem><para><filename>c:\usr\bin\iconv.dll</filename></para></listitem>
-<listitem><para><filename>c:\usr\bin\intl.dll</filename></para></listitem>
-<listitem><para><filename>c:\usr\bin\libglib-2.0-0.dll</filename></para></listitem>
-<listitem><para><filename>c:\usr\bin\libgmodule-2.0-0.dll</filename></para></listitem>
-<listitem><para><filename>c:\usr\bin\libgobject-2.0-0.dll</filename></para></listitem>
-<listitem><para><filename>c:\usr\bin\libgthread-2.0-0.dll</filename></para></listitem>
-<listitem><para><filename>c:\usr\bin\libxml2.dll</filename></para></listitem>
-<listitem><para><filename>c:\usr\bin\popt.dll</filename></para></listitem>
-</itemizedlist>
-
-</sect1>
-
-</chapter>
+++ /dev/null
-<chapter id="chapter-xml">
- <title>XML in <application>GStreamer</application></title>
- <para>
- <application>GStreamer</application> uses XML to store and load
- its pipeline definitions. XML is also used internally to manage the
- plugin registry. The plugin registry is a file that contains the definition
- of all the plugins <application>GStreamer</application> knows about to have
- quick access to the specifics of the plugins.
- </para>
-
- <para>
- We will show you how you can save a pipeline to XML and how you can reload that
- XML file again for later use.
- </para>
-
- <sect1 id="section-xml-write">
- <title>Turning GstElements into XML</title>
-
- <para>
- We create a simple pipeline and write it to stdout with
- gst_xml_write_file (). The following code constructs an MP3 player
- pipeline with two threads and then writes out the XML both to stdout
- and to a file. Use this program with one argument: the MP3 file on disk.
- </para>
-
- <programlisting>
-
-<!-- example-begin xml-mp3.c a -->
-<![CDATA[
-#include <stdlib.h>
-#include <gst/gst.h>
-
-gboolean playing;
-
-int
-main (int argc, char *argv[])
-{
- GstElement *filesrc, *osssink, *queue, *queue2, *decode;
- GstElement *bin;
- GstElement *thread, *thread2;
-
- gst_init (&argc,&argv);
-
- if (argc != 2) {
- g_print ("usage: %s <mp3 filename>\n", argv[0]);
- exit (-1);
- }
-
- /* create a new thread to hold the elements */
- thread = gst_element_factory_make ("thread", "thread");
- g_assert (thread != NULL);
- thread2 = gst_element_factory_make ("thread", "thread2");
- g_assert (thread2 != NULL);
-
- /* create a new bin to hold the elements */
- bin = gst_bin_new ("bin");
- g_assert (bin != NULL);
-
- /* create a disk reader */
- filesrc = gst_element_factory_make ("filesrc", "disk_source");
- g_assert (filesrc != NULL);
- g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
-
- queue = gst_element_factory_make ("queue", "queue");
- queue2 = gst_element_factory_make ("queue", "queue2");
-
- /* and an audio sink */
- osssink = gst_element_factory_make ("osssink", "play_audio");
- g_assert (osssink != NULL);
-
- decode = gst_element_factory_make ("mad", "decode");
- g_assert (decode != NULL);
-
- /* add objects to the main bin */
- gst_bin_add_many (GST_BIN (bin), filesrc, queue, NULL);
-
- gst_bin_add_many (GST_BIN (thread), decode, queue2, NULL);
-
- gst_bin_add (GST_BIN (thread2), osssink);
-
- gst_element_link_many (filesrc, queue, decode, queue2, osssink, NULL);
-
- gst_bin_add_many (GST_BIN (bin), thread, thread2, NULL);
-
- /* write the bin to stdout */
- gst_xml_write_file (GST_ELEMENT (bin), stdout);
-
- /* write the bin to a file */
- gst_xml_write_file (GST_ELEMENT (bin), fopen ("xmlTest.gst", "w"));
-
- exit (0);
-}
-]]>
-<!-- example-end xml-mp3.c a -->
- </programlisting>
- <para>
- The most important line is:
- </para>
- <programlisting>
- gst_xml_write_file (GST_ELEMENT (bin), stdout);
- </programlisting>
- <para>
- gst_xml_write_file () will turn the given element into an xmlDocPtr that
- is then formatted and saved to a file. To save to disk, pass the result
- of a fopen(2) as the second argument.
- </para>
- <para>
- The complete element hierarchy will be saved along with the inter element
- pad links and the element parameters. Future <application>GStreamer</application>
- versions will also allow you to store the signals in the XML file.
- </para>
- </sect1>
-
- <sect1 id="section-xml-load">
- <title>Loading a GstElement from an XML file</title>
- <para>
- Before an XML file can be loaded, you must create a GstXML object.
- A saved XML file can then be loaded with the
- gst_xml_parse_file (xml, filename, rootelement) method.
- The root element can optionally left NULL. The following code example loads
- the previously created XML file and runs it.
- </para>
- <programlisting>
-#include <stdlib.h>
-#include <gst/gst.h>
-
-int
-main(int argc, char *argv[])
-{
- GstXML *xml;
- GstElement *bin;
- gboolean ret;
-
- gst_init (&argc, &argv);
-
- xml = gst_xml_new ();
-
- ret = gst_xml_parse_file(xml, "xmlTest.gst", NULL);
- g_assert (ret == TRUE);
-
- bin = gst_xml_get_element (xml, "bin");
- g_assert (bin != NULL);
-
- gst_element_set_state (bin, GST_STATE_PLAYING);
-
- while (gst_bin_iterate(GST_BIN(bin)));
-
- gst_element_set_state (bin, GST_STATE_NULL);
-
- exit (0);
-}
- </programlisting>
- <para>
- gst_xml_get_element (xml, "name") can be used to get a specific element
- from the XML file.
- </para>
- <para>
- gst_xml_get_topelements (xml) can be used to get a list of all toplevel elements
- in the XML file.
- </para>
- <para>
- In addition to loading a file, you can also load a from a xmlDocPtr and
- an in memory buffer using gst_xml_parse_doc and gst_xml_parse_memory
- respectively. Both of these methods return a gboolean indicating
- success or failure of the requested action.
- </para>
- </sect1>
- <sect1 id="section-xml-custom">
- <title>Adding custom XML tags into the core XML data</title>
-
- <para>
- It is possible to add custom XML tags to the core XML created with
- gst_xml_write. This feature can be used by an application to add more
- information to the save plugins. The editor will for example insert
- the position of the elements on the screen using the custom XML tags.
- </para>
- <para>
- It is strongly suggested to save and load the custom XML tags using
- a namespace. This will solve the problem of having your XML tags
- interfere with the core XML tags.
- </para>
- <para>
- To insert a hook into the element saving procedure you can link
- a signal to the GstElement using the following piece of code:
- </para>
- <programlisting>
-xmlNsPtr ns;
-
- ...
- ns = xmlNewNs (NULL, "http://gstreamer.net/gst-test/1.0/", "test");
- ...
- thread = gst_element_factory_make ("thread", "thread");
- g_signal_connect (G_OBJECT (thread), "object_saved",
- G_CALLBACK (object_saved), g_strdup ("decoder thread"));
- ...
- </programlisting>
- <para>
- When the thread is saved, the object_save method will be called. Our example
- will insert a comment tag:
- </para>
- <programlisting>
-static void
-object_saved (GstObject *object, xmlNodePtr parent, gpointer data)
-{
- xmlNodePtr child;
-
- child = xmlNewChild (parent, ns, "comment", NULL);
- xmlNewChild (child, ns, "text", (gchar *)data);
-}
- </programlisting>
- <para>
- Adding the custom tag code to the above example you will get an XML file
- with the custom tags in it. Here's an excerpt:
- </para>
- <programlisting>
- ...
- <gst:element>
- <gst:name>thread</gst:name>
- <gst:type>thread</gst:type>
- <gst:version>0.1.0</gst:version>
- ...
- </gst:children>
- <test:comment>
- <test:text>decoder thread</test:text>
- </test:comment>
- </gst:element>
- ...
- </programlisting>
- <para>
- To retrieve the custom XML again, you need to attach a signal to
- the GstXML object used to load the XML data. You can then parse your
- custom XML from the XML tree whenever an object is loaded.
- </para>
-
- <para>
- We can extend our previous example with the following piece of
- code.
- </para>
-
- <programlisting>
- xml = gst_xml_new ();
-
- g_signal_connect (G_OBJECT (xml), "object_loaded",
- G_CALLBACK (xml_loaded), xml);
-
- ret = gst_xml_parse_file (xml, "xmlTest.gst", NULL);
- g_assert (ret == TRUE);
- </programlisting>
-
- <para>
- Whenever a new object has been loaded, the xml_loaded function will
- be called. This function looks like:
- </para>
- <programlisting>
-static void
-xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data)
-{
- xmlNodePtr children = self->xmlChildrenNode;
-
- while (children) {
- if (!strcmp (children->name, "comment")) {
- xmlNodePtr nodes = children->xmlChildrenNode;
-
- while (nodes) {
- if (!strcmp (nodes->name, "text")) {
- gchar *name = g_strdup (xmlNodeGetContent (nodes));
- g_print ("object %s loaded with comment '%s'\n",
- gst_object_get_name (object), name);
- }
- nodes = nodes->next;
- }
- }
- children = children->next;
- }
-}
- </programlisting>
- <para>
- As you can see, you'll get a handle to the GstXML object, the
- newly loaded GstObject and the xmlNodePtr that was used to create
- this object. In the above example we look for our special tag inside
- the XML tree that was used to load the object and we print our
- comment to the console.
- </para>
- </sect1>
-
-</chapter>
EXTRA_DIST = extract.pl
EXAMPLES = \
- dynamic $(GNOME) elementmake elementget helloworld \
- init popt queue threads $(GST_LOADSAVE_SRC)
+ dynamic \
+ $(GNOME) \
+ elementcreate \
+ elementmake \
+ elementfactory \
+ elementget \
+ elementlink \
+ bin \
+ pad \
+ ghostpad \
+ helloworld \
+ init \
+ popt \
+ query \
+ queue \
+ threads \
+ playbin \
+ decodebin \
+ $(GST_LOADSAVE_SRC)
-dynamic.c: $(top_srcdir)/docs/manual/dynamic.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/dynamic.xml
+dynamic.c: $(top_srcdir)/docs/manual/advanced-autoplugging.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/advanced-autoplugging.xml
-elementmake.c elementget.c: $(top_srcdir)/docs/manual/elements-api.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/elements-api.xml
+elementmake.c elementcreate.c elementget.c elementlink.c elementfactory.c: $(top_srcdir)/docs/manual/basics-elements.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-elements.xml
-gnome.c: $(top_srcdir)/docs/manual/gnome.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/gnome.xml
+bin.c : $(top_srcdir)/docs/manual/basics-bins.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-bins.xml
-helloworld.c: $(top_srcdir)/docs/manual/helloworld.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/helloworld.xml
+pad.c ghostpad.c: $(top_srcdir)/docs/manual/basics-pads.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-pads.xml
-init.c popt.c: $(top_srcdir)/docs/manual/init-api.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/init-api.xml
+gnome.c: $(top_srcdir)/docs/manual/appendix-gnome.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/appendix-gnome.xml
-queue.c: $(top_srcdir)/docs/manual/queues.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/queues.xml
+helloworld.c: $(top_srcdir)/docs/manual/basics-helloworld.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-helloworld.xml
-threads.c: $(top_srcdir)/docs/manual/threads.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/threads.xml
+init.c popt.c: $(top_srcdir)/docs/manual/basics-init.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-init.xml
-xml-mp3.c: $(top_srcdir)/docs/manual/xml.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/xml.xml
+query.c: $(top_srcdir)/docs/manual/advanced-position.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/advanced-position.xml
+
+queue.c threads.c: $(top_srcdir)/docs/manual/advanced-threads.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/advanced-threads.xml
+
+playbin.c decodebin.c: $(top_srcdir)/docs/manual/highlevel-components.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/highlevel-components.xml
+
+xml-mp3.c: $(top_srcdir)/docs/manual/highlevel-xml.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/highlevel-xml.xml
# we use some of the examples as testsuite apps, to verify that
# they actually run
while ($line = <FILE>)
{
- if ($line =~ /<!-- example-begin $output (.*) -->/)
+ if ($line =~ /<!-- example-begin $output (.*?)-->/)
{
$found = 1;
$block_id = $1;
while ($line = <FILE>)
{
- if ($line =~ /<!-- example-end $output (.*) -->/)
+ if ($line =~ /<!-- example-end $output (.*?)-->/)
{
last;
}
EXTRA_DIST = extract.pl
EXAMPLES = \
- dynamic $(GNOME) elementmake elementget helloworld \
- init popt queue threads $(GST_LOADSAVE_SRC)
+ dynamic \
+ $(GNOME) \
+ elementcreate \
+ elementmake \
+ elementfactory \
+ elementget \
+ elementlink \
+ bin \
+ pad \
+ ghostpad \
+ helloworld \
+ init \
+ popt \
+ query \
+ queue \
+ threads \
+ playbin \
+ decodebin \
+ $(GST_LOADSAVE_SRC)
-dynamic.c: $(top_srcdir)/docs/manual/dynamic.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/dynamic.xml
+dynamic.c: $(top_srcdir)/docs/manual/advanced-autoplugging.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/advanced-autoplugging.xml
-elementmake.c elementget.c: $(top_srcdir)/docs/manual/elements-api.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/elements-api.xml
+elementmake.c elementcreate.c elementget.c elementlink.c elementfactory.c: $(top_srcdir)/docs/manual/basics-elements.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-elements.xml
-gnome.c: $(top_srcdir)/docs/manual/gnome.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/gnome.xml
+bin.c : $(top_srcdir)/docs/manual/basics-bins.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-bins.xml
-helloworld.c: $(top_srcdir)/docs/manual/helloworld.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/helloworld.xml
+pad.c ghostpad.c: $(top_srcdir)/docs/manual/basics-pads.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-pads.xml
-init.c popt.c: $(top_srcdir)/docs/manual/init-api.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/init-api.xml
+gnome.c: $(top_srcdir)/docs/manual/appendix-gnome.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/appendix-gnome.xml
-queue.c: $(top_srcdir)/docs/manual/queues.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/queues.xml
+helloworld.c: $(top_srcdir)/docs/manual/basics-helloworld.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-helloworld.xml
-threads.c: $(top_srcdir)/docs/manual/threads.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/threads.xml
+init.c popt.c: $(top_srcdir)/docs/manual/basics-init.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/basics-init.xml
-xml-mp3.c: $(top_srcdir)/docs/manual/xml.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ $(top_srcdir)/docs/manual/xml.xml
+query.c: $(top_srcdir)/docs/manual/advanced-position.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/advanced-position.xml
+
+queue.c threads.c: $(top_srcdir)/docs/manual/advanced-threads.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/advanced-threads.xml
+
+playbin.c decodebin.c: $(top_srcdir)/docs/manual/highlevel-components.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/highlevel-components.xml
+
+xml-mp3.c: $(top_srcdir)/docs/manual/highlevel-xml.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ \
+ $(top_srcdir)/docs/manual/highlevel-xml.xml
# we use some of the examples as testsuite apps, to verify that
# they actually run
while ($line = <FILE>)
{
- if ($line =~ /<!-- example-begin $output (.*) -->/)
+ if ($line =~ /<!-- example-begin $output (.*?)-->/)
{
$found = 1;
$block_id = $1;
while ($line = <FILE>)
{
- if ($line =~ /<!-- example-end $output (.*) -->/)
+ if ($line =~ /<!-- example-end $output (.*?)-->/)
{
last;
}