mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
put back old manual structure before integrating ronald's changes
Original commit message from CVS: put back old manual structure before integrating ronald's changes
This commit is contained in:
parent
5700e439fa
commit
e4383150e1
61 changed files with 10387 additions and 200 deletions
642
docs/manual/advanced-autoplugging.xml
Normal file
642
docs/manual/advanced-autoplugging.xml
Normal file
|
@ -0,0 +1,642 @@
|
|||
<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
|
||||
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>
|
||||
</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>
|
||||
|
||||
<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>
|
7
docs/manual/advanced-clocks.xml
Normal file
7
docs/manual/advanced-clocks.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<chapter id="chapter-clocks">
|
||||
<title>Clocks in GStreamer</title>
|
||||
|
||||
<para>
|
||||
WRITEME
|
||||
</para>
|
||||
</chapter>
|
198
docs/manual/advanced-dparams.xml
Normal file
198
docs/manual/advanced-dparams.xml
Normal file
|
@ -0,0 +1,198 @@
|
|||
<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>
|
42
docs/manual/advanced-schedulers.xml
Normal file
42
docs/manual/advanced-schedulers.xml
Normal file
|
@ -0,0 +1,42 @@
|
|||
<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>
|
296
docs/manual/advanced-threads.xml
Normal file
296
docs/manual/advanced-threads.xml
Normal file
|
@ -0,0 +1,296 @@
|
|||
<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="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>
|
||||
</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 */
|
||||
#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 */
|
||||
</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>
|
152
docs/manual/appendix-checklist.xml
Normal file
152
docs/manual/appendix-checklist.xml
Normal file
|
@ -0,0 +1,152 @@
|
|||
<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>
|
152
docs/manual/appendix-debugging.xml
Normal file
152
docs/manual/appendix-debugging.xml
Normal file
|
@ -0,0 +1,152 @@
|
|||
<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>
|
95
docs/manual/appendix-gnome.xml
Normal file
95
docs/manual/appendix-gnome.xml
Normal file
|
@ -0,0 +1,95 @@
|
|||
<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 */
|
||||
#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 */
|
||||
</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>
|
95
docs/manual/appendix-integration.xml
Normal file
95
docs/manual/appendix-integration.xml
Normal file
|
@ -0,0 +1,95 @@
|
|||
<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 */
|
||||
#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 */
|
||||
</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>
|
251
docs/manual/appendix-programs.xml
Normal file
251
docs/manual/appendix-programs.xml
Normal file
|
@ -0,0 +1,251 @@
|
|||
<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 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>
|
||||
|
||||
</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>
|
||||
</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>
|
||||
</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>
|
241
docs/manual/appendix-quotes.xml
Normal file
241
docs/manual/appendix-quotes.xml
Normal file
|
@ -0,0 +1,241 @@
|
|||
<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>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>
|
85
docs/manual/appendix-win32.xml
Normal file
85
docs/manual/appendix-win32.xml
Normal file
|
@ -0,0 +1,85 @@
|
|||
<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>
|
198
docs/manual/autoplugging.xml
Normal file
198
docs/manual/autoplugging.xml
Normal file
|
@ -0,0 +1,198 @@
|
|||
<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>
|
147
docs/manual/basics-bins.xml
Normal file
147
docs/manual/basics-bins.xml
Normal file
|
@ -0,0 +1,147 @@
|
|||
<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, 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>
|
||||
|
||||
<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>
|
||||
|
||||
<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
|
||||
containing elements. The toplevel bin has to be a pipeline.
|
||||
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.
|
||||
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>
|
||||
</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>
|
||||
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);
|
||||
|
||||
[..]
|
||||
}
|
||||
</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="../../GStreamer/html/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>
|
99
docs/manual/basics-data.xml
Normal file
99
docs/manual/basics-data.xml
Normal file
|
@ -0,0 +1,99 @@
|
|||
<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>
|
||||
|
||||
<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.
|
||||
</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>
|
||||
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>
|
||||
|
||||
<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>
|
511
docs/manual/basics-elements.xml
Normal file
511
docs/manual/basics-elements.xml
Normal file
|
@ -0,0 +1,511 @@
|
|||
<chapter id="chapter-elements" xreflabel="Elements">
|
||||
<title>Elements</title>
|
||||
<para>
|
||||
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" xreflabel="What are elements?">
|
||||
<title>What are elements?</title>
|
||||
<para>
|
||||
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>
|
||||
|
||||
<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. <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 (on the
|
||||
right). A source pad can only generate data.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="section-elements-filter">
|
||||
<title>Filters, convertors, demuxers, muxers and codecs</title>
|
||||
<para>
|
||||
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>
|
||||
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;"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
<para>
|
||||
<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
|
||||
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 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>
|
||||
|
||||
<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>
|
||||
|
||||
<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><![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;
|
||||
}
|
||||
]]></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><![CDATA[
|
||||
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");
|
||||
|
||||
gst_object_unref (GST_OBJECT (element));
|
||||
|
||||
return 0;
|
||||
}
|
||||
]]></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><![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;
|
||||
}
|
||||
]]></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><![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;
|
||||
}
|
||||
]]></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>
|
||||
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);
|
||||
|
||||
[..]
|
||||
}
|
||||
</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>
|
197
docs/manual/basics-helloworld.xml
Normal file
197
docs/manual/basics-helloworld.xml
Normal file
|
@ -0,0 +1,197 @@
|
|||
<chapter id="chapter-helloworld">
|
||||
<title>Your first application</title>
|
||||
<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-helloworld">
|
||||
<title>Hello world</title>
|
||||
<para>
|
||||
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>
|
||||
#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;
|
||||
|
||||
static void
|
||||
new_pad (GstElement *element,
|
||||
GstPad *pad,
|
||||
gpointer data)
|
||||
{
|
||||
/* 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));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
/* initialize GStreamer */
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
/* check input arguments */
|
||||
if (argc != 2) {
|
||||
g_print ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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 (filesrc), "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);
|
||||
|
||||
/* 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))) ;
|
||||
|
||||
/* clean up nicely */
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
<!-- FIXME: this image needs updating -->
|
||||
<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>
|
||||
</sect1>
|
||||
|
||||
<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 this example application with <command>./helloworld
|
||||
file.ogg</command>. Substitute <filename>file.ogg</filename>
|
||||
with your favourite Ogg/Vorbis file.
|
||||
</para>
|
||||
</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 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>
|
97
docs/manual/basics-init.xml
Normal file
97
docs/manual/basics-init.xml
Normal file
|
@ -0,0 +1,97 @@
|
|||
<chapter id="chapter-init">
|
||||
<title>Initializing &GStreamer;</title>
|
||||
<para>
|
||||
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>
|
||||
|
||||
<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>
|
||||
#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;
|
||||
}
|
||||
</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:
|
||||
</para>
|
||||
<programlisting>
|
||||
#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;
|
||||
}
|
||||
</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>
|
534
docs/manual/basics-pads.xml
Normal file
534
docs/manual/basics-pads.xml
Normal file
|
@ -0,0 +1,534 @@
|
|||
<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. 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>
|
||||
|
||||
<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>
|
||||
|
||||
<sect2 id="section-pads-dynamic">
|
||||
<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 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 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>
|
||||
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 */
|
||||
[..]
|
||||
}
|
||||
|
||||
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)));
|
||||
|
||||
[..]
|
||||
}
|
||||
</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. 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 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>
|
||||
<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 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>
|
||||
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-caps-structure">
|
||||
<title>Dissecting capabilities</title>
|
||||
<para>
|
||||
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>
|
||||
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>
|
||||
Pad Templates:
|
||||
SRC template: 'src'
|
||||
Availability: Always
|
||||
Capabilities:
|
||||
audio/x-raw-float
|
||||
rate: [ 8000, 50000 ]
|
||||
channels: [ 1, 2 ]
|
||||
endianness: 1234
|
||||
width: 32
|
||||
buffer-frames: 0
|
||||
|
||||
SINK template: 'sink'
|
||||
Availability: Always
|
||||
Capabilities:
|
||||
audio/x-vorbis
|
||||
</programlisting>
|
||||
</sect2>
|
||||
|
||||
<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, 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 (<classname>G_TYPE_INT</classname>):
|
||||
the property has this exact value.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A boolean value (<classname>G_TYPE_BOOLEAN</classname>):
|
||||
the property is either TRUE or FALSE.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A float value (<classname>G_TYPE_FLOAT</classname>):
|
||||
the property has this exact floating point value.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A string value (<classname>G_TYPE_STRING</classname>):
|
||||
the property contains a UTF-8 string.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
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
|
||||
(<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
|
||||
(<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 (<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-caps-filter">
|
||||
<title>Creating capabilities for filtering</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 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>
|
||||
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");
|
||||
|
||||
[..]
|
||||
}
|
||||
</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>
|
84
docs/manual/basics-plugins.xml
Normal file
84
docs/manual/basics-plugins.xml
Normal file
|
@ -0,0 +1,84 @@
|
|||
<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>
|
||||
|
||||
<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>
|
205
docs/manual/bins-api.xml
Normal file
205
docs/manual/bins-api.xml
Normal file
|
@ -0,0 +1,205 @@
|
|||
<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>
|
49
docs/manual/bins.xml
Normal file
49
docs/manual/bins.xml
Normal file
|
@ -0,0 +1,49 @@
|
|||
<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>
|
6
docs/manual/buffers-api.xml
Normal file
6
docs/manual/buffers-api.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<chapter id="chapter-buffers-api">
|
||||
<title>Buffers</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
</chapter>
|
66
docs/manual/buffers.xml
Normal file
66
docs/manual/buffers.xml
Normal file
|
@ -0,0 +1,66 @@
|
|||
<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>
|
5
docs/manual/clocks.xml
Normal file
5
docs/manual/clocks.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<chapter id="chapter-clocks">
|
||||
<title>Clocks in GStreamer</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
37
docs/manual/components.xml
Normal file
37
docs/manual/components.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<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>
|
130
docs/manual/cothreads.xml
Normal file
130
docs/manual/cothreads.xml
Normal file
|
@ -0,0 +1,130 @@
|
|||
<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>
|
152
docs/manual/debugging.xml
Normal file
152
docs/manual/debugging.xml
Normal file
|
@ -0,0 +1,152 @@
|
|||
<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>
|
198
docs/manual/dparams-app.xml
Normal file
198
docs/manual/dparams-app.xml
Normal file
|
@ -0,0 +1,198 @@
|
|||
<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>
|
191
docs/manual/dynamic.xml
Normal file
191
docs/manual/dynamic.xml
Normal file
|
@ -0,0 +1,191 @@
|
|||
<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 */
|
||||
#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>
|
||||
</chapter>
|
202
docs/manual/elements-api.xml
Normal file
202
docs/manual/elements-api.xml
Normal file
|
@ -0,0 +1,202 @@
|
|||
<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>
|
||||
<![CDATA[
|
||||
/* example-begin elementmake.c */
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *element;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
element = gst_element_factory_make ("fakesrc", "source");
|
||||
|
||||
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 */
|
||||
]]>
|
||||
</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.
|
||||
</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>
|
||||
<![CDATA[
|
||||
/* example-begin elementget.c */
|
||||
|
||||
#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 */
|
||||
]]>
|
||||
</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>
|
122
docs/manual/elements.xml
Normal file
122
docs/manual/elements.xml
Normal file
|
@ -0,0 +1,122 @@
|
|||
<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>
|
257
docs/manual/factories.xml
Normal file
257
docs/manual/factories.xml
Normal file
|
@ -0,0 +1,257 @@
|
|||
<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>
|
95
docs/manual/gnome.xml
Normal file
95
docs/manual/gnome.xml
Normal file
|
@ -0,0 +1,95 @@
|
|||
<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 */
|
||||
#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 */
|
||||
</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>
|
167
docs/manual/goals.xml
Normal file
167
docs/manual/goals.xml
Normal file
|
@ -0,0 +1,167 @@
|
|||
<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>
|
280
docs/manual/helloworld.xml
Normal file
280
docs/manual/helloworld.xml
Normal file
|
@ -0,0 +1,280 @@
|
|||
<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 */
|
||||
#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 */
|
||||
</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>
|
274
docs/manual/helloworld2.xml
Normal file
274
docs/manual/helloworld2.xml
Normal file
|
@ -0,0 +1,274 @@
|
|||
<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 */
|
||||
#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 */
|
||||
</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>
|
282
docs/manual/highlevel-components.xml
Normal file
282
docs/manual/highlevel-components.xml
Normal file
|
@ -0,0 +1,282 @@
|
|||
<chapter id="chapter-components">
|
||||
<title>Components</title>
|
||||
|
||||
<para>
|
||||
&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>
|
||||
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-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>
|
||||
#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;
|
||||
}
|
||||
</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>
|
||||
#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 (!strstr (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 (filesrc), "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);
|
||||
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;
|
||||
}
|
||||
</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-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-editor">
|
||||
<title>GstEditor</title>
|
||||
<para>
|
||||
GstEditor is a set of widgets to display a graphical representation of a
|
||||
pipeline.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
283
docs/manual/highlevel-xml.xml
Normal file
283
docs/manual/highlevel-xml.xml
Normal file
|
@ -0,0 +1,283 @@
|
|||
<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 */
|
||||
#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 */
|
||||
</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>
|
99
docs/manual/init-api.xml
Normal file
99
docs/manual/init-api.xml
Normal file
|
@ -0,0 +1,99 @@
|
|||
<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>
|
||||
<![CDATA[
|
||||
/* example-begin init.c */
|
||||
|
||||
#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 */
|
||||
]]>
|
||||
</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 */
|
||||
|
||||
#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 */
|
||||
</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>
|
302
docs/manual/intro-motivation.xml
Normal file
302
docs/manual/intro-motivation.xml
Normal file
|
@ -0,0 +1,302 @@
|
|||
<chapter id="chapter-motivation">
|
||||
<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.
|
||||
</para>
|
||||
<para>
|
||||
GStreamer was designed to provide a solution to the current Linux media
|
||||
problems.
|
||||
</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 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.
|
||||
</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-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>
|
||||
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>
|
||||
|
||||
<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>
|
117
docs/manual/intro-preface.xml
Normal file
117
docs/manual/intro-preface.xml
Normal file
|
@ -0,0 +1,117 @@
|
|||
<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, 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
|
||||
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>
|
||||
</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 <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>
|
59
docs/manual/intro.xml
Normal file
59
docs/manual/intro.xml
Normal file
|
@ -0,0 +1,59 @@
|
|||
<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>
|
83
docs/manual/links-api.xml
Normal file
83
docs/manual/links-api.xml
Normal file
|
@ -0,0 +1,83 @@
|
|||
<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>
|
29
docs/manual/links.xml
Normal file
29
docs/manual/links.xml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<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>
|
|
@ -10,49 +10,62 @@
|
|||
|
||||
<!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-preface.xml">
|
||||
<!ENTITY MOTIVATION SYSTEM "intro-motivation.xml">
|
||||
<!ENTITY INTRO SYSTEM "intro.xml">
|
||||
<!ENTITY MOTIVATION SYSTEM "motivation.xml">
|
||||
<!ENTITY GOALS SYSTEM "goals.xml">
|
||||
|
||||
<!-- Part 2: Basic Concepts -->
|
||||
<!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">
|
||||
<!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: 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 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: Higher-level interfaces -->
|
||||
<!ENTITY XML SYSTEM "highlevel-xml.xml">
|
||||
<!ENTITY COMPONENTS SYSTEM "highlevel-components.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">
|
||||
|
||||
<!-- 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">
|
||||
<!-- 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 GStreamer "<application>GStreamer</application>">
|
||||
<!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">
|
||||
]>
|
||||
|
||||
<book id="index">
|
||||
|
@ -86,16 +99,6 @@
|
|||
</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">
|
||||
|
@ -104,218 +107,218 @@
|
|||
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>&GStreamer; Application Development Manual (&GST_VERSION;)</title>
|
||||
<title><application>GStreamer</application> Application Development Manual (&GST_VERSION;)</title>
|
||||
|
||||
</bookinfo>
|
||||
|
||||
<!-- ############# Introduction & Overview - part ############### -->
|
||||
<!-- ############# Overview - part ############### -->
|
||||
|
||||
<part id="part-overview">
|
||||
<title>Overview</title>
|
||||
<part id="part-overview"><title>Overview</title>
|
||||
<partintro>
|
||||
<para>
|
||||
&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.).
|
||||
<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>.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&INTRO;
|
||||
&MOTIVATION;
|
||||
<!-- ############ Introduction - chapter ############# -->
|
||||
&INTRO;
|
||||
|
||||
&MOTIVATION;
|
||||
|
||||
&GOALS;
|
||||
</part>
|
||||
|
||||
<!-- ############ Basic concepts - part ############# -->
|
||||
|
||||
<part id="part-basics">
|
||||
<part id="part-basic-concepts">
|
||||
<title>Basic Concepts</title>
|
||||
<partintro>
|
||||
<para>
|
||||
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>
|
||||
We will first describe the basics of
|
||||
<application>GStreamer</application> programming by introducing the
|
||||
different objects needed to create a media pipeline.
|
||||
</para>
|
||||
<para>
|
||||
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>
|
||||
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>
|
||||
|
||||
&INIT;
|
||||
&ELEMENTS;
|
||||
&BINS;
|
||||
&PADS;
|
||||
&DATA;
|
||||
&HELLOWORLD;
|
||||
&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.
|
||||
</para>
|
||||
<para>
|
||||
We assume the reader is familiar with GTK+/GNOME programming.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&HELLOWORLD;
|
||||
|
||||
&FACTORIES;
|
||||
|
||||
</part>
|
||||
|
||||
<!-- ############ Advanced GStreamer - part ############# -->
|
||||
|
||||
<part id="part-advanced">
|
||||
<title>Advanced &GStreamer; concepts</title>
|
||||
<part id="part-advanced"><title>Advanced <application>GStreamer</application> concepts</title>
|
||||
|
||||
<partintro>
|
||||
<para>
|
||||
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.
|
||||
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>.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
&THREADS;
|
||||
|
||||
&QUERYEVENTS;
|
||||
&METADATA;
|
||||
&INTERFACES;
|
||||
&CLOCKS;
|
||||
&DPARAMS;
|
||||
&THREADS;
|
||||
&SCHEDULERS;
|
||||
&AUTOPLUGGING;
|
||||
&DATAACCESS;
|
||||
&QUEUES;
|
||||
|
||||
&COTHREADS;
|
||||
|
||||
&SCHEDULERS;
|
||||
|
||||
&CLOCKS;
|
||||
|
||||
&DYNAMIC;
|
||||
|
||||
&TYPEDETECTION;
|
||||
|
||||
&AUTOPLUGGING;
|
||||
|
||||
&HELLOWORLD2;
|
||||
|
||||
&DPARAMS;
|
||||
</part>
|
||||
|
||||
<!-- ############ Higher-level APIs in GStreamer - part ############# -->
|
||||
<!-- ############ XML in GStreamer - part ############# -->
|
||||
|
||||
<part id="part-xml-gstreamer"><title>XML in <application>GStreamer</application></title>
|
||||
|
||||
<part id="part-highlevel">
|
||||
<title>Higher-level interfaces for &GStreamer; applications</title>
|
||||
<partintro>
|
||||
<para>
|
||||
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.
|
||||
<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.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&COMPONENTS;
|
||||
&XML;
|
||||
|
||||
&XML;
|
||||
</part>
|
||||
|
||||
|
||||
<!-- ############ Appendices - part ############# -->
|
||||
|
||||
<part id="part-appendices">
|
||||
<title>Appendices</title>
|
||||
|
||||
<partintro>
|
||||
<para>
|
||||
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.
|
||||
<application>GStreamer</application> comes prepackaged with a few
|
||||
programs, and some useful debugging options.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
<!--
|
||||
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;
|
||||
|
||||
&DEBUGGING;
|
||||
&PROGRAMS;
|
||||
&GNOME;
|
||||
&WIN32;
|
||||
"ES;
|
||||
&PROGRAMS;
|
||||
|
||||
&COMPONENTS;
|
||||
|
||||
&GNOME;
|
||||
|
||||
&WIN32;
|
||||
|
||||
"ES;
|
||||
|
||||
</part>
|
||||
</book>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
111
docs/manual/motivation.xml
Normal file
111
docs/manual/motivation.xml
Normal file
|
@ -0,0 +1,111 @@
|
|||
<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>
|
302
docs/manual/pads-api.xml
Normal file
302
docs/manual/pads-api.xml
Normal file
|
@ -0,0 +1,302 @@
|
|||
<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>
|
244
docs/manual/pads.xml
Normal file
244
docs/manual/pads.xml
Normal file
|
@ -0,0 +1,244 @@
|
|||
<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>
|
56
docs/manual/plugins-api.xml
Normal file
56
docs/manual/plugins-api.xml
Normal file
|
@ -0,0 +1,56 @@
|
|||
<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>
|
31
docs/manual/plugins.xml
Normal file
31
docs/manual/plugins.xml
Normal file
|
@ -0,0 +1,31 @@
|
|||
<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>
|
333
docs/manual/programs.xml
Normal file
333
docs/manual/programs.xml
Normal file
|
@ -0,0 +1,333 @@
|
|||
<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>
|
129
docs/manual/queues.xml
Normal file
129
docs/manual/queues.xml
Normal file
|
@ -0,0 +1,129 @@
|
|||
<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 */
|
||||
#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>
|
||||
|
||||
|
||||
|
||||
</chapter>
|
253
docs/manual/quotes.xml
Normal file
253
docs/manual/quotes.xml
Normal file
|
@ -0,0 +1,253 @@
|
|||
<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>
|
42
docs/manual/schedulers.xml
Normal file
42
docs/manual/schedulers.xml
Normal file
|
@ -0,0 +1,42 @@
|
|||
<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>
|
48
docs/manual/states-api.xml
Normal file
48
docs/manual/states-api.xml
Normal file
|
@ -0,0 +1,48 @@
|
|||
<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>
|
141
docs/manual/states.xml
Normal file
141
docs/manual/states.xml
Normal file
|
@ -0,0 +1,141 @@
|
|||
<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>
|
168
docs/manual/threads.xml
Normal file
168
docs/manual/threads.xml
Normal file
|
@ -0,0 +1,168 @@
|
|||
<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 */
|
||||
#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 */
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
145
docs/manual/typedetection.xml
Normal file
145
docs/manual/typedetection.xml
Normal file
|
@ -0,0 +1,145 @@
|
|||
<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>
|
85
docs/manual/win32.xml
Normal file
85
docs/manual/win32.xml
Normal file
|
@ -0,0 +1,85 @@
|
|||
<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>
|
283
docs/manual/xml.xml
Normal file
283
docs/manual/xml.xml
Normal file
|
@ -0,0 +1,283 @@
|
|||
<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 */
|
||||
#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 */
|
||||
</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>
|
Loading…
Reference in a new issue