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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+
+<!-- ############ 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 <gst/control/control.h>
+ </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->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>&(example->volume)</filename>.
+ </para>
+ <programlisting>
+ gst_dpman_add_required_dparam_direct (
+ example->dpman,
+ g_param_spec_float("volume","Volume","Volume of the audio",
+ 0.0, 1.0, 0.8, G_PARAM_READWRITE),
+ FALSE,
+ FALSE,
+ &(example->volume)
+ );
+ </programlisting>
+ <para>
+ You can now use <filename>example->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->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->volume_f = g_value_get_float(value);
+ example->volume_i = example->volume_f * 8192;
+}
+ </programlisting>
+ <para>
+ Now <filename>example->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 < num_samples; j++) {
+ float_data[j] *= example->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->dpman, num_samples, GST_BUFFER_TIMESTAMP(buf));
+ ...
+ while (GST_DPMAN_PROCESS_COUNTDOWN(example->dpman, frame_countdown, j)) {
+ float_data[j++] *= example->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>
--- /dev/null
+<chapter id="cha-advanced-request">
+ <title>Request pads</title>
+ <para>
+ aka pushing and pulling
+ </para>
+</chapter>
--- /dev/null
+<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>
+
--- /dev/null
+<!-- ############ 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>
--- /dev/null
+<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>
--- /dev/null
+
+<!-- ############ 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>
--- /dev/null
+
+<!-- ############ 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>
--- /dev/null
+
+<!-- ############ 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>
+
--- /dev/null
+
+<!-- ############ chapter ############# -->
+
+<chapter id="cha-events">
+ <title>Events</title>
+ <para>
+ </para>
+</chapter>
--- /dev/null
+
+<!-- ############ 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>
--- /dev/null
+
+<!-- ############ 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>
--- /dev/null
+<!-- ############ 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 <your.name@your.isp>",
+ "(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>
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+
+<!-- ############ chapter ############# -->
+
+<chapter id="cha-building-chainfn">
+ <title>The chain function</title>
+ <para>
+ </para>
+</chapter>
--- /dev/null
+
+<!-- ############ chapter ############# -->
+
+<chapter id="cha-building-pads">
+ <title>Specifying the pads</title>
+ <para>
+ </para>
+</chapter>
+
--- /dev/null
+<!-- ############ chapter ############# -->
+
+<chapter id="cha-building-args" xreflabel="Adding Arguments">
+ <title>Adding Arguments</title>
+ <para>
+ Define arguments in enum.
+ </para>
+</chapter>
+
--- /dev/null
+
+<!-- ############ chapter ############# -->
+
+<chapter id="cha-building-signals">
+ <title>Signals</title>
+ <para>
+ Define signals in enum.
+ </para>
+</chapter>
--- /dev/null
+<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>
--- /dev/null
+<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>
+
--- /dev/null
+<?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>
--- /dev/null
+<!-- ############ 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 law</quote>, and 2 indicates
+ <quote>A 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>
\ No newline at end of file
--- /dev/null
+
+<!-- ############ 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 — and there are quite a lot of
+ plugins already — 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> —
+ 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> —
+ 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> — 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> — 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>
--- /dev/null
+<!ENTITY magic "pdf">
--- /dev/null
+<!ENTITY magic "png">
--- /dev/null
+
+<!-- ############ chapter ############# -->
+
+<chapter id="cha-other-autoplugger" xreflabel="Writing an Autoplugger">
+ <title>Writing an Autoplugger</title>
+ <para>
+ FIXME: write.
+ </para>
+</chapter>
--- /dev/null
+
+<!-- ############ chapter ############# -->
+
+<chapter id="cha-other-sink" xreflabel="Writing a Sink">
+ <title>Writing a Sink</title>
+ <para>
+ FIXME: write.
+ </para>
+</chapter>
--- /dev/null
+
+<!-- ############ chapter ############# -->
+
+<chapter id="cha-other-source" xreflabel="Writing a Source">
+ <title>Writing a Source</title>
+ <para>
+ FIXME: write.
+ </para>
+</chapter>
--- /dev/null
+ <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>