mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
conversion to docbook-xml. i don't have to ask that this be testing, because not ionly is it perfect, but i'm sure yo...
Original commit message from CVS: conversion to docbook-xml. i don't have to ask that this be testing, because not ionly is it perfect, but i'm sure you folks will learn that on your own :-)
This commit is contained in:
parent
fb32f9a4ac
commit
d2c3b2087d
69 changed files with 3142 additions and 230 deletions
|
@ -1,21 +1,25 @@
|
|||
manualname = gst-plugin-writers-guide
|
||||
htmlname = index.html
|
||||
DOC=gst-plugin-writers-guide
|
||||
MAIN=$(DOC).xml
|
||||
XML=$(shell echo *.xml)
|
||||
XSLFO=$(srcdir)/../xsl/fo.xsl
|
||||
XSLFOMODS=$(srcdir)/../xsl/ulink.xsl $(srcdir)/../xsl/keycombo.xsl
|
||||
XSLHTML=$(srcdir)/../xsl/html.xsl
|
||||
XSLHTMLMODS=$(srcdir)/../xsl/fileext.xsl $(srcdir)/../xsl/admon.xsl \
|
||||
$(srcdir)/../xsl/keycombo.xsl $(srcdir)/../xsl/css.xsl
|
||||
XSLS=$(XSLFO) $(XSLFOMODS) $(XSLHTML) $(XSLHTMLMODS)
|
||||
FIGS= # $(shell echo *.fig) (uncomment when pngs are added)
|
||||
PNGS=$(FIGS:.fig=.png)
|
||||
PDFS=$(FIGS:.fig=.pdf)
|
||||
SRC=$(XML)
|
||||
CSS=base.css
|
||||
|
||||
sgml_files = gst-plugin-writers-guide.sgml \
|
||||
titlepage.sgml \
|
||||
intro.sgml \
|
||||
testapp.sgml \
|
||||
loopbased.sgml \
|
||||
buffers.sgml \
|
||||
srcnsink.sgml \
|
||||
statemanage.sgml \
|
||||
checklist.sgml
|
||||
STYLESHEET_IMAGES=/usr/share/doc/docbook-xsl/images
|
||||
|
||||
fig_files =
|
||||
eps_files =
|
||||
png_files =
|
||||
EXTRA_DIST = $(XML) $(FIGS)
|
||||
|
||||
EXTRA_DIST = $(sgml_files) $(fig_files)
|
||||
## FIXME if we don't do this they don't get cleaned up in make distcheck
|
||||
## but maybe this is not the best way to do it
|
||||
CONFIG_CLEAN_FILES = $(XML) $(FIGS)
|
||||
|
||||
include $(srcdir)/../manuals.mak
|
||||
|
||||
|
|
0
docs/fwg/base.css
Normal file
0
docs/fwg/base.css
Normal file
|
@ -1,20 +1,17 @@
|
|||
<!DOCTYPE book PUBLIC "-//GNOME//DTD DocBook PNG Variant V1.0//EN" "" [
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
|
||||
<!ENTITY % magic-entities SYSTEM "magic">
|
||||
%magic-entities;
|
||||
|
||||
<!ENTITY TITLEPAGE SYSTEM "titlepage.sgml">
|
||||
|
||||
<!ENTITY INTRO SYSTEM "intro.sgml">
|
||||
|
||||
<!ENTITY TESTAPP SYSTEM "testapp.sgml">
|
||||
|
||||
<!ENTITY LOOPBASED SYSTEM "loopbased.sgml">
|
||||
|
||||
<!ENTITY BUFFERS SYSTEM "buffers.sgml">
|
||||
|
||||
<!ENTITY SRCNSINK SYSTEM "srcnsink.sgml">
|
||||
|
||||
<!ENTITY STATEMANAGE SYSTEM "statemanage.sgml">
|
||||
|
||||
<!ENTITY CHECKLIST SYSTEM "checklist.sgml">
|
||||
|
||||
<!ENTITY GStreamer "<application>GStreamer</application>">
|
||||
]>
|
||||
|
1
docs/fwg/magic-pdf
Normal file
1
docs/fwg/magic-pdf
Normal file
|
@ -0,0 +1 @@
|
|||
<!ENTITY magic "pdf">
|
1
docs/fwg/magic-png
Normal file
1
docs/fwg/magic-png
Normal file
|
@ -0,0 +1 @@
|
|||
<!ENTITY magic "png">
|
|
@ -1,80 +1,24 @@
|
|||
manualname = gstreamer-manual
|
||||
htmlname = index.html
|
||||
DOC=gstreamer-manual
|
||||
MAIN=$(DOC).xml
|
||||
XML=$(shell echo *.xml)
|
||||
XSLFO=$(srcdir)/../xsl/fo.xsl
|
||||
XSLFOMODS=$(srcdir)/../xsl/ulink.xsl $(srcdir)/../xsl/keycombo.xsl
|
||||
XSLHTML=$(srcdir)/../xsl/html.xsl
|
||||
XSLHTMLMODS=$(srcdir)/../xsl/fileext.xsl $(srcdir)/../xsl/admon.xsl \
|
||||
$(srcdir)/../xsl/keycombo.xsl $(srcdir)/../xsl/css.xsl
|
||||
XSLS=$(XSLFO) $(XSLFOMODS) $(XSLHTML) $(XSLHTMLMODS)
|
||||
FIGS=$(shell echo *.fig)
|
||||
PNGS=$(FIGS:.fig=.png)
|
||||
PDFS=$(FIGS:.fig=.pdf)
|
||||
SRC=$(XML)
|
||||
CSS=base.css
|
||||
|
||||
sgml_files = gstreamer-manual.sgml \
|
||||
advanced.sgml \
|
||||
autoplugging.sgml \
|
||||
bins.sgml \
|
||||
buffers.sgml \
|
||||
components.sgml \
|
||||
quotes.sgml \
|
||||
pads.sgml \
|
||||
connections.sgml \
|
||||
cothreads.sgml \
|
||||
dynamic.sgml \
|
||||
elements.sgml \
|
||||
factories.sgml \
|
||||
goals.sgml \
|
||||
helloworld.sgml \
|
||||
helloworld2.sgml \
|
||||
init.sgml \
|
||||
intro.sgml \
|
||||
motivation.sgml \
|
||||
plugins.sgml \
|
||||
programs.sgml \
|
||||
debugging.sgml \
|
||||
queues.sgml \
|
||||
states.sgml \
|
||||
threads.sgml \
|
||||
typedetection.sgml \
|
||||
utility.sgml \
|
||||
xml.sgml
|
||||
STYLESHEET_IMAGES=/usr/share/doc/docbook-xsl/images
|
||||
|
||||
fig_files = bin-element.fig \
|
||||
bin-element-ghost.fig \
|
||||
connected-elements.fig \
|
||||
filter-element-multi.fig \
|
||||
filter-element.fig \
|
||||
hello-world.fig \
|
||||
mime-world.fig \
|
||||
queue.fig \
|
||||
sink-element.fig \
|
||||
src-element.fig \
|
||||
state-diagram.fig \
|
||||
thread.fig
|
||||
|
||||
eps_files = images/bin-element.eps \
|
||||
images/bin-element-ghost.eps \
|
||||
images/connected-elements.eps \
|
||||
images/filter-element-multi.eps \
|
||||
images/filter-element.eps \
|
||||
images/hello-world.eps \
|
||||
images/mime-world.eps \
|
||||
images/queue.eps \
|
||||
images/sink-element.eps \
|
||||
images/src-element.eps \
|
||||
images/state-diagram.eps \
|
||||
images/thread.eps
|
||||
|
||||
png_files = images/bin-element.png \
|
||||
images/bin-element-ghost.png \
|
||||
images/connected-elements.png \
|
||||
images/filter-element-multi.png \
|
||||
images/filter-element.png \
|
||||
images/hello-world.png \
|
||||
images/mime-world.png \
|
||||
images/queue.png \
|
||||
images/sink-element.png \
|
||||
images/src-element.png \
|
||||
images/state-diagram.png \
|
||||
images/thread.png
|
||||
|
||||
EXTRA_DIST = $(sgml_files) $(fig_files)
|
||||
EXTRA_DIST = $(XML) $(FIGS)
|
||||
|
||||
## FIXME if we don't do this they don't get cleaned up in make distcheck
|
||||
## but maybe this is not the best way to do it
|
||||
CONFIG_CLEAN_FILES = $(sgml_files) $(fig_files)
|
||||
CONFIG_CLEAN_FILES = $(XML) $(FIGS)
|
||||
|
||||
include $(srcdir)/../manuals.mak
|
||||
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
<title>The Hello world pipeline with MIME types</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/mime-world" format="PNG">
|
||||
<imagedata fileref="images/mime-world.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
<title>a thread</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/thread" format="PNG">
|
||||
<imagedata fileref="images/thread.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
98
docs/manual/appendix-debugging.xml
Normal file
98
docs/manual/appendix-debugging.xml
Normal file
|
@ -0,0 +1,98 @@
|
|||
<chapter id="cha-debugging">
|
||||
<title>Debugging</title>
|
||||
<para>
|
||||
GStreamer has an extensive set of debugging tools for
|
||||
plugin developers.
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title>Command line options</title>
|
||||
<para>
|
||||
Applications using the GStreamer libraries accept the following set
|
||||
of command line argruments to enable the debugging system.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-debug-mask=<replaceable>mask</replaceable></option>
|
||||
Sets the mask for the debugging output.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-info-mask=<replaceable>mask</replaceable></option>
|
||||
Sets the mask for the info output.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-mask=<replaceable>mask</replaceable></option>
|
||||
Sets the mask for the info *and* the debug output.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-plugin-spew</option>
|
||||
Enable printout of errors while loading GST plugins.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-plugin-path=<replaceable>PATH</replaceable></option>
|
||||
Add a directory to the plugin search path.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--help</option> Print the a short desciption of the
|
||||
options and an overview of the current debugging/info masks
|
||||
set.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
The follwing table gives an overview of the mask values and
|
||||
their meaning. (enabled) means that the corresponding flag
|
||||
has been set.
|
||||
</para>
|
||||
<programlisting>
|
||||
Mask (to be OR'ed) info/debug FLAGS
|
||||
--------------------------------------------------------
|
||||
0x00000001 (enabled)/ GST_INIT
|
||||
0x00000002 / COTHREADS
|
||||
0x00000004 / COTHREAD_SWITCH
|
||||
0x00000008 / AUTOPLUG
|
||||
0x00000010 / AUTOPLUG_ATTEMPT
|
||||
0x00000020 / PARENTAGE
|
||||
0x00000040 / STATES
|
||||
0x00000080 / PLANING
|
||||
0x00000100 / SCHEDULING
|
||||
0x00000200 / OPERATION
|
||||
0x00000400 / BUFFER
|
||||
0x00000800 / CAPS
|
||||
0x00001000 / CLOCK
|
||||
0x00002000 / ELEMENT_PADS
|
||||
0x00004000 / ELEMENTFACTORY
|
||||
0x00008000 / PADS
|
||||
0x00010000 / PIPELINE
|
||||
0x00020000 / PLUGIN_LOADING
|
||||
0x00040000 / PLUGIN_ERRORS
|
||||
0x00080000 / PLUGIN_INFO
|
||||
0x00100000 / PROPERTIES
|
||||
0x00200000 / THREAD
|
||||
0x00400000 / TYPES
|
||||
0x00800000 / XML
|
||||
0x01000000 / NEGOTIATION
|
||||
0x02000000 / REFCOUNTING
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1>
|
||||
<title>Adding a custom debug handler</title>
|
||||
<para>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
0
docs/manual/base.css
Normal file
0
docs/manual/base.css
Normal file
|
@ -20,7 +20,7 @@
|
|||
<title>Visualisation of a <classname>GstBin</classname> element with some elements in it</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/bin-element" format="PNG">
|
||||
<imagedata fileref="images/bin-element.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
|
@ -176,7 +176,7 @@
|
|||
<title>Visualisation of a <classname>GstBin</classname> element with a ghostpad</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/bin-element-ghost" format="PNG">
|
||||
<imagedata fileref="images/bin-element-ghost.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
|
@ -36,7 +36,7 @@
|
|||
<title>Visualisation of a source element</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/src-element" format="PNG">
|
||||
<imagedata fileref="images/src-element.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
|
@ -65,7 +65,7 @@
|
|||
<title>Visualisation of a filter element</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/filter-element" format="PNG">
|
||||
<imagedata fileref="images/filter-element.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
|
@ -79,7 +79,7 @@
|
|||
more than one output pad</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/filter-element-multi" format="PNG">
|
||||
<imagedata fileref="images/filter-element-multi.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
|
@ -103,7 +103,7 @@
|
|||
<title>Visualisation of a sink element</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/sink-element" format="PNG">
|
||||
<imagedata fileref="images/sink-element.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
|
@ -203,7 +203,7 @@ main (int argc, char *argv[])
|
|||
<title>The Hello world pipeline</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/hello-world" format="PNG">
|
||||
<imagedata fileref="images/hello-world.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
218
docs/manual/bins.xml
Normal file
218
docs/manual/bins.xml
Normal file
|
@ -0,0 +1,218 @@
|
|||
<chapter id="cha-bins">
|
||||
<title>Bins</title>
|
||||
<para>
|
||||
A Bin is a container element. You can add elements to a bin. Since a bin is
|
||||
an <classname>GstElement</classname> itself, it can also be added to another bin.
|
||||
</para>
|
||||
<para>
|
||||
Bins allow you to combine connected 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 powerfull 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="sec-bin-img">
|
||||
<title>Visualisation of a <classname>GstBin</classname> element with some elements in it</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/bin-element.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
|
||||
<para>
|
||||
There are two standard bins available to the GStreamer programmer:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
A pipeline (<classname>GstPipeline</classname>). Which is a generic container you will
|
||||
use most of the time. The toplevel bin has to be a pipeline.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A thread (<classname>GstThread</classname>). All the elements in the thread bin will
|
||||
run in a separate thread. You will have to use this bin if you carfully have to
|
||||
synchronize audio and video for example. You will learn more about threads in.. <!-- FIXME -->
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<sect1 id="sec-bin-create">
|
||||
<title>Creating a bin</title>
|
||||
<para>
|
||||
You create a bin with a specified name 'mybin' with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElement *bin;
|
||||
|
||||
gst_bin_new ("mybin");
|
||||
...
|
||||
</programlisting>
|
||||
<para>
|
||||
A thread can be created with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElement *thread;
|
||||
|
||||
gst_thread_new ("mythread");
|
||||
...
|
||||
</programlisting>
|
||||
<para>
|
||||
Pipelines are created with gst_pipeline_new ("name");
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sec-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_elementfactory_make ("mpg123", "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.
|
||||
</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 an bin by using the elements 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_element_get_name (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>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sec-bin-custom">
|
||||
<title>Custom bins</title>
|
||||
<para>
|
||||
The application programmer can create custom bins packed with elements to perform a
|
||||
specific task. This allow you to write an MPEG audio decoder with just the follwing lines
|
||||
of code:
|
||||
|
||||
<programlisting>
|
||||
|
||||
// create the mp3player element
|
||||
GstElement *mp3player = gst_elementfactory_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>
|
||||
|
||||
Custom bins can be created with a plugin or an XML description. You will find more
|
||||
information about creating custom bin in the Filter-Writers-Guide.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sec-bin-ghostpads">
|
||||
<title>Ghostpads</title>
|
||||
<para>
|
||||
You can see from figure ... how a bin has no pads of its own. This is where Ghostpads
|
||||
come into play.
|
||||
</para>
|
||||
<para>
|
||||
A ghostpad 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="sec-bin-ghost-img">
|
||||
<title>Visualisation of a <classname>GstBin</classname> element with a ghostpad</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/bin-element-ghost.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
<para>
|
||||
Above is a representation of a ghostpad. the sinkpad of element one is now also a pad
|
||||
of the bin.
|
||||
</para>
|
||||
<para>
|
||||
Ghostpads can actually be added to all <classname>GstElement</classname>s and not just
|
||||
<classname>GstBin</classname>s. Use the following code example to add a ghostpad to a bin:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElement *bin;
|
||||
GstElement *element;
|
||||
|
||||
element = gst_elementfactory_create ("mpg123", "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. We can now, for example, connect the srcpad of a disksrc to the
|
||||
bin with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElement *disksrc;
|
||||
|
||||
disksrc = gst_elementfactory_create ("disksrc", "disk_reader");
|
||||
|
||||
gst_element_connect (disksrc, "src", bin, "sink");
|
||||
...
|
||||
</programlisting>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
59
docs/manual/buffers.xml
Normal file
59
docs/manual/buffers.xml
Normal file
|
@ -0,0 +1,59 @@
|
|||
<chapter id="cha-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 the 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>
|
||||
The most important information in the buffer is:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
A pointer to a piece of memory.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The size of the memory.
|
||||
</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 is having a reference to it.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
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 filter. That filter 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 carefull when
|
||||
the buffer is used in more than one element; a copy on write has to made in this
|
||||
situation.
|
||||
</para>
|
||||
|
||||
</chapter>
|
|
@ -9,7 +9,7 @@
|
|||
<title>Visualisation of three connected elements</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/connected-elements" format="PNG">
|
||||
<imagedata fileref="images/connected-elements.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
98
docs/manual/debugging.xml
Normal file
98
docs/manual/debugging.xml
Normal file
|
@ -0,0 +1,98 @@
|
|||
<chapter id="cha-debugging">
|
||||
<title>Debugging</title>
|
||||
<para>
|
||||
GStreamer has an extensive set of debugging tools for
|
||||
plugin developers.
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title>Command line options</title>
|
||||
<para>
|
||||
Applications using the GStreamer libraries accept the following set
|
||||
of command line argruments to enable the debugging system.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-debug-mask=<replaceable>mask</replaceable></option>
|
||||
Sets the mask for the debugging output.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-info-mask=<replaceable>mask</replaceable></option>
|
||||
Sets the mask for the info output.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-mask=<replaceable>mask</replaceable></option>
|
||||
Sets the mask for the info *and* the debug output.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-plugin-spew</option>
|
||||
Enable printout of errors while loading GST plugins.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--gst-plugin-path=<replaceable>PATH</replaceable></option>
|
||||
Add a directory to the plugin search path.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--help</option> Print the a short desciption of the
|
||||
options and an overview of the current debugging/info masks
|
||||
set.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
The follwing table gives an overview of the mask values and
|
||||
their meaning. (enabled) means that the corresponding flag
|
||||
has been set.
|
||||
</para>
|
||||
<programlisting>
|
||||
Mask (to be OR'ed) info/debug FLAGS
|
||||
--------------------------------------------------------
|
||||
0x00000001 (enabled)/ GST_INIT
|
||||
0x00000002 / COTHREADS
|
||||
0x00000004 / COTHREAD_SWITCH
|
||||
0x00000008 / AUTOPLUG
|
||||
0x00000010 / AUTOPLUG_ATTEMPT
|
||||
0x00000020 / PARENTAGE
|
||||
0x00000040 / STATES
|
||||
0x00000080 / PLANING
|
||||
0x00000100 / SCHEDULING
|
||||
0x00000200 / OPERATION
|
||||
0x00000400 / BUFFER
|
||||
0x00000800 / CAPS
|
||||
0x00001000 / CLOCK
|
||||
0x00002000 / ELEMENT_PADS
|
||||
0x00004000 / ELEMENTFACTORY
|
||||
0x00008000 / PADS
|
||||
0x00010000 / PIPELINE
|
||||
0x00020000 / PLUGIN_LOADING
|
||||
0x00040000 / PLUGIN_ERRORS
|
||||
0x00080000 / PLUGIN_INFO
|
||||
0x00100000 / PROPERTIES
|
||||
0x00200000 / THREAD
|
||||
0x00400000 / TYPES
|
||||
0x00800000 / XML
|
||||
0x01000000 / NEGOTIATION
|
||||
0x02000000 / REFCOUNTING
|
||||
</programlisting>
|
||||
</sect1>
|
||||
<sect1>
|
||||
<title>Adding a custom debug handler</title>
|
||||
<para>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
161
docs/manual/elements.xml
Normal file
161
docs/manual/elements.xml
Normal file
|
@ -0,0 +1,161 @@
|
|||
<chapter id="cha-elements">
|
||||
<title>GstElement</title>
|
||||
<para>
|
||||
The most important object in <application>GStreamer</application> for the
|
||||
application programmer is the <classname>GstElement</classname> object.
|
||||
</para>
|
||||
|
||||
<sect1 id="sec-elements-design">
|
||||
<title>What is a GstElement</title>
|
||||
<para>
|
||||
The GstElement is the basic building block for the media pipeline. All the
|
||||
different components you are going to use are derived from this GstElement.
|
||||
This means that a lot of functions you are going to use operate on this object.
|
||||
</para>
|
||||
<para>
|
||||
You will see that those elements have pads. These are the elements
|
||||
connections with the 'outside' world. Depending on the number and direction of
|
||||
the pads, we can see three types of elements: source, filter and sink element.
|
||||
</para>
|
||||
<para>
|
||||
These three types are all the same GstElement object, they just differ in how
|
||||
the pads are.
|
||||
</para>
|
||||
|
||||
<sect2 id="sec-elements-src">
|
||||
<title>GStreamer source elements</title>
|
||||
<para>
|
||||
This element will generate data that will be used by the pipeline. It is
|
||||
typically a file or an audio source.
|
||||
</para>
|
||||
<para>
|
||||
Below you see how we will visualize the element.
|
||||
We always draw a src pad to the right of the element.
|
||||
</para>
|
||||
<figure float="1" id="sec-element-srcimg">
|
||||
<title>Visualisation of a source element</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/src-element.&magic;" format="&magic;" />
|
||||
</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 src pad. A src pad can only
|
||||
generate buffers.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="sec-elements-filter">
|
||||
<title>GStreamer filter elements</title>
|
||||
<para>
|
||||
Filter elements both have an input and an output pad. They operate on data
|
||||
they receive in the sink pad and send the result to the src pad.
|
||||
</para>
|
||||
<para>
|
||||
Examples of a filter element might include: an MPEG decoder, volume filter,...
|
||||
</para>
|
||||
<para>
|
||||
Filters may also contain any number of input pads and output pads. For example,
|
||||
a video mixer might have to input pads (the images of the two different video
|
||||
streams) and one output pad.
|
||||
</para>
|
||||
<figure float="1" id="sec-element-filterimg">
|
||||
<title>Visualisation of a filter element</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/filter-element.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
<para>
|
||||
The above figure shows the visualisation of a filter element. This element has
|
||||
one sink pad (input) and one src (output) pad. Sink pads are drawn on the left
|
||||
of the element.
|
||||
</para>
|
||||
<figure float="1" id="sec-element-multifilterimg">
|
||||
<title>Visualisation of a filter element with
|
||||
more than one output pad</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/filter-element-multi.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
<para>
|
||||
The above figure shows the visualisation of a filter element with more than one
|
||||
output pad. An example of such a filter is the AVI splitter. This element will
|
||||
parse the input data and extracts 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 connect an arbitrary element to the newly created pad.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="sec-elements-sink">
|
||||
<title>GStreamer sink elements</title>
|
||||
<para>
|
||||
This element accepts data but will not generate any new data. A sink element
|
||||
is typically a file on disk, a soundcard, a display,... It is presented as
|
||||
below:
|
||||
</para>
|
||||
<figure float="1" id="sec-element-sinkimg">
|
||||
<title>Visualisation of a sink element</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/sink-element.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
</sect2>
|
||||
</sect1>
|
||||
<sect1 id="sec-elements-create">
|
||||
<title>Creating a GstElement</title>
|
||||
<para>
|
||||
GstElements are created from factories. To create an element, one has to get
|
||||
access the a <classname>GstElementFactory</classname> using a unique factoryname.
|
||||
</para>
|
||||
<para>
|
||||
The following code example is used to get a factory that can be used to create the
|
||||
mpg123 element, an mp3 decoder.
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElementFactory *factory;
|
||||
|
||||
factory = gst_elementfactory_find ("mpg123");
|
||||
</programlisting>
|
||||
<para>
|
||||
Once you have the handle to the elementfactory, you can create a real element with
|
||||
the following code fragment:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElement *element;
|
||||
|
||||
element = gst_elementfactory_create (factory, "decoder");
|
||||
</programlisting>
|
||||
<para>
|
||||
gst_elementfactory_create () will use the elementfactory to create an element with the
|
||||
given name. The name of the element is something you can use later on to lookup the
|
||||
element in a bin, for example.
|
||||
</para>
|
||||
<para>
|
||||
A simple shortcut exists for creating an element from a factory. The following example
|
||||
creates an element, named "decoder" from the elementfactory named "mpg123". This
|
||||
convenient function is most widly used to create an element.
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElement *element;
|
||||
|
||||
element = gst_elementfactory_make ("mpg123", "decoder");
|
||||
</programlisting>
|
||||
<para>
|
||||
An element can be destroyed with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstElement *element;
|
||||
|
||||
...
|
||||
gst_element_destroy (element);
|
||||
</programlisting>
|
||||
</sect1>
|
||||
</chapter>
|
332
docs/manual/factories.xml
Normal file
332
docs/manual/factories.xml
Normal file
|
@ -0,0 +1,332 @@
|
|||
<chapter id="cha-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 how 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>
|
||||
<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 */
|
||||
parse = gst_elementfactory_make ("mp3parse", "parse");
|
||||
decoder = gst_elementfactory_make ("mpg123", "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 mpg123 by explicitly stating the mpg123 elements name.
|
||||
Our little program therefore always uses the mpg123 decoder element
|
||||
to decode the MP3 audio stream, even if there are 3 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>
|
||||
<title>more on MIME Types</title>
|
||||
<para>
|
||||
GStreamer uses MIME types to indentify 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) types are a set of
|
||||
string that denote a certain type of data. examples include:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
audio/raw : 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, the MIME types are added
|
||||
to the Capability structure of a pad.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In our helloworld example the elements we constructed would have the
|
||||
following MIME types associated with their source and sink pads:
|
||||
</para>
|
||||
<figure float="1" id="sec-mime-img">
|
||||
<title>The Hello world pipeline with MIME types</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/mime-world.&magic;" format="&magic;" />
|
||||
</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
|
||||
me a pipeline that does an audio/mpeg to audio/raw 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>
|
||||
<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.
|
||||
</para>
|
||||
<para>
|
||||
The type information is maintained in a list of
|
||||
<classname>GstType</classname>. The definition of a
|
||||
<classname>GstType</classname> is like:
|
||||
</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>
|
||||
All operations on <classname>GstType</classname> occur via their
|
||||
<classname>guint16 id</classname> numbers, with <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 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>
|
||||
|
||||
<sect2>
|
||||
<title>id to <classname>GstElementFactory</classname> conversion</title>
|
||||
<para>
|
||||
When we have obtained a given type id using one of the above methods,
|
||||
we can obtain a list of all the elements that operate on this MIME
|
||||
type or extension.
|
||||
</para>
|
||||
<para>
|
||||
Obtain a list of all the elements that use this id as source with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GList *list;
|
||||
|
||||
list = gst_type_gst_srcs (id);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Obtain a list of all the elements that use this id as sink with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GList *list;
|
||||
|
||||
list = gst_type_gst_sinks (id);
|
||||
</programlisting>
|
||||
<para>
|
||||
When you have a list of elements, you can simply take the first
|
||||
element of the list to obtain an appropriate element.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
As you can see, there might be a multitude of elements that
|
||||
are able to operate on audio/raw types. some might include:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
an MP3 audio encoder.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
an audio sink.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
an audio resampler.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
a spectrum filter.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
Depending on the application, you might want to use a different
|
||||
element. This is why GStreamer leaves that decision up to the
|
||||
application programmer.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>id to id path detection</title>
|
||||
<para>
|
||||
You can obtain a <classname>GList</classname> of elements that
|
||||
will transform the source id into the destination id.
|
||||
</para>
|
||||
<programlisting>
|
||||
GList *list;
|
||||
|
||||
list = gst_type_gst_sink_to_src (sourceid, sinkid);
|
||||
</programlisting>
|
||||
<para>
|
||||
This piece of code will give you the elements needed to construct
|
||||
a path from sourceid to sinkid. This function is mainly used in
|
||||
autoplugging the pipeline.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<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_elementfactory_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>
|
||||
<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>
|
|
@ -1,34 +1,39 @@
|
|||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
|
||||
<!ENTITY INTRO SYSTEM "intro.sgml">
|
||||
<!ENTITY MOTIVATION SYSTEM "motivation.sgml">
|
||||
<!ENTITY GOALS SYSTEM "goals.sgml">
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
|
||||
<!ENTITY % magic-entities SYSTEM "magic">
|
||||
%magic-entities;
|
||||
|
||||
<!ENTITY INIT SYSTEM "init.sgml">
|
||||
<!ENTITY ELEMENTS SYSTEM "elements.sgml">
|
||||
<!ENTITY PADS SYSTEM "pads.sgml">
|
||||
<!ENTITY CONNECTIONS SYSTEM "connections.sgml">
|
||||
<!ENTITY BINS SYSTEM "bins.sgml">
|
||||
<!ENTITY BUFFERS SYSTEM "buffers.sgml">
|
||||
<!ENTITY STATES SYSTEM "states.sgml">
|
||||
<!ENTITY INTRO SYSTEM "intro.xml">
|
||||
<!ENTITY MOTIVATION SYSTEM "motivation.xml">
|
||||
<!ENTITY GOALS SYSTEM "goals.xml">
|
||||
|
||||
<!ENTITY HELLOWORLD SYSTEM "helloworld.sgml">
|
||||
<!ENTITY FACTORIES SYSTEM "factories.sgml">
|
||||
<!ENTITY AUTOPLUGGING SYSTEM "autoplugging.sgml">
|
||||
<!ENTITY HELLOWORLD2 SYSTEM "helloworld2.sgml">
|
||||
<!ENTITY INIT SYSTEM "init.xml">
|
||||
<!ENTITY ELEMENTS SYSTEM "elements.xml">
|
||||
<!ENTITY PADS SYSTEM "pads.xml">
|
||||
<!ENTITY CONNECTIONS SYSTEM "connections.xml">
|
||||
<!ENTITY BINS SYSTEM "bins.xml">
|
||||
<!ENTITY BUFFERS SYSTEM "buffers.xml">
|
||||
<!ENTITY STATES SYSTEM "states.xml">
|
||||
|
||||
<!ENTITY THREADS SYSTEM "threads.sgml">
|
||||
<!ENTITY QUEUES SYSTEM "queues.sgml">
|
||||
<!ENTITY COTHREADS SYSTEM "cothreads.sgml">
|
||||
<!ENTITY DYNAMIC SYSTEM "dynamic.sgml">
|
||||
<!ENTITY TYPEDETECTION SYSTEM "typedetection.sgml">
|
||||
<!ENTITY UTILITY SYSTEM "utility.sgml">
|
||||
<!ENTITY HELLOWORLD SYSTEM "helloworld.xml">
|
||||
<!ENTITY FACTORIES SYSTEM "factories.xml">
|
||||
<!ENTITY AUTOPLUGGING SYSTEM "autoplugging.xml">
|
||||
<!ENTITY HELLOWORLD2 SYSTEM "helloworld2.xml">
|
||||
|
||||
<!ENTITY XML SYSTEM "xml.sgml">
|
||||
<!ENTITY PLUGINS SYSTEM "plugins.sgml">
|
||||
<!ENTITY DEBUGGING SYSTEM "debugging.sgml">
|
||||
<!ENTITY PROGRAMS SYSTEM "programs.sgml">
|
||||
<!ENTITY COMPONENTS SYSTEM "components.sgml">
|
||||
<!ENTITY QUOTES SYSTEM "quotes.sgml">
|
||||
<!ENTITY THREADS SYSTEM "threads.xml">
|
||||
<!ENTITY QUEUES SYSTEM "queues.xml">
|
||||
<!ENTITY COTHREADS SYSTEM "cothreads.xml">
|
||||
<!ENTITY DYNAMIC SYSTEM "dynamic.xml">
|
||||
<!ENTITY TYPEDETECTION SYSTEM "typedetection.xml">
|
||||
<!ENTITY UTILITY SYSTEM "utility.xml">
|
||||
|
||||
<!ENTITY XML SYSTEM "xml.xml">
|
||||
<!ENTITY PLUGINS SYSTEM "plugins.xml">
|
||||
<!ENTITY DEBUGGING SYSTEM "debugging.xml">
|
||||
<!ENTITY PROGRAMS SYSTEM "programs.xml">
|
||||
<!ENTITY COMPONENTS SYSTEM "components.xml">
|
||||
<!ENTITY QUOTES SYSTEM "quotes.xml">
|
||||
]>
|
||||
|
||||
<book id="index">
|
307
docs/manual/helloworld.xml
Normal file
307
docs/manual/helloworld.xml
Normal file
|
@ -0,0 +1,307 @@
|
|||
<chapter id="cha-hello">
|
||||
<title>Your first application</title>
|
||||
<para>
|
||||
This chapter describes the most rudimentary aspects of a <application>GStreamer</application> application,
|
||||
including initializing the libraries, creating elements, packing them into
|
||||
a pipeline and playing, pause and stop the pipeline.
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title>Hello world</title>
|
||||
<para>
|
||||
We will create a simple first application. In fact it will be a complete
|
||||
MP3 player, using standard <application>GStreamer</application> components. The player will read from
|
||||
a file that is given as the first argument of the program.
|
||||
</para>
|
||||
|
||||
|
||||
<programlisting>
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *pipeline, *disksrc, *parse, *decoder, *audiosink;
|
||||
|
||||
gst_init(&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create a new pipeline to hold the elements */
|
||||
pipeline = gst_pipeline_new ("pipeline");
|
||||
|
||||
/* create a disk reader */
|
||||
disksrc = gst_elementfactory_make ("disksrc", "disk_source");
|
||||
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
|
||||
|
||||
/* now it's time to get the parser */
|
||||
parse = gst_elementfactory_make ("mp3parse", "parse");
|
||||
decoder = gst_elementfactory_make ("mpg123", "decoder");
|
||||
|
||||
/* and an audio sink */
|
||||
audiosink = gst_elementfactory_make ("osssink", "play_audio");
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add (GST_BIN (pipeline), disksrc);
|
||||
gst_bin_add (GST_BIN (pipeline), parse);
|
||||
gst_bin_add (GST_BIN (pipeline), decoder);
|
||||
gst_bin_add (GST_BIN (pipeline), audiosink);
|
||||
|
||||
/* connect src to sink */
|
||||
gst_pad_connect (gst_element_get_pad (disksrc, "src"),
|
||||
gst_element_get_pad (parse, "sink"));
|
||||
gst_pad_connect (gst_element_get_pad (parse, "src"),
|
||||
gst_element_get_pad (decoder, "sink"));
|
||||
gst_pad_connect (gst_element_get_pad (decoder, "src"),
|
||||
gst_element_get_pad (audiosink, "sink"));
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
while (gst_bin_iterate (GST_BIN (pipeline)));
|
||||
|
||||
/* stop the pipeline */
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
||||
/* we don't need a reference to these objects anymore */
|
||||
gst_object_unref (GST_OBJECT (audiosink));
|
||||
gst_object_unref (GST_OBJECT (parse));
|
||||
gst_object_unref (GST_OBJECT (decoder));
|
||||
gst_object_unref (GST_OBJECT (disksrc));
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
</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 4 elements and one pipeline. Since all objects are
|
||||
in fact elements, we can define them as:
|
||||
</para>
|
||||
<programlisting>
|
||||
...
|
||||
GstElement *pipeline, *disksrc, *parse, *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 stuff 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 ("name").
|
||||
</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 */
|
||||
disksrc = gst_elementfactory_make ("disksrc", "disk_source");
|
||||
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
|
||||
</programlisting>
|
||||
<note>
|
||||
<para>
|
||||
You can check if the disksrc != NULL to verify the creation of the
|
||||
disk source element.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
We now create the MP3 decoder element. <application>GStreamer</application> requires you
|
||||
to put a parser in front of the decoder. This parser will
|
||||
cut the raw data from the disk source into MP3 frames
|
||||
suitable for the decoder. In the advanced concepts chapter we will
|
||||
see how this can be avoided.
|
||||
</para>
|
||||
<programlisting>
|
||||
/* now it's time to get the parser */
|
||||
parse = gst_elementfactory_make ("mp3parse", "parse");
|
||||
decoder = gst_elementfactory_make ("mpg123", "decoder");
|
||||
</programlisting>
|
||||
<para>
|
||||
gst_elementfactory_make() takes two arguments: a string that will
|
||||
identify the element you need and a second argument: how you want
|
||||
to name the element. The name of the element is something you can
|
||||
choose yourself and might be used to retrieve the element from a
|
||||
bin/pipeline.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Finally we create our audio sink element. This element will be able
|
||||
to playback the audio using OSS.
|
||||
</para>
|
||||
<programlisting>
|
||||
/* and an audio sink */
|
||||
audiosink = gst_elementfactory_make ("audiosink", "play_audio");
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
We then add the elements to the pipeline.
|
||||
</para>
|
||||
<programlisting>
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add (GST_BIN (pipeline), disksrc);
|
||||
gst_bin_add (GST_BIN (pipeline), parse);
|
||||
gst_bin_add (GST_BIN (pipeline), decoder);
|
||||
gst_bin_add (GST_BIN (pipeline), audiosink);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
We connect the different pads of the elements together like this:
|
||||
</para>
|
||||
<programlisting>
|
||||
/* connect src to sink */
|
||||
gst_pad_connect (gst_element_get_pad (disksrc, "src"),
|
||||
gst_element_get_pad (parse, "sink"));
|
||||
gst_pad_connect (gst_element_get_pad (parse, "src"),
|
||||
gst_element_get_pad (decoder, "sink"));
|
||||
gst_pad_connect (gst_element_get_pad (decoder, "src"),
|
||||
gst_element_get_pad (audiosink, "sink"));
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
We now have a created a complete pipeline. We can visualise the
|
||||
pipeline as follows:
|
||||
</para>
|
||||
<figure float="1" id="sec-hello-img">
|
||||
<title>The Hello world pipeline</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/hello-world.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
</figure>
|
||||
|
||||
<para>
|
||||
Everything is now set up to start the streaming. We use the following
|
||||
statements to change the state of the pipeline:
|
||||
</para>
|
||||
<programlisting>
|
||||
/* start playing */
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
</programlisting>
|
||||
<note>
|
||||
<para>
|
||||
<application>GStreamer</application> will take care of the READY and PAUSED state for y
|
||||
ou when going from NULL to PLAYING.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Since we do not use threads, nothing will happen yet. We manually have to
|
||||
call gst_bin_iterate() to execute one iteration of the pipeline.
|
||||
</para>
|
||||
<programlisting>
|
||||
while (gst_bin_iterate (GST_BIN (pipeline)));
|
||||
</programlisting>
|
||||
<para>
|
||||
The gst_bin_iterate() function will return TRUE as long as something interesting
|
||||
happended inside the pipeline. When the end-of-file has been reached the _iterate
|
||||
function will return FALSE and we can end the loop.
|
||||
</para>
|
||||
<programlisting>
|
||||
/* stop the pipeline */
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
||||
gst_object_unref (GST_OBJECT (audiosink));
|
||||
gst_object_unref (GST_OBJECT (decoder));
|
||||
gst_object_unref (GST_OBJECT (disksrc));
|
||||
gst_object_unref (GST_OBJECT (pipeline));
|
||||
|
||||
exit (0);
|
||||
</programlisting>
|
||||
<note>
|
||||
<para>
|
||||
don't forget to set the state of the pipeline to NULL. This will free
|
||||
all of the resources held by the elements.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>compiling helloworld.c</title>
|
||||
<para>
|
||||
To compile the helloworld example, use:
|
||||
</para>
|
||||
<programlisting>
|
||||
gcc -Wall `gstreamer-config --cflags --libs` helloworld.c \
|
||||
-o helloworld
|
||||
</programlisting>
|
||||
<para>
|
||||
This uses the program gstreamer-config, which comes with <application>GStreamer</application>. This program "knows"
|
||||
what compiler switches are needed to compile programs that use <application>GStreamer</application>.
|
||||
gstreamer-config --cflags will output a list of include
|
||||
directories for the compiler to look in, and gstreamer-config --libs will output the
|
||||
list of libraries for the compiler to link with and the directories to find them
|
||||
in.
|
||||
</para>
|
||||
<para>
|
||||
You can run the example with (substitute helloworld.mp3 with you favorite MP3 file):
|
||||
</para>
|
||||
<programlisting>
|
||||
./helloworld helloworld.mp3
|
||||
</programlisting>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>conclusion</title>
|
||||
<para>
|
||||
This concludes our first example. As you see, setting up a pipeline
|
||||
is very lowlevel but powerfull. You will later in this manual how
|
||||
you can create a custom MP3 element with a more high level API.
|
||||
</para>
|
||||
<para>
|
||||
It should be clear from the example that we can very easily replace the
|
||||
disksrc element with an httpsrc, giving you instant network streaming.
|
||||
An element could be build to handle icecast connections, for example.
|
||||
</para>
|
||||
<para>
|
||||
We can also choose to use another type of sink instead of the audiosink.
|
||||
We could use a disksink to write the raw samples to a file, for example.
|
||||
It should also be clear that inserting filters, like a stereo effect,
|
||||
into the pipeline is not that hard to do. The most important thing is
|
||||
that you can reuse allready existing elements.
|
||||
</para>
|
||||
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
32
docs/manual/highlevel-components.xml
Normal file
32
docs/manual/highlevel-components.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<chapter id="cha-components">
|
||||
<title>Components</title>
|
||||
<para>
|
||||
<application>GStreamer</application> includes components that people can include
|
||||
in their programs.
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title>GstPlay</title>
|
||||
<para>
|
||||
GstPlay is a GtkWidget with a simple API to play, pause and stop a media file.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>GstMediaPlay</title>
|
||||
<para>
|
||||
GstMediaply is a complete player widget.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title>GstEditor</title>
|
||||
<para>
|
||||
GstEditor is a set of widgets to display a graphical representation of a
|
||||
pipeline.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
49
docs/manual/intro.xml
Normal file
49
docs/manual/intro.xml
Normal file
|
@ -0,0 +1,49 @@
|
|||
<chapter id="cha-intro">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
This chapter gives you an overview of the technologies described in this
|
||||
book.
|
||||
</para>
|
||||
|
||||
<sect1 id="sec-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
|
||||
streaming multimedia application. The framework includes several
|
||||
components to build a full featured media player capable of playing
|
||||
MPEG1, MPEG2, AVI, MP3, WAV, AU, ...
|
||||
</para>
|
||||
|
||||
<para>
|
||||
GStreamer, however, is much more than just another media player. Its
|
||||
main advantages are that the pluggable components also make it possible
|
||||
to write a full flegded video or audio editing application.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The framework is based on plug-ins that will provide the various codec
|
||||
and other functionality. The plugins can be connected 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.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
1
docs/manual/magic-pdf
Normal file
1
docs/manual/magic-pdf
Normal file
|
@ -0,0 +1 @@
|
|||
<!ENTITY magic "pdf">
|
1
docs/manual/magic-png
Normal file
1
docs/manual/magic-png
Normal file
|
@ -0,0 +1 @@
|
|||
<!ENTITY magic "png">
|
99
docs/manual/motivation.xml
Normal file
99
docs/manual/motivation.xml
Normal file
|
@ -0,0 +1,99 @@
|
|||
<chapter id="cha-motivation">
|
||||
<title>Motivation</title>
|
||||
<para>
|
||||
Linux has historically lagged behind other operating systems in the multimedia
|
||||
arena. Microsoft's Windows[tm] and Apple's MacOS[tm] 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="sec-motivation-problems">
|
||||
<title>Current problems</title>
|
||||
<para>
|
||||
We descibe the typical problems in todays media handling on Linux.
|
||||
</para>
|
||||
<sect2 id="sec-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="sec-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 I wanted to convert an MPEG2 video stream into an AVI file, my best
|
||||
option would be to take all of the MPEG2 decoding algorithms out
|
||||
of the player and duplicate them into my own AVI encoder. These
|
||||
algorithms cannot easily be shared accross 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="sec-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.
|
||||
</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.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="sec-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 emerging technologies such as
|
||||
the GNOME object embedding using BONOBO.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="sec-motivation-catchup">
|
||||
<title>Catch up with the Windows(tm) 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>
|
459
docs/manual/pads.xml
Normal file
459
docs/manual/pads.xml
Normal file
|
@ -0,0 +1,459 @@
|
|||
<chapter id="cha-pads">
|
||||
<title>GstPad</title>
|
||||
<para>
|
||||
As we have seen in the previous chapter (GstElement), the pads are the elements
|
||||
connections with 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 (<classname>GstCaps</classname>)
|
||||
</para>
|
||||
|
||||
<sect1 id="sec-pads-get">
|
||||
<title>Getting pads from an element</title>
|
||||
<para>
|
||||
Once you have created an element, you can get one of its pads with:
|
||||
</para>
|
||||
<programlisting>
|
||||
GstPad *srcpad;
|
||||
...
|
||||
srcpad = gst_element_get_pad (element, "src");
|
||||
...
|
||||
</programlisting>
|
||||
<para>
|
||||
This function will get the pad named "src" from the given element.
|
||||
</para>
|
||||
<para>
|
||||
Alternatively, you can also request a GList of pads from the element. The following
|
||||
code example will print the names of all the pads of an element.
|
||||
</para>
|
||||
<programlisting>
|
||||
GList *pads;
|
||||
...
|
||||
pads = gst_element_get_pad_list (element);
|
||||
while (pads) {
|
||||
GstPad *pad = GST_PAD (pads->data);
|
||||
|
||||
g_print ("pad name %s\n", gst_pad_get_name (pad));
|
||||
|
||||
pads = g_list_next (pads);
|
||||
}
|
||||
...
|
||||
</programlisting>
|
||||
<sect2 id="sec-pads-functions">
|
||||
<title>Useful pad functions</title>
|
||||
<para>
|
||||
You can get the name of a pad with gst_pad_get_name () and set its name with
|
||||
get_pad_set_name();
|
||||
</para>
|
||||
<para>
|
||||
gst_pad_get_direction (GstPad *pad) can be used to query if the pad is a sink
|
||||
or a src pad. Remember a src pad is a pad that can output data and a sink pad is
|
||||
one that accepts data.
|
||||
</para>
|
||||
<para>
|
||||
You can get the parent of the pad, this is the element that this pad belongs to,
|
||||
with get_pad_set_parent(GstPad *pad). This function will return a pointer to a
|
||||
GstObject.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="sec-pads-dynamic">
|
||||
<title>Dynamic pads</title>
|
||||
<para>
|
||||
Some elements might not have their pads when they are created. This can, for
|
||||
example, happen with an MPEG2 system demuxer. The demuxer will create its
|
||||
pads at runtime when it detects the different elementary streams in the MPEG2
|
||||
system stream.
|
||||
</para>
|
||||
<para>
|
||||
Running <application>gstreamer-inspect mpeg2parse</application> will show that
|
||||
the element has only one pad: a sink pad called 'sink'. The other pads are
|
||||
"dormant" as you can see in the padtemplates from the 'Exists: Sometimes'
|
||||
property. Depending on the type of MPEG2 file you play, the pads are created. We
|
||||
will see that this is very important when you are going to create dynamic
|
||||
pipelines later on in this manual.
|
||||
</para>
|
||||
<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_connect_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
|
||||
...
|
||||
// connect 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 usefull
|
||||
...
|
||||
|
||||
mpeg2parser = gst_elementfactory_make ("mpeg2parse", "mpeg2parse");
|
||||
g_signal_connect (G_OBJECT (mpeg2parser), "new_pad", pad_connect_func, pipeline);
|
||||
...
|
||||
|
||||
// start the pipeline
|
||||
gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
|
||||
...
|
||||
}
|
||||
</programlisting>
|
||||
<note>
|
||||
<para>
|
||||
You need to set the pipeline to READY or NULL if you want to change it.
|
||||
</para>
|
||||
</note>
|
||||
</sect2>
|
||||
<sect2 id="sec-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 usefull for muxers, 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>
|
||||
<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 connect another element to it.
|
||||
</para>
|
||||
<programlisting>
|
||||
...
|
||||
GstPad *pad;
|
||||
...
|
||||
element = gst_elementfactory_make ("tee", "element");
|
||||
|
||||
pad = gst_element_request_pad_by_name (element, "src%d");
|
||||
g_print ("new pad %s\n", gst_pad_get_name (pad));
|
||||
...
|
||||
</programlisting>
|
||||
<para>
|
||||
The gst_element_request_pad_by_name 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
|
||||
padtemplate. This is very usefull if you want to connect an element to
|
||||
a muxer element and you need to request a pad that is compatible. The
|
||||
gst_element_request_compatible_pad is used to request a compatible pad, as
|
||||
is shown in the next example.
|
||||
</para>
|
||||
<programlisting>
|
||||
...
|
||||
GstPadTemplate *templ;
|
||||
GstPad *pad;
|
||||
...
|
||||
element = gst_elementfactory_make ("tee", "element");
|
||||
mp3parse = gst_elementfactory_make ("mp3parse", "mp3parse");
|
||||
|
||||
templ = gst_element_get_padtemplate_by_name (mp3parse, "sink");
|
||||
|
||||
pad = gst_element_request_compatible_pad (element, templ);
|
||||
g_print ("new pad %s\n", gst_pad_get_name (pad));
|
||||
...
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
<sect1 id="sec-pads-description">
|
||||
<title>Capabilities of a GstPad</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 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
|
||||
filter-writer-guide.
|
||||
</para>
|
||||
|
||||
<sect2 id="sec-pads-caps">
|
||||
<title>What is a capability</title>
|
||||
<para>
|
||||
A capability is attached to a pad in order to describe what type of media the pad
|
||||
can handle.
|
||||
</para>
|
||||
<para>
|
||||
A capability is named and consists of a MIME type and a set of properties. Its data
|
||||
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>
|
||||
<para>
|
||||
Below is a dump of the capabilities of the element mpg123, as shown by
|
||||
<command>gstreamer-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 src 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: 'sink'
|
||||
....
|
||||
Capabilities:
|
||||
'mpg123_sink':
|
||||
MIME type: 'audio/mp3':
|
||||
layer: Integer range: 1 - 3
|
||||
bitrate: Integer range: 8 - 320
|
||||
framed: Boolean: TRUE
|
||||
|
||||
SRC: 'src'
|
||||
....
|
||||
Capabilities:
|
||||
'mpg123_src':
|
||||
MIME type: 'audio/raw':
|
||||
format: Integer: 16
|
||||
depth: Integer: 16
|
||||
rate: Integer range: 11025 - 48000
|
||||
channels: List:
|
||||
Integer: 1
|
||||
Integer: 2
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="sec-pads-props">
|
||||
<title>What are properties</title>
|
||||
<para>
|
||||
Properties are used to describe extra information for the capabilities. The properties
|
||||
basically exist of a key (a string) and a value. There are different possibile value types
|
||||
that can be used:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
An integer value: the property has this exact value.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
An integer range value. The property denotes a range of possible values. In the case
|
||||
of the mpg123 element: the src pad has a property rate that can go from 11025 to 48000.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A boolean value.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
a fourcc value: this is a value that is commonly used to describe an encoding for video,
|
||||
as used be the AVI specification.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A list value: the property can take any value from a list.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A float value: the property has this exact floating point value.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A float range value: denotes a range of possible floating point values.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A string value.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</sect2>
|
||||
<sect2 id="sec-pads-caps-use">
|
||||
<title>What are the capabilities 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 connected, <application>GStreamer</application>
|
||||
can verify if the two pads are talking about the same media types.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</sect2>
|
||||
<sect2 id="sec-pads-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="sec-pads-caps-create">
|
||||
<title>Creating capabilities structures</title>
|
||||
<para>
|
||||
While the capabilities are mainly used inside the plugin to describe the media type of the
|
||||
pads, the application programmer also has to have basic understanding of caps in order to
|
||||
interface with the plugins, specially 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 <classname>GstCaps *</classname> structure is like:
|
||||
<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/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 ragne from a to b
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
GST_PROPS_FLOAT_RANGE(a,b): A float ragne 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/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/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>
|
70
docs/manual/plugins.xml
Normal file
70
docs/manual/plugins.xml
Normal file
|
@ -0,0 +1,70 @@
|
|||
<chapter id="cha-plugins">
|
||||
<title>What are Plugins</title>
|
||||
<para>
|
||||
A plugin is a shared library that contains at least one of the following items:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
one or more elementfactories
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
one or more typedefinitions
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
one or more autopluggers
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
The plugins have one simple method: plugin_init () where all the elementfactories are
|
||||
created and the typedefinitions are registered.
|
||||
</para>
|
||||
<para>
|
||||
the plugins are maintained in the plugin system. Optionally, the typedefinitions and
|
||||
the elementfactories 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>
|
||||
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 GList of available plugins with:
|
||||
</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>
|
240
docs/manual/programs.xml
Normal file
240
docs/manual/programs.xml
Normal file
|
@ -0,0 +1,240 @@
|
|||
<chapter id="cha-programs">
|
||||
<title>Programs</title>
|
||||
<para>
|
||||
</para>
|
||||
|
||||
<sect1>
|
||||
<title><command>gstreamer-config</command></title>
|
||||
<para>
|
||||
<command>gstreamer-config</command> is a script to get information about the installed
|
||||
version of <application>GStreamer</application>.
|
||||
This program "knows" what compiler switches are needed to compile programs that use
|
||||
<application>GStreamer</application>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<command>gstreamer-config</command> accepts the following options:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--version</option> Print the currently installed version of
|
||||
<application>GStreamer</application> on the standard output.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--libs</option> Print the linker flags that are necessary to link a
|
||||
<application>GStreamer</application> program.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--cflags</option> Print the compiler flags that are necessary to compile a
|
||||
<application>GStreamer</application> program.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--prefix=<replaceable>PREFIX</replaceable></option>
|
||||
If specified, use <replaceable>PREFIX</replaceable> instead of the installation
|
||||
prefix that <application>GStreamer</application> was built with when computing the
|
||||
output for the <option>--cflags</option> and <option>--libs</option> options.
|
||||
This option is also used for the exec prefix if
|
||||
<option>--exec-prefix</option> was not specified. This option must be specified before any
|
||||
<option>--libs</option> or <option>--cflags</option> options.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>--exec-prefix=<replaceable>PREFIX</replaceable></option>
|
||||
If specified, use <replaceable>PREFIX</replaceable> instead of the installation exec
|
||||
prefix that <application>GStreamer</application> was built with when computing the
|
||||
output for the <option>--cflags</option> and <option>--libs</option> options. This option must be
|
||||
specified before any <option>--libs</option> or <option>--cflags</option>
|
||||
options.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
A simple <filename>Makefile</filename> will contain something like:
|
||||
<programlisting>
|
||||
CC = gcc
|
||||
|
||||
helloworld2: helloworld2.c
|
||||
$(CC) -Wall `gstreamer-config --cflags --libs` helloworld2.c -o helloworld2
|
||||
|
||||
clean:
|
||||
rm -f *.o helloworld2
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title><command>gstreamer-register</command></title>
|
||||
<para>
|
||||
<command>gstreamer-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 in <filename>/etc/gstreamer/reg.xml</filename>.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title><command>gstreamer-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>
|
||||
gstreamer-launch disksrc location=hello.mp3 ! mp3parse ! mpg123 ! audiosink
|
||||
</screen>
|
||||
|
||||
A more complex pipeline looks like:
|
||||
|
||||
<screen>
|
||||
gstreamer-launch disksrc redpill.vob audio_00! (ac3parse ! ac3dec ! audiosink) \
|
||||
video_00! (mpeg2dec ! videosink)
|
||||
</screen>
|
||||
|
||||
</para>
|
||||
<para>
|
||||
Note that the parser isn't capable of more complex pipelines yet, including
|
||||
the VOB player above. The minor tweaks will be made post 0.2.1.
|
||||
</para>
|
||||
<para>
|
||||
You can also use the the parser in you own code. <application>GStreamer</application>
|
||||
provides a function gst_parse_launch () that you can use to construt a pipeline.
|
||||
The following programs lets you create an mp3 pipeline using the gst_parse_launch ()
|
||||
function:
|
||||
</para>
|
||||
<programlisting>
|
||||
#include <gst/gst.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *pipeline;
|
||||
GstElement *disksrc;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
pipeline = gst_pipeline_new ("my_pipeline");
|
||||
|
||||
gst_parse_launch ("disksrc[my_disksrc] ! mp3parse ! mpg123 ! osssink", GST_BIN (pipeline));
|
||||
|
||||
disksrc = gst_bin_get_by_name (GST_BIN (pipeline), "my_disksrc");
|
||||
g_object_set (G_OBJECT (disksrc), "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 disksrc element from the constructed bin using the
|
||||
element name.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
<title><command>gstreamer-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 mpg123, you would specify:
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
gstreamer-inspect mpg123
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
Below is the output of a query for the audiosink element:
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
Factory Details:
|
||||
Long name: Audio Sink (OSS)
|
||||
Class: Sink/Audio
|
||||
Description: Output to a sound card via OSS
|
||||
Version: 0.1.0
|
||||
Author(s): Erik Walthinsen <omega@cse.ogi.edu>
|
||||
Copyright: (C) 1999
|
||||
|
||||
Pad Templates:
|
||||
SINK template: 'sink'
|
||||
Exists: Always
|
||||
Capabilities:
|
||||
'audiosink_sink':
|
||||
MIME type: 'audio/raw':
|
||||
format: Integer: 16
|
||||
depth: List:
|
||||
Integer: 8
|
||||
Integer: 16
|
||||
rate: Integer range: 8000 - 48000
|
||||
channels: Integer range: 1 - 2
|
||||
|
||||
Element Flags:
|
||||
GST_ELEMENT_THREADSUGGESTED
|
||||
no flags set
|
||||
|
||||
Element Implementation:
|
||||
No loopfunc(), must be chain-based or not configured yet
|
||||
Has change_state() function
|
||||
|
||||
Pads:
|
||||
SINK: 'sink'
|
||||
Implementation:
|
||||
Has chainfunc(): 0x4001cde8
|
||||
Has default eosfunc() gst_pad_eos_func()
|
||||
Pad Template: 'sink'
|
||||
Capabilities:
|
||||
'audiosink_sink':
|
||||
MIME type: 'audio/raw':
|
||||
format: Integer: 16
|
||||
depth: List:
|
||||
Integer: 8
|
||||
Integer: 16
|
||||
rate: Integer range: 8000 - 48000
|
||||
channels: Integer range: 1 - 2
|
||||
|
||||
Element Arguments:
|
||||
GstAudioSink::mute: Boolean
|
||||
GstAudioSink::format: Enum (default 16)
|
||||
(8): 8 Bits
|
||||
(16): 16 Bits
|
||||
GstAudioSink::channels: Enum (default 2)
|
||||
(1): Mono
|
||||
(2): Stereo
|
||||
GstAudioSink::frequency: Integer
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
To query the information about a plugin, you would do:
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
gstreamer-inspect gstelements
|
||||
</screen>
|
||||
</sect1>
|
||||
<sect1>
|
||||
<title><command>gstmediaplay</command></title>
|
||||
<para>
|
||||
A sample media player.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
|
@ -26,7 +26,7 @@
|
|||
<title>a two-threaded decoder with a queue</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/queue" format="PNG">
|
||||
<imagedata fileref="images/queue.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
186
docs/manual/quotes.xml
Normal file
186
docs/manual/quotes.xml
Normal file
|
@ -0,0 +1,186 @@
|
|||
<chapter id="cha-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.openprojects.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>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 oru 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>
|
|
@ -54,10 +54,10 @@
|
|||
<para>
|
||||
You can set the following states to an element:
|
||||
</para>
|
||||
<informaltable pgwide=1 frame="none" role="enum">
|
||||
<informaltable pgwide="1" frame="none" role="enum">
|
||||
<tgroup cols="2">
|
||||
<colspec colwidth="2*">
|
||||
<colspec colwidth="8*">
|
||||
<colspec colwidth="2*" />
|
||||
<colspec colwidth="8*" />
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><literal>GST_STATE_NULL</literal></entry>
|
143
docs/manual/threads.xml
Normal file
143
docs/manual/threads.xml
Normal file
|
@ -0,0 +1,143 @@
|
|||
<chapter id="cha-threads">
|
||||
<title>Threads</title>
|
||||
<para>
|
||||
GStreamer has support for multithreading throught the use of
|
||||
the <classname>GstThread</classname> object. This object is in fact
|
||||
a special <classname>GstBin</classname> that will become a thread when started.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To construct a new thread you will perform something like:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
GstElement *my_thread;
|
||||
|
||||
// create the thread object
|
||||
my_thread = gst_thread_new ("my_thread");
|
||||
g_return_if_fail (audio_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));
|
||||
|
||||
// connect the elements here...
|
||||
...
|
||||
|
||||
// start playing
|
||||
gst_element_set_state (GST_ELEMENT (my_thread), GST_STATE_PLAYING);
|
||||
|
||||
</programlisting>
|
||||
|
||||
<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.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
A thread should normally contain a source element. Most often, the thread
|
||||
is fed with data from a queue.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
A thread will be visualised as below
|
||||
</para>
|
||||
<figure float="1" id="sec-threads-img">
|
||||
<title>a thread</title>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="images/thread.&magic;" format="&magic;" />
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</figure>
|
||||
|
||||
<para>
|
||||
As an example we show the helloworld program using a thread.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
#include <gst/gst.h>
|
||||
|
||||
/* eos will be called when the src element has an end of stream */
|
||||
void
|
||||
eos (GstSrc *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);
|
||||
|
||||
gst_main_quit ();
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *disksrc, *audiosink;
|
||||
GstElement *pipeline;
|
||||
GstElement *thread;
|
||||
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <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 new bin to hold the elements */
|
||||
pipeline = gst_pipeline_new ("pipeline");
|
||||
g_assert (pipeline != NULL);
|
||||
|
||||
/* create a disk reader */
|
||||
disksrc = gst_elementfactory_make ("disksrc", "disk_source");
|
||||
g_assert (disksrc != NULL);
|
||||
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
|
||||
g_signal_connect (G_OBJECT (disksrc), "eos",
|
||||
G_CALLBACK (eos), thread);
|
||||
|
||||
/* and an audio sink */
|
||||
audiosink = gst_elementfactory_make ("audiosink", "play_audio");
|
||||
g_assert (audiosink != NULL);
|
||||
|
||||
/* add objects to the main pipeline */
|
||||
gst_bin_add (GST_BIN (pipeline), disksrc);
|
||||
gst_bin_add (GST_BIN (pipeline), audiosink);
|
||||
|
||||
/* automatically setup the pipeline */
|
||||
if (!gst_pipeline_autoplug (GST_PIPELINE (pipeline))) {
|
||||
g_print ("unable to handle stream\n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* remove the source element from the pipeline */
|
||||
gst_bin_remove (GST_BIN (pipeline), disksrc);
|
||||
|
||||
/* insert the source element in the thread, remember a thread needs at
|
||||
least one source or connection element */
|
||||
gst_bin_add (GST_BIN (thread), disksrc);
|
||||
|
||||
/* add the pipeline to the thread too */
|
||||
gst_bin_add (GST_BIN (thread), GST_ELEMENT (pipeline));
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state (GST_ELEMENT (thread), GST_STATE_PLAYING);
|
||||
|
||||
/* do whatever you want here, the thread will be playing */
|
||||
...
|
||||
|
||||
gst_main ();
|
||||
|
||||
gst_pipeline_destroy (thread);
|
||||
|
||||
exit (0);
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
</chapter>
|
292
docs/manual/xml.xml
Normal file
292
docs/manual/xml.xml
Normal file
|
@ -0,0 +1,292 @@
|
|||
<chapter id="cha-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="sec-xml-write">
|
||||
<title>Turning GstElements into XML</title>
|
||||
|
||||
<para>
|
||||
We create a simple pipeline and save it to disk with gst_xml_write (). The following
|
||||
code constructs an mp3 player pipeline with two threads and finaly writes it to disk.
|
||||
use this program with one argument: the mp3 file on disk.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
#include <stdlib.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
gboolean playing;
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GstElement *disksrc, *audiosink, *queue, *queue2, *parse, *decode;
|
||||
GstElement *bin;
|
||||
GstElement *thread, *thread2;
|
||||
|
||||
gst_init (&argc,&argv);
|
||||
|
||||
if (argc != 2) {
|
||||
g_print ("usage: %s <filename>\n", argv[0]);
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* create a new thread to hold the elements */
|
||||
thread = gst_elementfactory_make ("thread", "thread");
|
||||
g_assert (thread != NULL);
|
||||
thread2 = gst_elementfactory_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 */
|
||||
disksrc = gst_elementfactory_make ("disksrc", "disk_source");
|
||||
g_assert (disksrc != NULL);
|
||||
g_object_set (G_OBJECT (disksrc), "location", argv[1], NULL);
|
||||
|
||||
queue = gst_elementfactory_make ("queue", "queue");
|
||||
queue2 = gst_elementfactory_make ("queue", "queue2");
|
||||
|
||||
/* and an audio sink */
|
||||
audiosink = gst_elementfactory_make ("audiosink", "play_audio");
|
||||
g_assert (audiosink != NULL);
|
||||
|
||||
parse = gst_elementfactory_make ("mp3parse", "parse");
|
||||
decode = gst_elementfactory_make ("mpg123", "decode");
|
||||
|
||||
/* add objects to the main bin */
|
||||
gst_bin_add (GST_BIN (bin), disksrc);
|
||||
gst_bin_add (GST_BIN (bin), queue);
|
||||
|
||||
gst_bin_add (GST_BIN (thread), parse);
|
||||
gst_bin_add (GST_BIN (thread), decode);
|
||||
gst_bin_add (GST_BIN (thread), queue2);
|
||||
|
||||
gst_bin_add (GST_BIN (thread2), audiosink);
|
||||
|
||||
gst_pad_connect (gst_element_get_pad (disksrc,"src"),
|
||||
gst_element_get_pad (queue,"sink"));
|
||||
|
||||
gst_pad_connect (gst_element_get_pad (queue,"src"),
|
||||
gst_element_get_pad (parse,"sink"));
|
||||
gst_pad_connect (gst_element_get_pad (parse,"src"),
|
||||
gst_element_get_pad (decode,"sink"));
|
||||
gst_pad_connect (gst_element_get_pad (decode,"src"),
|
||||
gst_element_get_pad (queue2,"sink"));
|
||||
|
||||
gst_pad_connect (gst_element_get_pad (queue2,"src"),
|
||||
gst_element_get_pad (audiosink,"sink"));
|
||||
|
||||
gst_bin_add (GST_BIN (bin), thread);
|
||||
gst_bin_add (GST_BIN (bin), thread2);
|
||||
|
||||
// write the bin to disk
|
||||
xmlSaveFile ("xmlTest.gst", gst_xml_write (GST_ELEMENT (bin)));
|
||||
|
||||
exit (0);
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
The most important line is:
|
||||
</para>
|
||||
<programlisting>
|
||||
xmlSaveFile ("xmlTest.gst", gst_xml_write (GST_ELEMENT (bin)));
|
||||
</programlisting>
|
||||
<para>
|
||||
gst_xml_write () will turn the given element into and xmlDocPtr that
|
||||
can be saved with the xmlSaveFile () function found in the gnome-xml
|
||||
package. The result is an XML file named xmlTest.gst.
|
||||
</para>
|
||||
<para>
|
||||
The complete element hierarchy will be saved along with the inter element
|
||||
pad connections 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="sec-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
|
||||
respectivily. both of these methods return a gboolean indicating success
|
||||
or failure of the requested action.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="sec-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 connect
|
||||
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_elementfactory_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 caled. 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>
|
175
docs/manuals.mak
175
docs/manuals.mak
|
@ -1,107 +1,98 @@
|
|||
# Included by directories containing manuals.
|
||||
# Expects the following to be defined:
|
||||
# manualname
|
||||
# htmlname
|
||||
# sgml_files
|
||||
# fig_files
|
||||
# eps_files
|
||||
# png_files
|
||||
|
||||
PDFFILES=$(manualname).pdf
|
||||
PSFILES=$(manualname).ps
|
||||
# taken from selfdocbookx, http://cyberelk.net/tim/docbook/selfdocbookx/index.html
|
||||
|
||||
if HAVE_FIG2DEV_PNG
|
||||
PNGS_TO_MAKE=$(png_files)
|
||||
else
|
||||
PNGS_TO_MAKE=
|
||||
endif
|
||||
# modified by andy wingo <apwingo@eos.ncsu.edu> 14 dec 2001 for use by gstreamer
|
||||
|
||||
$(manualname)/$(htmlname): $(sgml_files) $(PNGS_TO_MAKE)
|
||||
if HAVE_DB2HTML
|
||||
db2html $(manualname).sgml
|
||||
else
|
||||
@echo "Can't build $@: don't have db2html tool"
|
||||
endif
|
||||
all: html ps pdf
|
||||
|
||||
$(manualname).pdf: $(manualname).ps
|
||||
if HAVE_PS2PDF
|
||||
@if [ -r $< ] ; then ps2pdf $< $@ ; fi
|
||||
else
|
||||
@echo "Can't build $@: don't have ps2pdf tool"
|
||||
endif
|
||||
if HAVE_XSLTPROC
|
||||
|
||||
if HAVE_FIG2DEV_EPS
|
||||
$(manualname).ps: $(sgml_files) $(eps_files)
|
||||
else
|
||||
$(manualname).ps: $(sgml_files)
|
||||
endif
|
||||
if HAVE_DB2PS
|
||||
@if [ -r $< ] ; then db2ps $(manualname).sgml ; fi
|
||||
else
|
||||
@echo "Can't build $@: don't have db2ps tool"
|
||||
endif
|
||||
if HAVE_FIG2DEV_PNG
|
||||
html: $(DOC)
|
||||
else !HAVE_FIG2DEV_PNG
|
||||
html:
|
||||
endif !HAVE_FIG2DEV_PNG
|
||||
|
||||
images :
|
||||
mkdir images
|
||||
if HAVE_FIG2DEV_PDF
|
||||
if HAVE_PDFXMLTEX
|
||||
pdf: $(DOC).pdf
|
||||
|
||||
if HAVE_FIG2DEV_PNG
|
||||
images/%.png : %.fig images
|
||||
fig2dev -L png -s 16 $< $@
|
||||
endif
|
||||
if HAVE_PDFTOPS
|
||||
ps: $(DOC).ps
|
||||
else !HAVE_PDFTOPS
|
||||
ps:
|
||||
endif !HAVE_PDFTOPS
|
||||
|
||||
if HAVE_FIG2DEV_EPS
|
||||
images/%.eps : %.fig images
|
||||
fig2dev -L eps -s 16 -m 0.5 $< $@
|
||||
endif
|
||||
else !HAVE_PDFXMLTEX
|
||||
pdf:
|
||||
ps:
|
||||
endif !HAVE_PDFXMLTEX
|
||||
|
||||
$(manualname)/images:
|
||||
@if [ -d $(manualname) ] ; then \
|
||||
if [ -d images ] ; then \
|
||||
ln -sf ../images $(manualname)/images ;\
|
||||
fi \
|
||||
fi
|
||||
else !HAVE_FIG2DEV_PDF
|
||||
pdf:
|
||||
ps:
|
||||
endif !HAVE_FIG2DEV_PDF
|
||||
|
||||
htmldocs: $(manualname)/$(htmlname) $(manualname)/images
|
||||
pdfdocs: $(PDFFILES)
|
||||
psdocs: $(PSFILES)
|
||||
else !HAVE_XSLTPROC
|
||||
html:
|
||||
ps:
|
||||
pdf:
|
||||
endif !HAVE_XSLTPROC
|
||||
|
||||
# Data to install, in the usual automake way
|
||||
docdatadir = $(datadir)/gstreamer
|
||||
docdata_DATA = $(PDFFILES) $(PSFILES)
|
||||
$(DOC).fo: $(XML) $(PDFS) $(XSLFO) $(XSLFOMODS)
|
||||
cp magic-pdf magic
|
||||
xsltproc $(XSLFO) $(MAIN) > $@-t
|
||||
mv -f $@-t $@
|
||||
|
||||
htmlinst: htmldocs
|
||||
@if [ -r $(manualname)/$(htmlname) ] ; then \
|
||||
echo "Installing $(manualname)" ; \
|
||||
$(mkinstalldirs) $(DESTDIR)$(docdatadir)/$(manualname) ; \
|
||||
$(mkinstalldirs) $(DESTDIR)$(docdatadir)/$(manualname)/images ; \
|
||||
$(INSTALL_DATA) $(manualname)/*.html $(DESTDIR)$(docdatadir)/$(manualname) ; \
|
||||
for a in "x" $(png_files); do \
|
||||
if [ "x$$a" != "xx" ] ; then \
|
||||
if [ -r $$a ] ; then \
|
||||
$(INSTALL_DATA) $$a $(DESTDIR)$(docdatadir)/$(manualname)/images ; \
|
||||
fi; fi; done \
|
||||
else \
|
||||
if [ -r $(srcdir)/$(manualname)/$(htmlname) ] ; then \
|
||||
echo "Installing $(srcdir)/$(manualname)" ; \
|
||||
$(mkinstalldirs) $(DESTDIR)$(docdatadir)/$(manualname) ; \
|
||||
$(mkinstalldirs) $(DESTDIR)$(docdatadir)/$(manualname)/images ; \
|
||||
$(INSTALL_DATA) $(srcdir)/$(manualname)/*.html $(DESTDIR)$(docdatadir)/$(manualname) ; \
|
||||
for a in "x" $(png_files); do \
|
||||
if [ "x$$a" != "xx" ] ; then \
|
||||
if [ -r $$a ] ; then \
|
||||
$(INSTALL_DATA) $$a $(DESTDIR)$(docdatadir)/$(manualname)/images ; \
|
||||
fi; fi; done \
|
||||
else \
|
||||
echo "NOT installing HTML documentation: not present, and can't generate" ; \
|
||||
fi \
|
||||
fi
|
||||
$(DOC).pdf: $(DOC).fo
|
||||
pdfxmltex $<
|
||||
pdfxmltex $<
|
||||
|
||||
htmluninst:
|
||||
$(RM) -rf $(DESTDIR)$(docdatadir)/$(manualname)
|
||||
$(DOC).ps: $(DOC).pdf
|
||||
pdftops $< $@
|
||||
|
||||
all-local: htmldocs pdfdocs psdocs
|
||||
clean-local:
|
||||
$(RM) -rf $(manualname)/ $(manualname).junk/ images/*.eps images/*.png *.eps *.png *.ps *.pdf *.aux *.dvi *.log *.tex DBTOHTML_OUTPUT_DIR*
|
||||
install-data-local: htmlinst
|
||||
uninstall-local: htmluninst
|
||||
$(DOC): $(XML) $(PNGS) $(XSLHTML) $(XSLHTMLMODS)
|
||||
-$(RM) *.html
|
||||
-$(RM) -r $@
|
||||
mkdir $@
|
||||
cp magic-png magic
|
||||
xsltproc $(XSLHTML) $(MAIN)
|
||||
mv *.html $@
|
||||
cp -a $(STYLESHEET_IMAGES) $@/stylesheet-images
|
||||
cp $(CSS) $@
|
||||
test "x$(PNGS)" != "x" && mkdir $@/images && cp $(PNGS) $@/images || true
|
||||
|
||||
builddate:
|
||||
echo -n $$(date "+%e %B %Y") > $@
|
||||
|
||||
clean:
|
||||
-$(RM) -f *.log *.dvi *.aux *.tex *.out *-t
|
||||
-$(RM) -f $(PNGS) $(PDFS) builddate *.html
|
||||
-$(RM) -rf $(DOC) $(DOC).ps $(DOC).pdf $(DOC).fo
|
||||
|
||||
distclean: clean
|
||||
-$(RM) -f *~ $(DOC).tar.gz docbook.tar.gz
|
||||
# -$(RM) -r docbook
|
||||
|
||||
$(DOC).tar.gz: distclean
|
||||
(cd ..; tar zcf /tmp/$(DOC).tar.gz $(DOC) )
|
||||
mv /tmp/$(DOC).tar.gz .
|
||||
|
||||
#docbook: $(DOC).tar.gz all
|
||||
# -$(RM) -r $@
|
||||
# mkdir $@
|
||||
# cp $(DOC).tar.gz $(DOC).ps $(DOC).pdf $@
|
||||
# tar cf - $(DOC) | (cd $@; tar xf -)
|
||||
|
||||
#docbook.tar.gz: docbook
|
||||
# tar zcf docbook.tar.gz docbook
|
||||
|
||||
# Make png from xfig
|
||||
%.png: %.fig
|
||||
fig2dev -Lpng $< $@
|
||||
|
||||
# Make pdf from xfig
|
||||
%.pdf: %.fig
|
||||
fig2dev -Lpdf $< $@
|
||||
|
||||
.PHONY: distclean clean all builddate
|
||||
|
|
11
docs/xsl/admon.xsl
Normal file
11
docs/xsl/admon.xsl
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
version='1.0'>
|
||||
|
||||
<!-- Turn on admonition graphics. -->
|
||||
<xsl:param name="admon.graphics" select="'1'"/>
|
||||
<xsl:param name="admon.graphics.path" select="'stylesheet-images/'"/>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
10
docs/xsl/css.xsl
Normal file
10
docs/xsl/css.xsl
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
version='1.0'>
|
||||
|
||||
<!-- Use an HTML CSS stylesheet. -->
|
||||
<xsl:param name="html.stylesheet" select="'base.css'"/>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
11
docs/xsl/fileext.xsl
Normal file
11
docs/xsl/fileext.xsl
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
version='1.0'>
|
||||
|
||||
<!-- This sets the extension for HTML files to ".html". -->
|
||||
<!-- (The stylesheet's default for XHTML files is ".xhtm".) -->
|
||||
<xsl:param name="html.ext" select="'.html'"/>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
16
docs/xsl/fo.xsl
Normal file
16
docs/xsl/fo.xsl
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version='1.0'
|
||||
xmlns="http://www.w3.org/TR/xhtml1/transitional"
|
||||
exclude-result-prefixes="#default">
|
||||
|
||||
<!-- This file is for customizing the default XSL stylesheets. -->
|
||||
<!-- We include them here (this one is for print output): -->
|
||||
<xsl:import
|
||||
href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/>
|
||||
|
||||
<!-- .. and customize them here: -->
|
||||
<xsl:include href="ulink.xsl"/>
|
||||
<xsl:include href="keycombo.xsl"/>
|
||||
|
||||
</xsl:stylesheet>
|
18
docs/xsl/html.xsl
Normal file
18
docs/xsl/html.xsl
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version='1.0'
|
||||
xmlns="http://www.w3.org/TR/xhtml1/transitional"
|
||||
exclude-result-prefixes="#default">
|
||||
|
||||
<!-- This file is for customizing the default XSL stylesheets. -->
|
||||
<!-- We include them here (this one is for HTML output): -->
|
||||
<xsl:import
|
||||
href="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl"/>
|
||||
|
||||
<!-- .. and customize them here: -->
|
||||
<xsl:include href="fileext.xsl"/>
|
||||
<xsl:include href="keycombo.xsl"/>
|
||||
<xsl:include href="admon.xsl"/>
|
||||
<xsl:include href="css.xsl"/>
|
||||
|
||||
</xsl:stylesheet>
|
26
docs/xsl/keycombo.xsl
Normal file
26
docs/xsl/keycombo.xsl
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
version='1.0'>
|
||||
|
||||
<!-- There is a bug in docbook-xsl-1.45; work around it here. -->
|
||||
<!-- Also change it slightly for emacs key descriptions. -->
|
||||
<xsl:template match="keycombo">
|
||||
<xsl:variable name="action" select="@action"/>
|
||||
<xsl:variable name="joinchar">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$action='seq'"><xsl:text> </xsl:text></xsl:when>
|
||||
<xsl:when test="$action='simul'">-</xsl:when>
|
||||
<xsl:otherwise>-</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:for-each select="./*">
|
||||
<xsl:if test="position()>1">
|
||||
<xsl:value-of select="$joinchar"/>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="."/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
32
docs/xsl/ulink.xsl
Normal file
32
docs/xsl/ulink.xsl
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:fo="http://www.w3.org/1999/XSL/Format"
|
||||
version='1.0'>
|
||||
|
||||
<!-- This alters the rendering of URLs. Let's follow RFC 2396 -->
|
||||
<!-- guidelines. -->
|
||||
<xsl:template match="ulink">
|
||||
<fo:basic-link external-destination="{@url}"
|
||||
xsl:use-attribute-sets="xref.properties">
|
||||
<xsl:choose>
|
||||
<xsl:when test="count(child::node())=0">
|
||||
<xsl:text><</xsl:text>
|
||||
<xsl:value-of select="@url"/>
|
||||
<xsl:text>></xsl:text>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</fo:basic-link>
|
||||
<xsl:if test="count(child::node()) != 0">
|
||||
<fo:inline hyphenate="false">
|
||||
<xsl:text> at <</xsl:text>
|
||||
<xsl:value-of select="@url"/>
|
||||
<xsl:text>></xsl:text>
|
||||
</fo:inline>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
Loading…
Reference in a new issue