Moved "Filter Writer's Guide" to "Plugin Writer's Guide". Divided existing info from old guide into several files, on...

Original commit message from CVS:
Moved "Filter Writer's Guide" to "Plugin Writer's Guide". Divided existing info
from old guide into several files, one per chapter. The guide still needs much
work ...
This commit is contained in:
Leif Johnson 2002-09-27 18:34:33 +00:00
parent cc5f591c17
commit 622a80da54
34 changed files with 2067 additions and 2 deletions

View file

@ -5,8 +5,8 @@ else
SUBDIRS_PLUGINS =
endif
SUBDIRS = manual fwg gst libs $(SUBDIRS_PLUGINS) devhelp
DIST_SUBDIRS = manual fwg gst libs plugins xsl devhelp
SUBDIRS = manual pwg gst libs $(SUBDIRS_PLUGINS) devhelp
DIST_SUBDIRS = manual pwg gst libs plugins xsl devhelp
EXTRA_DIST = slides manuals.mak

13
docs/pwg/.gitignore vendored Normal file
View file

@ -0,0 +1,13 @@
Makefile
Makefile.in
*.bak
.deps
images
gst-plugin-writers-guide
gst-plugin-writers-guide.pdf
gst-plugin-writers-guide.ps
gst-plugin-writers-guide.dvi
gst-plugin-writers-guide.tex
gst-plugin-writers-guide.log
gst-plugin-writers-guide.aux
gst-plugin-writers-guide.junk

18
docs/pwg/Makefile.am Normal file
View file

@ -0,0 +1,18 @@
DOC=gst-plugin-writers-guide
MAIN=$(DOC).xml
XML=$(wildcard *.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= # $(wildcard *.fig) (uncomment when pngs are added)
PNGS=$(FIGS:.fig=.png)
PDFS=$(FIGS:.fig=.pdf)
SRC=$(XML)
CSS=base.css
EXTRA_DIST = $(XML) $(FIGS) $(CSS) magic-png magic-pdf
include $(srcdir)/../manuals.mak

View file

View file

@ -0,0 +1,481 @@
<!-- ############ chapter ############# -->
<chapter id="cha-dparams">
<title>Supporting Dynamic Parameters</title>
<para>
Sometimes object properties are not powerful enough to control the
parameters that affect the behaviour of your element. When this is the case
you can expose these parameters as Dynamic Parameters which can be
manipulated by any Dynamic Parameters aware application.
</para>
<para>
Throughout this section, the term <emphasis>dparams</emphasis> will be used
as an abbreviation for "Dynamic Parameters".
</para>
<sect1 id="sect-dparams-compare">
<title>Comparing Dynamic Parameters with GObject Properties</title>
<para>
Your first exposure to dparams may be to convert an existing element from
using object properties to using dparams. The following table gives an
overview of the difference between these approaches. The significance of
these differences should become apparent later on.
</para>
<informaltable frame="all">
<tgroup cols="3">
<thead>
<row>
<entry></entry>
<entry>Object Properties</entry>
<entry>Dynamic Parameters</entry>
</row>
</thead>
<tbody>
<row>
<entry><emphasis>Parameter definition</emphasis></entry>
<entry>Class level at compile time</entry>
<entry>Any level at run time</entry>
</row>
<row>
<entry><emphasis>Getting and setting</emphasis></entry>
<entry>Implemented by element subclass as functions</entry>
<entry>Handled entirely by dparams subsystem</entry>
</row>
<row>
<entry><emphasis>Extra objects required</emphasis></entry>
<entry>None - all functionality is derived from base GObject</entry>
<entry>Element needs to create and store a <filename>GstDParamManager</filename> at object creation</entry>
</row>
<row>
<entry><emphasis>Frequency and resolution of updates</emphasis></entry>
<entry>Object properties will only be updated between calls to _get, _chain or _loop</entry>
<entry>dparams can be updated at any rate independant of calls to _get, _chain or _loop up to sample-level accuracy</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect1>
</chapter>
<chapter id="cha-dparam-start">
<title>Getting Started</title>
<para>
The dparams subsystem is contained within the
<filename>gstcontrol</filename> library. You need to include the header in
your element's source file:
</para>
<programlisting>
#include &lt;gst/control/control.h&gt;
</programlisting>
<para>
Even though the <filename>gstcontrol</filename> library may be linked into
the host application, you should make sure it is loaded in your
<filename>plugin_init</filename> function:
</para>
<programlisting>
static gboolean
plugin_init (GModule *module, GstPlugin *plugin)
{
...
/* load dparam support library */
if (!gst_library_load ("gstcontrol"))
{
gst_info ("example: could not load support library: 'gstcontrol'\n");
return FALSE;
}
...
}
</programlisting>
<para>
You need to store an instance of <filename>GstDParamManager</filename> in
your element's struct:
</para>
<programlisting>
struct _GstExample {
GstElement element;
...
GstDParamManager *dpman;
...
};
</programlisting>
<para>
The <filename>GstDParamManager</filename> can be initialised in your
element's init function:
</para>
<programlisting>
static void
gst_example_init (GstExample *example)
{
...
example-&gt;dpman = gst_dpman_new ("example_dpman", GST_ELEMENT(example));
...
}
</programlisting>
</chapter>
<chapter id="cha-dparam-define">
<title>Defining Parameter Specificiations</title>
<para>
You can define the dparams you need anywhere within your element but will
usually need to do so in only a couple of places:
<itemizedlist>
<listitem>
In the element <filename>init</filename> function, just after the call
to <filename>gst_dpman_new</filename>
</listitem>
<listitem>
Whenever a new pad is created so that parameters can affect data going
into or out of a specific pad. An example of this would be a mixer
element where a seperate volume parameter is needed on every pad.
</listitem>
</itemizedlist>
</para>
<para>
There are three different ways the dparams subsystem can pass parameters
into your element. Which one you use will depend on how that parameter is
used within your element. Each of these methods has its own function to
define a required dparam:
<itemizedlist>
<listitem><filename>gst_dpman_add_required_dparam_direct</filename></listitem>
<listitem><filename>gst_dpman_add_required_dparam_callback</filename></listitem>
<listitem><filename>gst_dpman_add_required_dparam_array</filename></listitem>
</itemizedlist>
These functions will return TRUE if the required dparam was added
successfully.
</para>
<para>
The following function will be used as an example.
<programlisting>
gboolean
gst_dpman_add_required_dparam_direct (GstDParamManager *dpman,
GParamSpec *param_spec,
gboolean is_log,
gboolean is_rate,
gpointer update_data)
</programlisting>
The common parameters to these functions are:
<itemizedlist>
<listitem>
<filename>GstDParamManager *dpman</filename> the element's dparam
manager
</listitem>
<listitem>
<filename>GParamSpec *param_spec</filename> the param spec which defines
the required dparam
</listitem>
<listitem>
<filename>gboolean is_log</filename> whether this dparam value should be
interpreted on a log scale (such as a frequency or a decibel value)
</listitem>
<listitem>
<filename>gboolean is_rate</filename> whether this dparam value is a
proportion of the sample rate. For example with a sample rate of 44100,
0.5 would be 22050 Hz and 0.25 would be 11025 Hz.
</listitem>
</itemizedlist>
</para>
<sect2 id="sect-dparam-direct">
<title>Direct Method</title>
<para>
This method is the simplest and has the lowest overhead for parameters
which change less frequently than the sample rate. First you need
somewhere to store the parameter - this will usually be in your element's
stuct.
</para>
<programlisting>
struct _GstExample {
GstElement element;
...
GstDParamManager *dpman;
gfloat volume;
...
};
</programlisting>
<para>
Then to define the required dparam just call
<filename>gst_dpman_add_required_dparam_direct</filename> and pass in the
location of the parameter to change. In this case the location is
<filename>&amp;(example-&gt;volume)</filename>.
</para>
<programlisting>
gst_dpman_add_required_dparam_direct (
example-&gt;dpman,
g_param_spec_float("volume","Volume","Volume of the audio",
0.0, 1.0, 0.8, G_PARAM_READWRITE),
FALSE,
FALSE,
&amp;(example-&gt;volume)
);
</programlisting>
<para>
You can now use <filename>example-&gt;volume</filename> anywhere in your
element knowing that it will always contain the correct value to use.
</para>
</sect2>
<sect2 id="sect-dparam-callback">
<title>Callback Method</title>
<para>
This should be used if the you have other values to calculate whenever a
parameter changes. If you used the direct method you wouldn't know if a
parameter had changed so you would have to recalculate the other values
every time you needed them. By using the callback method, other values
only have to be recalculated when the dparam value actually changes.
</para>
<para>
The following code illustrates an instance where you might want to use the
callback method. If you had a volume dparam which was represented by a
gfloat number, your element may only deal with integer arithmatic. The
callback could be used to calculate the integer scaler when the volume
changes. First you will need somewhere to store these values.
</para>
<programlisting>
struct _GstExample {
GstElement element;
...
GstDParamManager *dpman;
gfloat volume_f;
gint volume_i;
...
};
</programlisting>
<para>
When the required dparam is defined, the callback function
<filename>gst_example_update_volume</filename> and some user data (which
in this case is our element instance) is passed in to the call to
<filename>gst_dpman_add_required_dparam_callback</filename>.
</para>
<programlisting>
gst_dpman_add_required_dparam_callback (
example-&gt;dpman,
g_param_spec_float("volume","Volume","Volume of the audio",
0.0, 1.0, 0.8, G_PARAM_READWRITE),
FALSE,
FALSE,
gst_example_update_volume,
example
);
</programlisting>
<para>
The callback function needs to conform to this signiture
</para>
<programlisting>
typedef void (*GstDPMUpdateFunction) (GValue *value, gpointer data);
</programlisting>
<para>
In our example the callback function looks like this
</para>
<programlisting>
static void
gst_example_update_volume(GValue *value, gpointer data)
{
GstExample *example = (GstExample*)data;
g_return_if_fail(GST_IS_EXAMPLE(example));
example-&gt;volume_f = g_value_get_float(value);
example-&gt;volume_i = example-&gt;volume_f * 8192;
}
</programlisting>
<para>
Now <filename>example-&gt;volume_i</filename> can be used elsewhere and it
will always contain the correct value.
</para>
</sect2>
<sect2 id="sect-dparam-array">
<title>Array Method</title>
<para>
This method is quite different from the other two. It could be thought of
as a specialised method which should only be used if you need the
advantages that it provides. Instead of giving the element a single value
it provides an array of values where each item in the array corresponds to
a sample of audio in your buffer. There are a couple of reasons why this
might be useful.
</para>
<itemizedlist>
<listitem>
Certain optimisations may be possible since you can iterate over your
dparams array and your buffer data together.
</listitem>
<listitem>
Some dparams may be able to interpolate changing values at the sample
rate. This would allow the array to contain very smoothly changing
values which may be required for the stability and quality of some DSP
algorithms.
</listitem>
</itemizedlist>
<para>
The array method is currently the least mature of the three methods and is
not yet ready to be used in elements, but plugin writers should be aware
of its existance for the future.
</para>
</sect2>
</chapter>
<chapter id="cha-dparam-loop">
<title>The Data Processing Loop</title>
<para>
This is the most critical aspect of the dparams subsystem as it relates to
elements. In a traditional audio processing loop, a <filename>for</filename>
loop will usually iterate over each sample in the buffer, processing one
sample at a time until the buffer is finished. A simplified loop with no
error checking might look something like this.
</para>
<programlisting>
static void
example_chain (GstPad *pad, GstBuffer *buf)
{
...
gfloat *float_data;
int j;
GstExample *example = GST_EXAMPLE(GST_OBJECT_PARENT (pad));
int num_samples = GST_BUFFER_SIZE(buf)/sizeof(gfloat);
float_data = (gfloat *)GST_BUFFER_DATA(buf);
...
for (j = 0; j &lt; num_samples; j++) {
float_data[j] *= example-&gt;volume;
}
...
}
</programlisting>
<para>
To make this dparams aware, a couple of changes are needed.
</para>
<programlisting>
static void
example_chain (GstPad *pad, GstBuffer *buf)
{
...
int j = 0;
GstExample *example = GST_EXAMPLE(GST_OBJECT_PARENT (pad));
int num_samples = GST_BUFFER_SIZE(buf)/sizeof(gfloat);
gfloat *float_data = (gfloat *)GST_BUFFER_DATA(buf);
int frame_countdown = GST_DPMAN_PREPROCESS(example-&gt;dpman, num_samples, GST_BUFFER_TIMESTAMP(buf));
...
while (GST_DPMAN_PROCESS_COUNTDOWN(example-&gt;dpman, frame_countdown, j)) {
float_data[j++] *= example-&gt;volume;
}
...
}
</programlisting>
<para>
The biggest changes here are 2 new macros,
<filename>GST_DPMAN_PREPROCESS</filename> and
<filename>GST_DPMAN_PROCESS_COUNTDOWN</filename>. You will also notice that
the for loop has become a while loop.
<filename>GST_DPMAN_PROCESS_COUNTDOWN</filename> is called as the condition
for the while loop so that any required dparams can be updated in the middle
of a buffer if required. This is because one of the required behaviours of
dparams is that they can be <emphasis>sample accurate</emphasis>. This means
that parameters change at the exact timestamp that they are supposed to -
not after the buffer has finished being processed.
</para>
<para>
It may be alarming to see a macro as the condition for a while loop, but it
is actually very efficient. The macro expands to the following.
</para>
<programlisting>
#define GST_DPMAN_PROCESS_COUNTDOWN(dpman, frame_countdown, frame_count) \
(frame_countdown-- || \
(frame_countdown = GST_DPMAN_PROCESS(dpman, frame_count)))
</programlisting>
<para>
So as long as <filename>frame_countdown</filename> is greater than 0,
<filename>GST_DPMAN_PROCESS</filename> will not be called at all. Also in
many cases, <filename>GST_DPMAN_PROCESS</filename> will do nothing and
simply return 0, meaning that there is no more data in the buffer to
process.
</para>
<para>
The macro <filename>GST_DPMAN_PREPROCESS</filename> will do the following:
<itemizedlist>
<listitem>
Update any dparams which are due to be updated.
</listitem>
<listitem>
Calculate how many samples should be processed before the next required
update
</listitem>
<listitem>
Return the number of samples until next update, or the number of samples
in the buffer - whichever is less.
</listitem>
</itemizedlist>
In fact <filename>GST_DPMAN_PROCESS</filename> may do the same things as
<filename>GST_DPMAN_PREPROCESS</filename> depending on the mode that the
dparam manager is running in (see below).
</para>
<sect2 id="sect-dparam-modes">
<title>DParam Manager Modes</title>
<para>
A brief explanation of dparam manager modes might be useful here even
though it doesn't generally affect the way your element is written. There
are different ways media applications will be used which require that an
element's parameters be updated in differently. These include:
<itemizedlist>
<listitem>
<emphasis>Timelined</emphasis> - all parameter changes are known in
advance before the pipeline is run.
</listitem>
<listitem>
<emphasis>Realtime low-latency</emphasis> - Nothing is known ahead of
time about when a parameter might change. Changes need to be
propagated to the element as soon as possible.
</listitem>
</itemizedlist>
When a dparam-aware application gets the dparam manager for an element,
the first thing it will do is set the dparam manager mode. Current modes
are <filename>"synchronous"</filename> and
<filename>"asynchronous"</filename>.
</para>
<para>
If you are in a realtime low-latency situation then the
<filename>"synchronous"</filename> mode is appropriate. During
<filename>GST_DPMAN_PREPROCESS</filename> this mode will poll all dparams
for required updates and propagate them.
<filename>GST_DPMAN_PROCESS</filename> will do nothing in this mode. To
then achieve the desired latency, the size of the buffers needs to be
reduced so that the dparams will be polled for updates at the desired
frequency.
</para>
<para>
In a timelined situation, the <filename>"asynchronous"</filename> mode
will be required. This mode hasn't actually been implemented yet but will
be described anyway. The <filename>GST_DPMAN_PREPROCESS</filename> call
will precalculate when and how often each dparam needs to update for the
duration of the current buffer. From then on
<filename>GST_DPMAN_PROCESS</filename> will propagate the calculated
updates each time it is called until end of the buffer. If the application
is rendering to disk in non-realtime, the render could be sped up by
increasing the buffer size. In the <filename>"asynchronous"</filename>
mode this could be done without affecting the sample accuracy of the
parameter updates
</para>
</sect2>
<sect2 id="sect-dparam-audio-video">
<title>DParam Manager Modes</title>
<para>
All of the explanation so far has presumed that the buffer contains audio
data with many samples. Video should be regarded differently since a video
buffer often contains only 1 frame. In this case some of the complexity of
dparams isn't required but the other benefits still make it useful for
video parameters. If a buffer only contains one frame of video, only a
single call to <filename>GST_DPMAN_PREPROCESS</filename> should be
required. For more than one frame per buffer, treat it the same as the
audio case.
</para>
</sect2>
</chapter>

View file

View file

@ -0,0 +1,6 @@
<chapter id="cha-advanced-request">
<title>Request pads</title>
<para>
aka pushing and pulling
</para>
</chapter>

View file

@ -0,0 +1,27 @@
<chapter id="cha-loopbased-sched">
<title>How scheduling works</title>
<para>
aka pushing and pulling
</para>
</chapter>
<chapter id="cha-loopbased-loopfn">
<title>How a loopfunc works</title>
<para>
aka pulling and pushing
</para>
</chapter>
<chapter id="cha-loopbased-secnd">
<title>Adding a second output</title>
<para>
Identity is now a tee
</para>
</chapter>
<chapter id="cha-loopbased-modappl">
<title>Modifying the test application</title>
<para>
</para>
</chapter>

View file

@ -0,0 +1,88 @@
<!-- ############ chapter ############# -->
<chapter id="cha-building-types">
<title>Types and Properties</title>
<para>
There is a very large set of possible types that may be used to pass data
between elements. Indeed, each new element that is defined may use a new
data format (though unless at least one other element recognises that
format, it will be most likely be useless since nothing will be able to
link with it).
</para>
<para>
In order for types to be useful, and for systems like autopluggers to
work, it is neccessary that all elements agree on the type definitions,
and which properties are required for each type. The &GStreamer; framework
itself simply provides the ability to define types and parameters, but
does not fix the meaning of types and parameters, and does not enforce
standards on the creation of new types. This is a matter for a policy to
decide, not technical systems to enforce.
</para>
<para>
For now, the policy is simple:
<itemizedlist>
<listitem>
<para>
Do not create a new type if you could use one which already exists.
</para>
</listitem>
<listitem>
<para>
If creating a new type, discuss it first with the other &GStreamer;
developers, on at least one of: IRC, mailing lists, the &GStreamer;
wiki.
</para>
</listitem>
<listitem>
<para>
Try to ensure that the name for a new format is as unlikely to
conflict with anything else created already, and is not a more
generalised name than it should be. For example: "audio/compressed"
would be too generalised a name to represent audio data compressed
with an mp3 codec. Instead "audio/mp3" might be an appropriate name,
or "audio/compressed" could exist and have a property indicating the
type of compression used.
</para>
</listitem>
<listitem>
<para>
Ensure that, when you do create a new type, you specify it clearly,
and get it added to the list of known types so that other developers
can use the type correctly when writing their elements.
</para>
</listitem>
</itemizedlist>
</para>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-types-test" xreflabel="Building a Simple Format for Testing">
<title>Building a Simple Format for Testing</title>
<para>
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-types-mime" xreflabel="A Simple Mime Type">
<title>A Simple Mime Type</title>
<para>
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-types-properties" xreflabel="Type Properties">
<title>Type Properties</title>
<para>
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-types-typefind" xreflabel="Typefind Functions and Autoplugging">
<title>Typefind Functions and Autoplugging</title>
<para>
</para>
</sect1>
</chapter>

View file

@ -0,0 +1,14 @@
<chapter id="cha-checklist-filter">
<title>
Things to check when writing a filter
</title>
<para>
</para>
</chapter>
<chapter id="cha-checklist-srcsink">
<title>
Things to check when writing a source or sink
</title>
<para>
</para>
</chapter>

View file

0
docs/pwg/base.css Normal file
View file

View file

@ -0,0 +1,18 @@
<!-- ############ chapter ############# -->
<chapter id="cha-autopluggers">
<title>Autopluggers</title>
<para>
&GStreamer; has an autoplugging mechanism, which enables application writers
to simply specify start and end elements for a path, and the system will
then create a path which links these elements, in accordance with the type
information provided by the elements.
</para>
<para>
It is possible to devise many different schemes for generating such
pathways, perhaps to optimise based on special criteria, or with some
specific constraints. It is thus possible to define new autoplugging
systems, using the plugin system.
</para>
</chapter>

View file

@ -0,0 +1,32 @@
<!-- ############ chapter ############# -->
<chapter id="cha-buffers">
<title>Buffers</title>
<para>
Buffers are structures used to pass data between elements. All streams of
data are chopped up into chunks which are stored in buffers. Buffers can be
of any size, and also contain metadata indicating the type of data contained
in them. Buffers can be allocated by various different schemes, and may
either be passed on by elements or unreferenced (and the memory used by the
buffer freed).
</para>
<sect1 id="sect1-buffers-anatomy">
<title>Anatomy of a buffer</title>
<para>
</para>
</sect1>
<sect1 id="sect1-buffers-refcounts">
<title>Refcounts and mutability</title>
<para>
</para>
</sect1>
<sect1 id="sect1-buffers-metadata">
<title>Metadata</title>
<para>
</para>
</sect1>
</chapter>

View file

@ -0,0 +1,39 @@
<!-- ############ chapter ############# -->
<chapter id="cha-basics-elements">
<title>Elements, Plugins, and Filters</title>
<para>
In the &GStreamer; framework, a <emphasis>plugin</emphasis> is a specific
sort of code module that gets loaded when a program requests the
functionality that the plugin provides. A plugin is essentially a shared
code library.
<emphasis>Filters</emphasis> are an
important subset of plugins that process data, as opposed to producing or
consuming data. (Producers and consumers of data are called
<emphasis>source</emphasis> and <emphasis>sink</emphasis> plugins,
respectively.)
</para>
<para>
Elements are at the core of &GStreamer;. Without elements, &GStreamer; is
just a bunch of pipe fittings with nothing to connect. A large number of
elements (filters, sources, and sinks) ship with &GStreamer;, but extra
elements can also be written. The purpose of this guide is to help you
learn to create new elements.
</para>
<para>
An element may be constructed in several different ways, but all must
conform to the same basic rules. This guide presents one basic way to build
a filter elementA simple filter may be built with the
FilterFactory, where the only code that need be written is the actual filter
code. A more complex filter, or a source or sink, will need to be written
out fully for complete access to the features and performance possible with
&GStreamer;.
</para>
<para>
The implementation of a new element will be contained in a plugin: a single
plugin may contain the implementation of several elements, or just a single
one.
</para>
</chapter>

View file

@ -0,0 +1,8 @@
<!-- ############ chapter ############# -->
<chapter id="cha-events">
<title>Events</title>
<para>
</para>
</chapter>

View file

@ -0,0 +1,30 @@
<!-- ############ chapter ############# -->
<chapter id="cha-plugins">
<title>Plugins</title>
<para>
Extensions to &GStreamer; can be made using a plugin mechanism. This is used
extensively in &GStreamer; even if only the standard package is being used:
a few very basic functions reside in the core library, and all others are
implemented in plugins.
</para>
<para>
Plugins are only loaded when needed: a plugin registry is used to store the
details of the plugins so that it is not neccessary to load all plugins to
determine which are needed. This registry needs to be updated whenever a new
plugin is added to the system: see the <emphasis>gst-register</emphasis>
utility and the documentation in the &GstAppDevMan; for more details.
</para>
<para>
User extensions to &GStreamer; can be installed in the main plugin
directory, and will immediately be available for use in applications.
<emphasis>gst-register</emphasis> should be run to update the repository:
but the system should work correctly even if it hasn't been - it will just
take longer to load the correct plugin.
</para>
<para>
User specific plugin directories and registries will be available in future
versions of &GStreamer;.
</para>
</chapter>

15
docs/pwg/basics-types.xml Normal file
View file

@ -0,0 +1,15 @@
<!-- ############ chapter ############# -->
<chapter id="cha-typing">
<title>Typing and Properties</title>
<para>
A type system is used to ensure that the data passed between elements is in
a recognised format, and that the various parameters required to fully
specify that format match up correctly. Each connection that is made between
elements has a specified type. This is related, but different, to the
metadata in buffers which describes the type of data in that particular
buffer. See the next chapter of this document for details of the available
types.
</para>
</chapter>

View file

@ -0,0 +1,295 @@
<!-- ############ chapter ############# -->
<chapter id="cha-building-boiler" xreflabel="Constructing the Boilerplate">
<title>Constructing the Boilerplate</title>
<para>
In this chapter you will learn how to construct the bare minimum code for a
new plugin. Starting from ground zero, you will see how to get the
&GStreamer; template source. Then you will learn how to use a few simple
command line tools to copy and modify a template plugin and thus create your
new plugin. By the end of all this, you will have a functional audio filter
plugin that you can compile and test.
</para>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-boiler-source" xreflabel="Getting the Gstreamer Plugin Templates">
<title>Getting the Gstreamer Plugin Templates</title>
<para>
There are currently two ways to develop a new plugin for &GStreamer;: You
can write the entire plugin by hand, or you can copy an existing plugin
template and write the plugin code you need. The second method is by far
the simpler of the two, so the first method will not even be described
here.
</para>
<para>
The first step is to check out a copy of the
<filename>gst-template</filename> CVS module to get an important tool and
the source code template for the basic &GStreamer; plugin. To check out
the <filename>gst-template</filename> module, type the following two
commands on a command line:
</para>
<screen>
<prompt>shell $ </prompt><userinput>cvs -d:pserver:anonymous@cvs.gstreamer.sourceforge.net:/cvsroot/gstreamer login</userinput>
Logging in to :pserver:anonymous@cvs.gstreamer.sourceforge.net:2401/cvsroot/gstreamer
CVS password:
<prompt>shell $ </prompt><userinput>cvs -z3 -d:pserver:anonymous@cvs.gstreamer.sourceforge.net:/cvsroot/gstreamer co gst-template</userinput>
U gst-template/README
U gst-template/gst-app/AUTHORS
U gst-template/gst-app/ChangeLog
U gst-template/gst-app/Makefile.am
U gst-template/gst-app/NEWS
U gst-template/gst-app/README
U gst-template/gst-app/autogen.sh
U gst-template/gst-app/configure.ac
U gst-template/gst-app/src/Makefile.am
...
</screen>
<para>
After the first command, you will have to press <keycap>ENTER</keycap> to
log in to the CVS server. You might have to log in twice. The second
command will check out a series of files and directories into <filename
class="directory">./gst-template</filename>. The template you will be
using is in <filename
class="directory">./gst-template/gst-plugin/</filename> directory. You
should look over the files in that directory to get a general idea of the
structure of a source tree for a plugin.
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-boiler-filterstamp" xreflabel="Using Filterstamp">
<title>Using Filterstamp</title>
<para>
The first thing to do when making a new element is to specify some basic
details about it: what its name is, who wrote it, what version number it
is, etc. We also need to define an object to represent the element and to
store the data the element needs. These details are collectively known as
the <emphasis>boilerplate</emphasis>.
</para>
<para>
The standard way of defining the boilerplate is simply to write some code,
and fill in some structures. As mentioned in the previous section, the
easiest way to do this is to copy a template and add functionality
according to your needs. To help you do so, there is a script called
<command>pluginstamp.sh</command> in the <filename
class="directory">tools/</filename> directory of the
<filename>gst-template</filename> source tree that does exactly this.
</para>
<para>
To use <command>pluginstamp.sh</command>, first open up a terminal window.
Change to the <filename class="directory">gst-template</filename>
directory, and then run the <command>pluginstamp.sh</command> command. The
arguments to the <command>pluginstamp.sh</command> are:
</para>
<orderedlist>
<listitem>
<para>the name of the plugin, and</para>
</listitem>
<listitem>
<para>
the directory that should hold a new subdirectory for the source tree
of the plugin.
</para>
</listitem>
</orderedlist>
<para>
Note that capitalization is important for the name of the plugin. Under
some operating systems, capitalization is also important when specifying
directory names. For example, the
following commands create the ExampleFilter plugin based on the plugin
template and put the output files in a new directory called <filename
class="directory">~/src/examplefilter/</filename>:
</para>
<screen>
<prompt>shell $ </prompt><userinput>cd gst-template</userinput>
<prompt>shell $ </prompt><userinput>tools/pluginstamp.sh ExampleFilter ~/src</userinput>
</screen>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 name="sect1-boiler-examine" xreflabel="Examining the Basic Code">
<title>Examining the Basic Code</title>
<para>
First we will examine the code you would be likely to place in a header
file (although since the interface to the code is entirely defined by the
pluging system, and doesn't depend on reading a header file, this is not
crucial.)
The code here can be found in
<filename>examples/pwg/examplefilter/boiler/gstexamplefilter.h</filename>.
</para>
<example name="ex-boiler-examine-h" xreflabel="Example Plugin Header File">
<title>Example Plugin Header File</title>
<programlisting>
/* Definition of structure storing data for this element. */
typedef struct _GstExample GstExample;
struct _GstExample {
GstElement element;
GstPad *sinkpad,*srcpad;
gint8 active;
};
/* Standard definition defining a class for this element. */
typedef struct _GstExampleClass GstExampleClass;
struct _GstExampleClass {
GstElementClass parent_class;
};
/* Standard macros for defining types for this element. */
#define GST_TYPE_EXAMPLE \
(gst_example_get_type())
#define GST_EXAMPLE(obj) \
(GTK_CHECK_CAST((obj),GST_TYPE_EXAMPLE,GstExample))
#define GST_EXAMPLE_CLASS(klass) \
(GTK_CHECK_CLASS_CAST((klass),GST_TYPE_EXAMPLE,GstExample))
#define GST_IS_EXAMPLE(obj) \
(GTK_CHECK_TYPE((obj),GST_TYPE_EXAMPLE))
#define GST_IS_EXAMPLE_CLASS(obj) \
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EXAMPLE))
/* Standard function returning type information. */
GtkType gst_example_get_type(void);
</programlisting>
</example>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-boiler-filterfactory" xreflabel="Creating a Filter With FilterFactory">
<title>Creating a Filter With FilterFactory (Future)</title>
<para>
A plan for the future is to create a FilterFactory, to make the process of
making a new filter a simple process of specifying a few details, and
writing a small amount of code to perform the actual data processing.
Ideally, a FilterFactory would perform the tasks of boilerplate creation,
code functionality implementation, and filter registration.
</para>
<para>
Unfortunately, this has not yet been implemented. Even when someone
eventually does write a FilterFactory, this element will not be able to
cover all the possibilities available for filter writing. Thus, some
plugins will always need to be manually coded and registered.
</para>
<para>
Here is a rough outline of what is planned: You run the FilterFactory and
give the factory a list of appropriate function pointers and data
structures to define a filter. With a reasonable measure of preprocessor
magic, you just need to provide a name for the filter and definitions of
the functions and data structures desired. Then you call a macro from
within plugin_init() that registers the new filter. All the fluff that
goes into the definition of a filter is thus be hidden from view.
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-boiler-details">
<title>GstElementDetails</title>
<para>
The GstElementDetails structure gives a heirarchical type for the element,
a human-readable description of the element, as well as author and version
data. The entries are:
</para>
<itemizedlist>
<listitem><para>
A long, english, name for the element.
</para></listitem><listitem><para>
The type of the element, as a heirarchy. The heirarchy is defined by
specifying the top level category, followed by a "/", followed by the
next level category, etc. The type should be defined according to the
guidelines elsewhere in this document. (FIXME: write the guidelines, and
give a better reference to them)
</para></listitem><listitem><para>
A brief description of the purpose of the element.
</para></listitem><listitem><para>
The version number of the element. For elements in the main GStreamer
source code, this will often simply be VERSION, which is a macro defined
to be the version number of the current GStreamer version. The only
requirement, however, is that the version number should increase
monotonically.
</para>
<para>
Version numbers should be stored in major.minor.patch form: ie, 3
(decimal) numbers, separated by periods (.).
</para></listitem><listitem><para>
The name of the author of the element, optionally followed by a contact
email address in angle brackets.
</para></listitem><listitem><para>
The copyright details for the element.
</para></listitem>
</itemizedlist>
<para>
For example:
</para>
<programlisting>
static GstElementDetails example_details = {
"An example plugin",
"Example/FirstExample",
"Shows the basic structure of a plugin",
VERSION,
"your name &lt;your.name@your.isp&gt;",
"(C) 2001",
};
</programlisting>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-boiler-constructors">
<title>Constructor Functions</title>
<para>
Each element has two functions which are used for construction of an
element. These are the _class_init() function, which is used to initialise
the class (specifying what signals and arguments the class has and setting
up global state), and the _init() function, which is used to initialise a
specific instance of the class.
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-boiler-plugininit">
<title>The plugin_init function</title>
<para>
Once we have written code defining all the parts of the plugin, we need to
write the plugin_init() function. This is a special function, which is
called as soon as the plugin is loaded, and must return a pointer to a newly
allocated GstPlugin structure. This structure contains the details of all
the facilities provided by the plugin, and is the mechanism by which the
definitions are made available to the rest of the &GStreamer; system. Helper
functions are provided to help fill the structure: for future compatability
it is recommended that these functions are used, as documented below, rather
than attempting to access the structure directly.
</para>
<para>
Note that the information returned by the plugin_init() function will be
cached in a central registry. For this reason, it is important that the same
information is always returned by the function: for example, it must not
make element factories available based on runtime conditions. If an element
can only work in certain conditions (for example, if the soundcard is not
being used by some other process) this must be reflected by the element
being unable to enter the READY state if unavailable, rather than the plugin
attempting to deny existence of the plugin.
</para>
</sect1>
</chapter>

View file

@ -0,0 +1,8 @@
<!-- ############ chapter ############# -->
<chapter id="cha-building-chainfn">
<title>The chain function</title>
<para>
</para>
</chapter>

View file

@ -0,0 +1,9 @@
<!-- ############ chapter ############# -->
<chapter id="cha-building-pads">
<title>Specifying the pads</title>
<para>
</para>
</chapter>

View file

@ -0,0 +1,9 @@
<!-- ############ chapter ############# -->
<chapter id="cha-building-args" xreflabel="Adding Arguments">
<title>Adding Arguments</title>
<para>
Define arguments in enum.
</para>
</chapter>

View file

@ -0,0 +1,9 @@
<!-- ############ chapter ############# -->
<chapter id="cha-building-signals">
<title>Signals</title>
<para>
Define signals in enum.
</para>
</chapter>

View file

@ -0,0 +1,14 @@
<chapter id="cha-statemanage-states">
<title>
What are states?
</title>
<para>
</para>
</chapter>
<chapter id="cha-statemanage-filters">
<title>
Mangaging filter state
</title>
<para>
</para>
</chapter>

View file

@ -0,0 +1,25 @@
<chapter id="cha-testapp-init">
<title>Initialization</title>
<para>
</para>
</chapter>
<chapter id="cha-testapp-inst">
<title>Instantiating the plugins</title>
<para>
(NOTE: we really should have a debugging Sink)
</para>
</chapter>
<chapter id="cha-testapp-connect">
<title>Connecting the plugins</title>
<para>
</para>
</chapter>
<chapter id="cha-testapp-running">
<title>Running the pipeline</title>
<para>
</para>
</chapter>

View file

@ -0,0 +1,156 @@
<?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.xml">
<!ENTITY INTRO_PREFACE SYSTEM "intro_preface.xml">
<!ENTITY INTRO_BASICS SYSTEM "intro_basics.xml">
<!ENTITY BUILDING_BOILER SYSTEM "building_boiler.xml">
<!ENTITY BUILDING_PADS SYSTEM "building_pads.xml">
<!ENTITY BUILDING_CHAINFN SYSTEM "building_chainfn.xml">
<!ENTITY BUILDING_STATE SYSTEM "building_state.xml">
<!ENTITY BUILDING_PROPS SYSTEM "building_props.xml">
<!ENTITY BUILDING_SIGNALS SYSTEM "building_signals.xml">
<!ENTITY BUILDING_TESTAPP SYSTEM "building_testapp.xml">
<!ENTITY ADVANCED_SCHEDULING SYSTEM "advanced_scheduling.xml">
<!ENTITY ADVANCED_TYPES SYSTEM "advanced_types.xml">
<!ENTITY ADVANCED_REQUEST SYSTEM "advanced_request.xml">
<!ENTITY ADVANCED_CLOCK SYSTEM "advanced_clock.xml">
<!ENTITY ADVANCED_DPARAMS SYSTEM "advanced_dparams.xml">
<!ENTITY ADVANCED_MIDI SYSTEM "advanced_midi.xml">
<!ENTITY OTHER_SOURCE SYSTEM "other_source.xml">
<!ENTITY OTHER_SINK SYSTEM "other_sink.xml">
<!ENTITY OTHER_AUTOPLUGGER SYSTEM "other_autoplugger.xml">
<!ENTITY APPENDIX_CHECKLIST SYSTEM "appendix_checklist.xml">
<!ENTITY APPENDIX_PYTHON SYSTEM "appendix_python.xml">
<!ENTITY GStreamer "<application>GStreamer</application>">
<!ENTITY GstVersion "0.4.1">
<!ENTITY GstAppDevMan "<emphasis>GStreamer Application Development Manual</emphasis>">
<!ENTITY GstLibRef "<emphasis>GStreamer Library Reference</emphasis>">
]>
<book id="book-gst-plugin-writers-guide">
&TITLEPAGE;
<!-- ############# part ############### -->
<part id="part-introduction" xreflabel="Introduction">
<title>Introduction</title>
<partintro>
<para>
&GStreamer; is an exremely powerful and versatile framework for creating
streaming media applications. Many of the virtues of the &GStreamer;
framework come from its modularity: &GStreamer; can seamlessly
incorporate new plugin modules. But because modularity and power often
come at a cost of greater complexity (consider, for example, <ulink
type="http" url="http://www.omg.org/">CORBA</ulink>), writing new
plugins is not always easy.
</para>
<para>
This guide is intended to help you understand the &GStreamer; framework
so you can develop new plugins to extend &GStreamer;'s functionality.
This guide introduces most of the basic plugin writing issues in version
&GstVersion; of &GStreamer;. This guide presents most issues in the
context of an example audio filter plugin written in C. However, the
guide also addresses some issues involved in writing other types of
plugins, and the end of the guide also describes some of the Python
bindings for &GStreamer;.
</para>
</partintro>
&INTRO_PREFACE;
&INTRO_BASICS;
</part>
<!-- ############ part ############# -->
<part id="part-building" xreflabel="Building a Filter">
<title>Building a Filter</title>
<partintro>
<para>
You now have the neccessary concepts to build your first plugin. In this
part of the guide, you will learn how to apply these concepts to write a
simple audio filter plugin. The previous parts of the guide have
contained no explicit example code, perhaps making things a bit abstract
and difficult to understand. In contrast, this section will present both
applications and code by following the development of an example audio
filter plugin called <quote>ExampleFilter</quote>.
</para>
<para>
The example filter will begin with a single input pad and a single
output pad. The filter will, at first, simply pass data through without
modification. But by the end of this part of the guide, you will learn
to add some more interesting functionality, including properties and
signal handlers. And after reading the next part of the guide, <xref
linkend="part-advanced"/>, you will be able to add even more
functionality to your plugins.
</para>
<para>
The example code used in this part of the guide can be found in
<filename class="directory">examples/pwg/examplefilter/</filename> in
your &GStreamer; directory.
</para>
</partintro>
&BUILDING_BOILER;
&BUILDING_PADS;
&BUILDING_CHAINFN;
&BUILDING_STATE;
&BUILDING_PROPS;
&BUILDING_SIGNALS;
&BUILDING_TESTAPP;
</part>
<!-- ############ part ############# -->
<part id="part-advanced" xreflabel="Advanced Filter Concepts">
<title>Advanced Filter Concepts</title>
<partintro>
<para>
</para>
</partintro>
&ADVANCED_SCHEDULING;
&ADVANCED_TYPES;
&ADVANCED_REQUEST;
&ADVANCED_CLOCK;
&ADVANCED_DPARAMS;
&ADVANCED_MIDI;
</part>
<!-- ############ part ############# -->
<part id="part-other" xreflabel="Other Element Types">
<title>Other Element Types</title>
<partintro>
<para>
</para>
</partintro>
&OTHER_SOURCE;
&OTHER_SINK;
&OTHER_AUTOPLUGGER;
</part>
<!-- ############ part ############# -->
<part id="part-appendix" xreflabel="Appendices">
<title>Appendices</title>
<partintro>
<para>
</para>
</partintro>
&APPENDIX_CHECKLIST;
&APPENDIX_PYTHON;
</part>
</book>

472
docs/pwg/intro-basics.xml Normal file
View file

@ -0,0 +1,472 @@
<!-- ############ chapter ############# -->
<chapter id="cha-intro-basics" xreflabel="Basic Concepts">
<title>Basic Concepts</title>
<para>
This chapter of the guide introduces the basic concepts of &GStreamer;.
Understanding these concepts will help you see the issues involved in
extending &GStreamer;. Many of these concepts are explained in greater
detail in the &GstAppDevMan;. The basic concepts presented here serve mainly
to refresh your memory.
</para>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-basics-elements" xreflabel="Elements and Plugins">
<title>Elements and Plugins</title>
<para>
Elements are at the core of &GStreamer;. In the context of plugin
development, an <emphasis>element</emphasis> is an object derived from the
<classname>GstElement</classname> class. An element provides some sort of
functionality when connected with other elements. Without elements,
&GStreamer; is just a bunch of conceptual pipe fittings with nothing to
connect. A large number of elements ship with &GStreamer;, but extra
elements can also be written. The purpose of this guide is to help you
learn to create new elements, which are encapsulated in plugins as
described below.
</para>
<para>
A <emphasis>filter</emphasis> is an important type of element that
processes a stream of data, as opposed to producing or consuming streams
of data. Producers and consumers of data are called
<emphasis>source</emphasis> and <emphasis>sink</emphasis> elements,
respectively.
</para>
<para>
Just writing a new element is not entirely enough, however: You will need
to encapsulate your element in a plugin to enable &GStreamer; to use it. A
<emphasis>plugin</emphasis> is essentially a loadable block of code,
usually a shared object file or dynamically linked library. A single
plugin may contain the implementation of several elements, or just a
single one. For simplicity, this guide concentrates primarily on plugins
containing one filter type element.
</para>
<para>
The plugin mechanism is used everywhere in &GStreamer;, even if only the
standard package is being used. A few very basic functions reside in the
core library, and all others are implemented in plugins. A plugin registry
is used to store the details of the plugins in an XML file. This way, a
program using &GStreamer; does not have to load all plugins to determine
which are needed. Plugins are only loaded when their provided elements are
requested.
</para>
<para>
See the &GstLibRef; for the current implementation details of <ulink
type="http"
url="http://gstreamer.net/docs/0.4.0/gstreamer/gstelement.html"><classname>GstElement</classname></ulink>
and <ulink type="http"
url="http://gstreamer.net/docs/0.4.0/gstreamer/gstreamer-gstplugin.html"><classname>GstPlugin</classname></ulink>.
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-basics-pads" xreflabel="Pads">
<title>Pads</title>
<para>
<emphasis>Pads</emphasis> are used to negotiate connections and data flow
between elements in &GStreamer;. A pad can be viewed as a
<quote>place</quote> on an element where connections may be made with
other elements. Pads have specific data handling capabilities: That is, a
pad only knows how to give or receive certain types of data. Connections
are only allowed when the capabilities of two pads are compatible.
</para>
<para>
An analogy may be helpful here. A pad is similar to a plug or jack on a
physical device. Consider, for example, a home theater system consisting
of an amplifier, a DVD player, and a television. Connecting the DVD player
to the amplifier is allowed only because both devices have audio jacks,
and connecting the television to the DVD player is allowed because both
devices have compatible video jacks. Pads in &GStreamer; serve the same
purpose as the jacks in the home theater system.
</para>
<para>
See the &GstLibRef; for the current implementation details of a <ulink
type="http"
url="http://gstreamer.net/docs/0.4.0/gstreamer/gstreamer-gstpad.html"><classname>GstPad</classname></ulink>.
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-basics-buffers" xreflabel="Buffers">
<title>Buffers</title>
<para>
All streams of data in &GStreamer; are chopped up into chunks that are
passed from a source pad on one element to a sink pad on another element.
<emphasis>Buffers</emphasis> are structures used to hold these chunks of
data. Buffers can be of any size, theoretically. Buffers may contain any
sort of data that the two pads involved know how to handle: Normally, a
buffer contains a chunk of some sort of audio or video data that flows
from one element to another.
</para>
<para>
Buffers also contain metadata describing the buffer's contents. Some of
the important types of metadata are:
<itemizedlist>
<listitem>
<para>
A pointer to the buffer's data.
</para>
</listitem>
<listitem>
<para>
An integer indicating the size of the buffer's data.
</para>
</listitem>
<listitem>
<para>
A <classname>GstData</classname> object describing the type of the
buffer's data.
</para>
</listitem>
<listitem>
<para>
A reference count indicating the number of elements currently
holding a reference to the buffer. When the buffer reference count
falls to zero, the buffer will be unlinked, and its memory will be
freed in some sense (see the next part about <xref
linkend="sect2-buffers-bufferpools"/> for more details).
</para>
</listitem>
</itemizedlist>
</para>
<para>
See the &GstLibRef; for the current implementation details of a <ulink
type="http"
url="http://gstreamer.net/docs/0.4.0/gstreamer/gstreamer-gstbuffer.html"><classname>GstBuffer</classname></ulink>.
</para>
<sect2 id="sect2-buffers-bufferpools" xreflabel="Buffer Allocation and
Buffer Pools">
<title>Buffer Allocation and Buffer Pools</title>
<para>
Buffers can be allocated using various schemes, and they may either be
passed on by an element or unreferenced, thus freeing the memory used by
the buffer.
</para>
<para>
Normally, filter elements in &GStreamer; deal with a buffer in place,
meaning that they do not create or destroy buffers. Sometimes, however,
elements might need to alter the reference count of a buffer to copy or
destroy the buffer, or to create a new buffer. For the most part, this
guide does not deal with elements that alter a buffer's reference count,
but buffer referencing is an important concept to know.
</para>
</sect2>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-basics-types" xreflabel="Types and Properties">
<title>Types and Properties</title>
<para>
&GStreamer; uses a type system to ensure that the data passed between
elements is in a recognized format. The type system is also important for
ensuring that the parameters required to fully specify a format match up
correctly when connecting pads between elements. Each connection that is
made between elements has a specified type.
</para>
<!-- ############ sect2 ############# -->
<sect2 id="sect2-types-basictypes" xreflabel="Basic Types">
<title>The Basic Types</title>
<para>
&GStreamer; already supports many basic media types. Following is a
table of the basic types used for buffers in &GStreamer;. The table
contains the name ("mime type") and a description of the type, the
properties associated with the type, and the meaning of each property.
</para>
<table frame="all" id="table-basictypes" xreflabel="Table of Basic Types">
<title>Table of Basic Types</title>
<tgroup cols="6" align="left" colsep="1" rowsep="1">
<thead>
<row>
<entry>Mime Type</entry>
<entry>Description</entry>
<entry>Property</entry>
<entry>Property Type</entry>
<entry>Property Values</entry>
<entry>Property Description</entry>
</row>
</thead>
<tbody valign="top">
<!-- ############ type ############# -->
<row>
<entry morerows="10">audio/raw</entry>
<entry morerows="10">
Unstructured and uncompressed raw audio data.
</entry>
<entry>rate</entry>
<entry>integer</entry>
<entry>greater than 0</entry>
<entry>
The sample rate of the data, in samples per second.
</entry>
</row>
<row>
<entry>channels</entry>
<entry>integer</entry>
<entry>greater than 0</entry>
<entry>
The number of channels of audio data.
</entry>
</row>
<row>
<entry>format</entry>
<entry>string</entry>
<entry><quote>int</quote> or <quote>float</quote></entry>
<entry>
The format in which the audio data is passed.
</entry>
</row>
<row>
<entry>law</entry>
<entry>integer</entry>
<entry>0, 1, or 2</entry>
<entry>
(Valid only if the data is in integer format.) The law used to
describe the data. The value 0 indicates <quote>linear</quote>, 1
indicates <quote>mu&nbsp;law</quote>, and 2 indicates
<quote>A&nbsp;law</quote>.
</entry>
</row>
<row>
<entry>endianness</entry>
<entry>boolean</entry>
<entry>0 or 1</entry>
<entry>
(Valid only if the data is in integer format.) The order of bytes
in a sample. The value 0 means <quote>little-endian</quote> (bytes
are least significant first). The value 1 means
<quote>big-endian</quote> (most significant byte first).
</entry>
</row>
<row>
<entry>signed</entry>
<entry>boolean</entry>
<entry>0 or 1</entry>
<entry>
(Valid only if the data is in integer format.) Whether the samples
are signed or not.
</entry>
</row>
<row>
<entry>width</entry>
<entry>integer</entry>
<entry>greater than 0</entry>
<entry>
(Valid only if the data is in integer format.) The number of bits
per sample.
</entry>
</row>
<row>
<entry>depth</entry>
<entry>integer</entry>
<entry>greater than 0</entry>
<entry>
(Valid only if the data is in integer format.) The number of bits
used per sample. This must be less than or equal to the width: If
the depth is less than the width, the low bits are assumed to be
the ones used. For example, a width of 32 and a depth of 24 means
that each sample is stored in a 32 bit word, but only the low 24
bits are actually used.
</entry>
</row>
<row>
<entry>layout</entry>
<entry>string</entry>
<entry><quote>gfloat</quote></entry>
<entry>
(Valid only if the data is in float format.) A string representing
the way in which the floating point data is represented.
</entry>
</row>
<row>
<entry>intercept</entry>
<entry>float</entry>
<entry>any, normally 0</entry>
<entry>
(Valid only if the data is in float format.) A floating point
value representing the value that the signal
<quote>centers</quote> on.
</entry>
</row>
<row>
<entry>slope</entry>
<entry>float</entry>
<entry>any, normally 1.0</entry>
<entry>
(Valid only if the data is in float format.) A floating point
value representing how far the signal deviates from the intercept.
A slope of 1.0 and an intercept of 0.0 would mean an audio signal
with minimum and maximum values of -1.0 and 1.0. A slope of
0.5 and intercept of 0.5 would represent values in the range 0.0
to 1.0.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry morerows="4">audio/mp3</entry>
<entry morerows="4">
Audio data compressed using the mp3 encoding scheme.
</entry>
<entry>framed</entry>
<entry>boolean</entry>
<entry>0 or 1</entry>
<entry>
A true value indicates that each buffer contains exactly one
frame. A false value indicates that frames and buffers do not
necessarily match up.
</entry>
</row>
<row>
<entry>layer</entry>
<entry>integer</entry>
<entry>1, 2, or 3</entry>
<entry>
The compression scheme layer used to compress the data.
</entry>
</row>
<row>
<entry>bitrate</entry>
<entry>integer</entry>
<entry>greater than 0</entry>
<entry>
The bitrate, in kilobits per second. For VBR (variable bitrate)
mp3 data, this is the average bitrate.
</entry>
</row>
<row>
<entry>channels</entry>
<entry>integer</entry>
<entry>greater than 0</entry>
<entry>
The number of channels of audio data present.
</entry>
</row>
<row>
<entry>joint-stereo</entry>
<entry>boolean</entry>
<entry>0 or 1</entry>
<entry>
If true, this implies that stereo data is stored as a combined
signal and the difference between the signals, rather than as two
entirely separate signals. If true, the <quote>channels</quote>
attribute must not be zero.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry morerows="0">audio/x-ogg</entry>
<entry morerows="0">
Audio data compressed using the Ogg Vorbis encoding scheme.
</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
FIXME: There are currently no parameters defined for this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry morerows="2">video/raw</entry>
<entry morerows="2">
Raw video data.
</entry>
<entry>fourcc</entry>
<entry>FOURCC code</entry>
<entry></entry>
<entry>
A FOURCC code identifying the format in which this data is stored.
FOURCC (Four Character Code) is a simple system to allow
unambiguous identification of a video datastream format. See
<ulink url="http://www.webartz.com/fourcc/"
type="http">http://www.webartz.com/fourcc/</ulink>
</entry>
</row>
<row>
<entry>width</entry>
<entry>integer</entry>
<entry>greater than 0</entry>
<entry>
The number of pixels wide that each video frame is.
</entry>
</row>
<row>
<entry>height</entry>
<entry>integer</entry>
<entry>greater than 0</entry>
<entry>
The number of pixels high that each video frame is.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry morerows="0">video/mpeg</entry>
<entry morerows="0">
Video data compressed using an MPEG encoding scheme.
</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
FIXME: There are currently no parameters defined for this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry morerows="0">video/avi</entry>
<entry morerows="0">
Video data compressed using the AVI encoding scheme.
</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
FIXME: There are currently no parameters defined for this type.
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-basics-events" xreflabel="Events">
<title>Events</title>
<para>
Events are a special type of data in &GStreamer;.
<emphasis>Events</emphasis> indicate some sort of notable event that has
happened somewhere in an element's pipeline. Just like any other data
type, an event comes to an element through its pads. Events are contained
in a <classname>GstBuffer</classname>, so an event buffer will contain
only an event, not any other type of data.
</para>
<para>
See the &GstLibRef; for the current implementation details of a <ulink
type="http"
url="http://gstreamer.net/docs/0.4.0/gstreamer/gstreamer-gstevent.html"><classname>GstEvent</classname></ulink>.
</para>
</sect1>
</chapter>

192
docs/pwg/intro-preface.xml Normal file
View file

@ -0,0 +1,192 @@
<!-- ############ chapter ############# -->
<chapter id="cha-intro-preface" xreflabel="Preface">
<title>Preface</title>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-preface-who" xreflabel="Who Should Read This Guide?">
<title>Who Should Read This Guide?</title>
<para>
This guide explains how to write new modules for &GStreamer;. The guide is
relevant to several groups of people:
</para>
<itemizedlist>
<listitem>
<para>
Anyone who wants to add support for new ways of processing data in
&GStreamer;. For example, a person in this group might want to create
a new data format converter, a new visualization tool, or a new
decoder or encoder.
</para>
</listitem>
<listitem>
<para>
Anyone who wants to add support for new input and output devices. For
example, people in this group might want to add the ability to write
to a new video output system or read data from a digital camera or
special microphone.
</para>
</listitem>
<listitem>
<para>
Anyone who wants to extend &GStreamer; in any way. You need to have an
understanding of how the plugin system works before you can understand
the constraints that the plugin system places on the rest of the code.
Also, you might be surprised after reading this at how much can be
done with plugins.
</para>
</listitem>
</itemizedlist>
<para>
This guide is not relevant to you if you only want to use the existing
functionality of &GStreamer;, or if you just want to use an application
that uses &GStreamer;. If you are only interested in using existing
plugins to write a new application &mdash; and there are quite a lot of
plugins already &mdash; you might want to check the &GstAppDevMan;. If you
are just trying to get help with a &GStreamer; application, then you
should check with the user manual for that particular application.
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-preface-reading" xreflabel="Preliminary Reading">
<title>Preliminary Reading</title>
<para>
This guide assumes that you are somewhat familiar with the basic workings
of &GStreamer;. For a gentle introduction to programming concepts in
&GStreamer;, you may wish to read the &GstAppDevMan; first. Also check out
the documentation available on the <ulink type="http"
url="http://gstreamer.net/docs/">&GStreamer; web site</ulink>,
particularly the documents available in the <ulink type="http"
url="http://gstreamer.net/wiki/">&GStreamer; wiki</ulink>.
</para>
<para>
Since &GStreamer; adheres to the GObject programming model, this guide
also assumes that you understand the basics of <ulink type="http"
url="http://developer.gnome.org/doc/API/2.0/gobject/index.html">GObject</ulink>
programming. There are several good introductions to the GObject library,
including the <emphasis><ulink type="http"
url="http://www.gtk.org/tutorial/">GTK+ Tutorial</ulink></emphasis>.
</para>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-preface-structure" xreflabel="Structure of This Guide">
<title>Structure of This Guide</title>
<para>
To help you navigate through this guide, it is divided into several large
parts. Each part addresses a particular broad topic concerning &GStreamer;
plugin development. The parts of this guide are laid out in the following
order:
</para>
<itemizedlist>
<listitem>
<para>
<guilabel><xref linkend="part-building"/></guilabel> &mdash;
Introduction to the structure of a plugin. This part covers all the
different steps you have to perform to build a basic audio filter
plugin. The discussion begins by giving examples of generating the
basic structures with <xref linkend="cha-building-boiler"/>. Then you
will learn how to write the code to get a basic filter plugin working.
Several chapters cover these concepts, including <xref
linkend="cha-building-types"/>, <xref linkend="cha-building-pads"/>,
<xref linkend="cha-building-chainfn"/>, and <xref
linkend="cha-building-state"/>.
</para>
<para>
After you have finished these chapters, you will have a working
plugin, but your new plugin might not have all the functionality you
need. To provide some standard functionality, you will learn how to
add features to a filter in the chapters on <xref
linkend="cha-building-props"/> and <xref
linkend="cha-building-signals"/>. Finally, you will learn to test your
new plugin in <xref linkend="cha-building-testapp"/>.
</para>
</listitem>
<listitem>
<para>
<guilabel><xref linkend="part-advanced"/></guilabel> &mdash;
Information on advanced features of &GStreamer; plugin development.
After learning about the basic steps, you should be able to create a
functional audio or video filter plugin with some nice features.
However, &GStreamer; offers more for plugin writers. This part of the
guide includes chapters on <xref linkend="cha-advanced-scheduling"/>,
<xref linkend="cha-advanced-request"/>, <xref
linkend="cha-advanced-clock"/>, <xref
linkend="cha-advanced-dparams"/>, and <xref
linkend="cha-advanced-midi"/>. Since these features are more advanced,
the chapters can basically be read in any order, as you need the
features for your custom plugins.
</para>
</listitem>
<listitem>
<para>
<guilabel><xref linkend="part-other"/></guilabel> &mdash; Explanation
of writing source and sink plugins. Although the concepts introduced
in the two previous parts of this guide apply to filter plugins, many
of the concepts apply equally to source and sink plugins. This part
will take a look at creating source and sink type plugins for
&GStreamer; in the chapters on <xref linkend="cha-other-source"/> and
<xref linkend="cha-other-sink"/>. The chapter on <xref
linkend="cha-other-autoplugger"/> describes writing autoplugger
plugins.
</para>
</listitem>
<listitem>
<para>
<guilabel><xref linkend="part-appendix"/></guilabel> &mdash; The
appendices contain some information that stubbornly refused to fit
cleanly in other sections of this guide, like the <xref
linkend="cha-appendix-checklist"/> and <xref
linkend="cha-appendix-python"/>. FIXME: organize better.
</para>
</listitem>
</itemizedlist>
<para>
The remainder of this introductory part presents a short overview of the
basic concepts involved in &GStreamer; plugin development. People familiar
with the &GstAppDevMan; can use this short overview to refresh their
memory. Topics covered include <xref linkend="sect1-basics-elements"/>,
<xref linkend="sect1-basics-pads"/>, <xref
linkend="sect1-basics-buffers"/>, <xref linkend="sect1-basics-types"/>,
and <xref linkend="sect1-basics-events"/>.
</para>
<para>
As you can see, there a lot to learn, so let's get started!
</para>
<itemizedlist>
<listitem>
<para>
Creating compound and complex elements by extending from a GstBin.
This will allow you to create plugins that have other plugins embedded
in them.
</para>
</listitem>
<listitem>
<para>
Adding new mime-types to the registry along with typedetect functions.
This will allow your plugin to operate on a completely new media type.
</para>
</listitem>
<listitem>
<para>
Creating custom schedulers when the default schedulers are
insufficient.
</para>
</listitem>
<listitem>
<para>
Creating custom autopluggers when the default ones are insufficient
for your needs.
</para>
</listitem>
</itemizedlist>
</sect1>
</chapter>

1
docs/pwg/magic-pdf Normal file
View file

@ -0,0 +1 @@
<!ENTITY magic "pdf">

1
docs/pwg/magic-png Normal file
View file

@ -0,0 +1 @@
<!ENTITY magic "png">

View file

@ -0,0 +1,9 @@
<!-- ############ chapter ############# -->
<chapter id="cha-other-autoplugger" xreflabel="Writing an Autoplugger">
<title>Writing an Autoplugger</title>
<para>
FIXME: write.
</para>
</chapter>

9
docs/pwg/other-sink.xml Normal file
View file

@ -0,0 +1,9 @@
<!-- ############ chapter ############# -->
<chapter id="cha-other-sink" xreflabel="Writing a Sink">
<title>Writing a Sink</title>
<para>
FIXME: write.
</para>
</chapter>

View file

@ -0,0 +1,9 @@
<!-- ############ chapter ############# -->
<chapter id="cha-other-source" xreflabel="Writing a Source">
<title>Writing a Source</title>
<para>
FIXME: write.
</para>
</chapter>

58
docs/pwg/titlepage.xml Normal file
View file

@ -0,0 +1,58 @@
<bookinfo>
<authorgroup>
<author>
<firstname>Richard</firstname>
<othername>John</othername>
<surname>Boulton</surname>
<authorblurb>
<para>
<email>richard-gst@tartarus.org</email>
</para>
</authorblurb>
</author>
<author>
<firstname>Erik</firstname>
<surname>Walthinsen</surname>
<authorblurb>
<para>
<email>omega@temple-baptist.com</email>
</para>
</authorblurb>
</author>
<author>
<firstname>Steve</firstname>
<surname>Baker</surname>
<authorblurb>
<para>
<email>stevebaker_org@yahoo.co.uk</email>
</para>
</authorblurb>
</author>
<author>
<firstname>Leif</firstname>
<surname>Johnson</surname>
<authorblurb>
<para>
<email>leif@ambient.2y.net</email>
</para>
</authorblurb>
</author>
</authorgroup>
<legalnotice id="legalnotice">
<para>
This material may be distributed only subject to the terms and
conditions set forth in the Open Publication License, v1.0 or later (the
latest version is presently available at <ulink
url="http://www.opencontent.org/openpub/"
type="http">http://www.opencontent.org/openpub/</ulink>).
</para>
</legalnotice>
<title>&GStreamer; Plugin Writer's Guide</title>
</bookinfo>