mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
Moving the "Filter Writer's Guide" to the "Plugin Writers' Guide".
Original commit message from CVS: Moving the "Filter Writer's Guide" to the "Plugin Writers' Guide".
This commit is contained in:
parent
ebda7d920a
commit
cc5f591c17
15 changed files with 0 additions and 1631 deletions
13
docs/fwg/.gitignore
vendored
13
docs/fwg/.gitignore
vendored
|
@ -1,13 +0,0 @@
|
|||
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
|
|
@ -1,18 +0,0 @@
|
|||
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
|
|
@ -1,23 +0,0 @@
|
|||
<chapter id="cha-buffers-anatomy">
|
||||
<title>
|
||||
Anatomy of a Buffer
|
||||
</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-buffers-refcounts">
|
||||
<title>
|
||||
Refcounts and mutability
|
||||
</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-buffers-metadata">
|
||||
<title>
|
||||
Metadata
|
||||
</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
|
@ -1,14 +0,0 @@
|
|||
<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>
|
|
@ -1,380 +0,0 @@
|
|||
<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>
|
|
@ -1,878 +0,0 @@
|
|||
<?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 SYSTEM "intro.xml">
|
||||
<!ENTITY TESTAPP SYSTEM "testapp.xml">
|
||||
<!ENTITY LOOPBASED SYSTEM "loopbased.xml">
|
||||
<!ENTITY BUFFERS SYSTEM "buffers.xml">
|
||||
<!ENTITY SRCNSINK SYSTEM "srcnsink.xml">
|
||||
<!ENTITY STATEMANAGE SYSTEM "statemanage.xml">
|
||||
<!ENTITY CHECKLIST SYSTEM "checklist.xml">
|
||||
<!ENTITY DPARAMS SYSTEM "dparams.xml">
|
||||
<!ENTITY GStreamer "<application>GStreamer</application>">
|
||||
]>
|
||||
|
||||
<book id="index">
|
||||
&TITLEPAGE;
|
||||
|
||||
<!-- ############# part ############### -->
|
||||
|
||||
<part id="introduction"><title>Introduction</title>
|
||||
<partintro>
|
||||
<para>
|
||||
&GStreamer; is a framework for creating
|
||||
streaming media applications. It is extremely powerful and versatile,
|
||||
and this versatility stems in part from its modularity, and its ability
|
||||
to incorporate new modules seamlessly into its framework.
|
||||
This document describes how to extend the capabilities of
|
||||
&GStreamer; by creating new plugins.
|
||||
</para>
|
||||
<para>
|
||||
It first describes the concepts required and the ways in which
|
||||
&GStreamer; can be extended. It then goes
|
||||
through a worked example of how to write a simple filter (for data
|
||||
processing), and how to test and debug it. More advanced concepts are
|
||||
then introduced, with worked examples of each. Next, writing source
|
||||
and sink elements (for performing input and output) is discussed.
|
||||
Finally, checklists of things to be sure to do when extending
|
||||
&GStreamer; are presented.
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&INTRO;
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="basic-concepts"><title>Basic concepts</title>
|
||||
<partintro>
|
||||
<para>
|
||||
|
||||
This section introduces the basic concepts required to understand the
|
||||
issues involved in extending &GStreamer;
|
||||
</para>
|
||||
<para>
|
||||
Many of these concepts are explained in greater detail in the
|
||||
GStreamer Application Development Manual, and are merely mentioned
|
||||
here to refresh your memory.
|
||||
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
|
||||
<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>gstreamer-register</emphasis> utility and the
|
||||
documentation in the <emphasis>GStreamer Application Development
|
||||
Manual</emphasis> 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>gstreamer-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>
|
||||
|
||||
<chapter id="cha-elements">
|
||||
<title>Elements</title>
|
||||
<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.
|
||||
</para>
|
||||
<para>
|
||||
An element may be constructed in several different ways, but all must
|
||||
conform to the same basic rules. A 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>
|
||||
|
||||
<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>
|
||||
</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 later in this document for
|
||||
details of the available types.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-metadata">
|
||||
<title>Metadata</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-scheduling">
|
||||
<title>Scheduling</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-chainloop">
|
||||
<title>Chain vs Loop Elements</title>
|
||||
<para>
|
||||
</para>
|
||||
</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>
|
||||
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="typesnprops"><title>Types and Properties</title>
|
||||
<partintro>
|
||||
<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>
|
||||
</partintro>
|
||||
|
||||
<chapter id="cha-basic-types">
|
||||
<title>The basic types</title>
|
||||
<para>
|
||||
This is a list of the basic types used for buffers. For each type, we
|
||||
give the name ("mime type") of the type, the list of properties which
|
||||
are associated with the type, the meaning of each property, and the
|
||||
purpose of the type.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>audio/raw</emphasis>
|
||||
- Unstructured and uncompressed raw audio data.
|
||||
</para><para>
|
||||
<emphasis>rate</emphasis>
|
||||
- The sample rate of the data, in samples per second.
|
||||
</para><para>
|
||||
<emphasis>channels</emphasis>
|
||||
- The number of channels of audio data.
|
||||
</para><para>
|
||||
<emphasis>format</emphasis>
|
||||
- This describes the format in which the audio data is passed.
|
||||
This is a string for which there are currently two valid values:
|
||||
"int" for integer data and "float" for floating point data.
|
||||
</para><para>
|
||||
<emphasis>law</emphasis>
|
||||
- Valid only if format=int. The law used to describe the data.
|
||||
This is an integer for which there are three valid values: 0 for
|
||||
linear, 1 for mu law, 2 for A law.
|
||||
</para><para>
|
||||
<emphasis>endianness</emphasis>
|
||||
- Valid only if format=int. The order of bytes in a sample. This
|
||||
is a boolean: 0 means little-endian (ie, bytes are least
|
||||
significant first), 1 means big-endian (ie, most significant byte
|
||||
first).
|
||||
</para><para>
|
||||
<emphasis>signed</emphasis>
|
||||
- Valid only if format=int. Whether the samples are signed or not.
|
||||
This is a boolean: 0 means unsigned, 1 means signed.
|
||||
</para><para>
|
||||
<emphasis>width</emphasis>
|
||||
- Valid only if format=int. The number of bits per sample. This
|
||||
is extremely likely to be a multiple of 8, but as ever this is up
|
||||
to each element supporting this format to specify.
|
||||
</para><para>
|
||||
<emphasis>depth</emphasis>
|
||||
- Valid only if format=int. The number of bits used per sample.
|
||||
This must be less than or equal to the width: if less than the
|
||||
width, the low bits are assumed to be the ones used. For example,
|
||||
width=32, depth=24 means that each sample is stored in a 32 bit
|
||||
word, but only the low 24 bits are actually used.
|
||||
</para><para>
|
||||
<emphasis>layout</emphasis>
|
||||
- Valid only if format=float. A string representing the way in
|
||||
which the floating point data is represented. For now, the only
|
||||
valid value is gfloat, meaning that the data is passed as a series
|
||||
of gfloat values.
|
||||
</para><para>
|
||||
<emphasis>intercept</emphasis>
|
||||
- Valid only if format=float. A floating point value representing
|
||||
the value that the signal "centres" on.
|
||||
</para><para>
|
||||
<emphasis>slope</emphasis>
|
||||
- Valid only if format=float. A floating point value representing
|
||||
how far the signal deviates from the intercept. So 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.
|
||||
</para>
|
||||
<para>
|
||||
For example: 16 bit integer, unsigned, linear, monophonic, big-endian,
|
||||
44100KHz audio would be represented by
|
||||
"format=int,law=0,endianness=1,signed=0,width=16,depth=16,rate=44100,channels=1"
|
||||
and floating point, using gfloat's, in the range -1.0 to 1.0,
|
||||
8000KHz stereo audio would be represented by
|
||||
"format=float,layout=gfloat,intercept=0.0,slope=1.0,rate=8000,channels=2"
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>audio/mp3</emphasis>
|
||||
- Audio data compressed using the mp3 encoding scheme.
|
||||
</para><para>
|
||||
<emphasis>framed</emphasis>
|
||||
- This is a boolean. If true (1), each buffer contains exactly
|
||||
one frame. If false (0), frames and buffers do not (necessarily)
|
||||
match up. If the data is not framed, the values of some of the
|
||||
properties will not be available, but others will be assumed to
|
||||
be constant throughout the file, or may be found in other ways.
|
||||
</para><para>
|
||||
<emphasis>layer</emphasis>
|
||||
- The compression scheme layer used to compress the data.
|
||||
This is an integer, and can currently have the value 1, 2
|
||||
or 3.
|
||||
</para><para>
|
||||
<emphasis>bitrate</emphasis>
|
||||
- The bitrate, in kilobits per second.
|
||||
For VBR (variable bitrate) mp3 data, this is the average bitrate.
|
||||
</para><para>
|
||||
<emphasis>channels</emphasis>
|
||||
- The number of channels of audio data present. This could
|
||||
theoretically be any integer greater than 0, but in practice will
|
||||
be either 1 or 2.
|
||||
</para><para>
|
||||
<emphasis>joint-stereo</emphasis>
|
||||
- Boolean. If true, channels must not be zero. 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.
|
||||
</para><para>
|
||||
There are many other properties relevant for
|
||||
<emphasis>audio/mp3</emphasis> data: these may be added to this
|
||||
specification at a later date.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>audio/x-ogg</emphasis>
|
||||
- Audio data compressed using the Ogg Vorbis encoding scheme.
|
||||
There are currently no parameters defined for this type. FIXME.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>video/raw</emphasis>
|
||||
- Raw video data.
|
||||
</para><para>
|
||||
<emphasis>fourcc</emphasis>
|
||||
- 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>
|
||||
</para><para>
|
||||
<emphasis>width</emphasis>
|
||||
- The number of pixels wide that each video frame is.
|
||||
</para><para>
|
||||
<emphasis>height</emphasis>
|
||||
- The number of pixels high that each video frame is.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>video/mpeg</emphasis>
|
||||
- Video data compressed using an mpeg encoding scheme.
|
||||
</para><para>
|
||||
<emphasis>mpegversion</emphasis>
|
||||
</para><para>
|
||||
<emphasis>systemstream</emphasis>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<emphasis>video/avi</emphasis>
|
||||
- Video data compressed using the AVI encoding scheme.
|
||||
There are currently no parameters defined for this type. FIXME.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-types-test">
|
||||
<title>Building a simple format for testing</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-types-simplemime">
|
||||
<title>A simple MIME type</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-types-props">
|
||||
<title>Type properties</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-types-typefind">
|
||||
<title>Typefind functions and autoplugging</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="first-plugin"><title>Building our first plugin</title>
|
||||
<partintro>
|
||||
<para>
|
||||
We are now have the neccessary concepts to build our first plugin.
|
||||
We are going to build an element which has a single input pad and
|
||||
a single output pad, and simply passes anything it reads on
|
||||
the input pad through and out on the output pad. We will also
|
||||
see where we could add code to convert this plugin into something
|
||||
more useful.
|
||||
</para>
|
||||
<para>
|
||||
The example code used in this section can be found in
|
||||
<filename>examples/plugins/</filename>
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
<chapter id="cha-boilerplate">
|
||||
<title>Constructing the boilerplate</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. I shall refer to these details
|
||||
collectively as the <emphasis>boilerplate</emphasis>.
|
||||
</para>
|
||||
|
||||
<sect1 id="sect-boilerplate-gobject">
|
||||
<title>Doing it the hard way with GstObject</title>
|
||||
<para>
|
||||
The standard way of defining the boilerplate is simply to write some
|
||||
code, and fill in some structures. The easiest way to do this is to
|
||||
copy an example and modify according to your needs.
|
||||
</para>
|
||||
<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/plugins/example.h</filename>
|
||||
</para>
|
||||
|
||||
<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>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect-boilerplate-filterfactory">
|
||||
<title>Doing it the easy way with FilterFactory</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.
|
||||
</para>
|
||||
<para>
|
||||
Unfortunately, this hasn't yet been implemented. It is also likely
|
||||
that when it is, it will not be possible to cover all the possibilities
|
||||
available by writing the boilerplate yourself, so some plugins will
|
||||
always need to be manually registered.
|
||||
</para>
|
||||
<para>
|
||||
As a rough outline of what is planned: the FilterFactory will take a
|
||||
list of appropriate function pointers, and data structures to define
|
||||
a filter. With a reasonable measure of preprocessor magic, the
|
||||
plugin writer will then simply need to provide definitions of the
|
||||
functions and data structures desired, and a name for the filter, and
|
||||
then call a macro from within plugin_init() which will register the
|
||||
new filter. All the fluff that goes into the definition of a filter
|
||||
will thus be hidden from view.
|
||||
</para>
|
||||
<para>
|
||||
Ideally, we will come up with a way for various FilterFactory-provided
|
||||
functions to be overridden, to the point where you can construct
|
||||
almost the most complex stuff with it, it just saves typing.
|
||||
</para>
|
||||
<para>
|
||||
Of course, the filter factory can be used to create sources and sinks
|
||||
too: simply create a filter with only source or sink pads.
|
||||
</para>
|
||||
<para>
|
||||
You may be thinking that this should really be called an
|
||||
ElementFactory. Well, we agree, but there is already something else
|
||||
justifiably ealled an ElementFactory (this is the thing which actually
|
||||
makes instances of elements). There is also already something called
|
||||
a PluginFactory. We just have too many factories and not enough words.
|
||||
And since this isn't yet written, it doesn't get priority for claiming
|
||||
a name.
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-defineelt">
|
||||
<title>Defining an element</title>
|
||||
<para>
|
||||
A new element is defined by creating an element factory. This is a
|
||||
structure containing all the information needed to create an instance
|
||||
of the element. Creating a factory requires two things: a type for
|
||||
the element to be created
|
||||
(this was defined in the boilerplate above: FIXME - reorganise),
|
||||
and a GstElementDetails structure, which contains some
|
||||
general information about the element to be created.
|
||||
</para>
|
||||
|
||||
<sect1 id="sect-defineelt-eltdetails">
|
||||
<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 ".".
|
||||
</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 id="sect-defineelt-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 id="sect-defineelt-pads">
|
||||
<title>Specifying the pads</title>
|
||||
<para>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect-defineelt-fns">
|
||||
<title>Attaching functions</title>
|
||||
<para>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect-defineelt-chainfn">
|
||||
<title>The chain function</title>
|
||||
<para>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect-defineelt-arguments">
|
||||
<title>Adding arguments</title>
|
||||
<para>
|
||||
Define arguments in enum.
|
||||
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect-defineelt-signals">
|
||||
<title>Signals</title>
|
||||
<para>
|
||||
Define signals in enum.
|
||||
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-definetype">
|
||||
<title>Defining a type</title>
|
||||
<para>
|
||||
A new type is defined by creating an type factory. This is a
|
||||
structure containing all the information needed to create an instance
|
||||
of the type.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-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 id="sect-plugininit-types">
|
||||
<title>Registering new types</title>
|
||||
<para>
|
||||
|
||||
</para>
|
||||
<programlisting>
|
||||
void gst_plugin_add_type(GstPlugin *plugin,
|
||||
GstTypeFactory *factory);
|
||||
</programlisting>
|
||||
<para>
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect-plugininit-filter">
|
||||
<title>Registering new element factories</title>
|
||||
<para>
|
||||
</para>
|
||||
<programlisting>
|
||||
void gst_plugin_add_factory(GstPlugin *plugin,
|
||||
GstElementFactory *factory);
|
||||
</programlisting>
|
||||
<para>
|
||||
Multiple element factories can be provided by a single plugin:
|
||||
all it needs to do is call gst_plugin_add_factory() for each
|
||||
element factory it wishes to provide.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect-plugininit-autopluggers">
|
||||
<title>Registering new autopluggers</title>
|
||||
<para>
|
||||
</para>
|
||||
<programlisting>
|
||||
void gst_plugin_add_autoplugger(GstPlugin *plugin,
|
||||
GstAutoplugFactory *factory);
|
||||
</programlisting>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
||||
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="dparams"><title>Supporting Dynamic Parameters</title>
|
||||
<partintro>
|
||||
<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 dparams will be used as an abbreviation for Dynamic Parameters.
|
||||
</para>
|
||||
</partintro>
|
||||
<sect2 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>
|
||||
</sect2>
|
||||
|
||||
&DPARAMS;
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="test-app"><title>Building a simple test application</title>
|
||||
<partintro>
|
||||
<para>
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&TESTAPP;
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="loopbased"><title>Loop-based Elements</title>
|
||||
<partintro>
|
||||
<para>
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&LOOPBASED;
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="buffersnmeta"><title>Buffers and Metadata</title>
|
||||
<partintro>
|
||||
<para>
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&BUFFERS;
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="srcnsink"><title>Sources and Sinks</title>
|
||||
<partintro>
|
||||
<para>
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&SRCNSINK;
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="statemanage"><title>State management</title>
|
||||
<partintro>
|
||||
<para>
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&STATEMANAGE;
|
||||
</part>
|
||||
|
||||
<!-- ############ part ############# -->
|
||||
|
||||
<part id="checklist"><title>Checklist</title>
|
||||
<partintro>
|
||||
<para>
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
&CHECKLIST;
|
||||
</part>
|
||||
|
||||
</book>
|
|
@ -1,173 +0,0 @@
|
|||
<chapter id="cha-doicare">
|
||||
<title>Do I care?</title>
|
||||
<para>
|
||||
This guide explains how to write new modules for GStreamer. It is
|
||||
relevant to:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Anyone who wants to add support for new input and output
|
||||
devices, often called sources and sinks. For example,
|
||||
adding the ability to write to a new video output system
|
||||
could be done by writing an appropriate sink plugin.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Anyone who wants to add support for new ways of processing
|
||||
data in GStreamer, often called
|
||||
filters. For example, a new data format converter could be
|
||||
created.
|
||||
</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 it places on the
|
||||
rest of the code. And you might be surprised 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 use an application which uses GStreamer.
|
||||
You lot can go away. Shoo... (You might find the <emphasis>GStreamer
|
||||
Application Development Manual</emphasis> helpful though.)
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-prelimreading">
|
||||
<title>Preliminary reading</title>
|
||||
<para>
|
||||
The reader should be familiar with the basic workings of
|
||||
<application>GStreamer</application>. For a gentle introduction to
|
||||
GStreamer, you may wish to read the <emphasis>GStreamer Application
|
||||
Development Manual</emphasis>. Since <application>GStreamer</application>
|
||||
adheres to the GObject programming model, the reader is also assumed to
|
||||
understand the basics of GObject.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="cha-structure">
|
||||
<title>Structure of this guide</title>
|
||||
<para>
|
||||
The <application>GStreamer</application> API for developing plugins is
|
||||
rather extensive and powerful. We will first try to get you up and running
|
||||
with a simple plugin as fast as possible. We will then gradually add more
|
||||
features to our example plugin. The basic topics will be:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Short overview of the GStreamer concepts. People familiar with the
|
||||
<emphasis>GStreamer Application Development Manual</emphasis> can use
|
||||
this short overview to refresh their memory.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Introduction to the basic structure of the plugin. We will cover all the
|
||||
different steps you have to perform in order to build a plugin. This will
|
||||
include a general overview of the structure of your source files.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Creating the plugin boilerplate. We will show you how to define and set up
|
||||
the different aspects for creating a plugin. This will cover extending the
|
||||
GstElement class and creating the elementfactory structures. This will include
|
||||
setting up the .h and .c files of your plugin.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Defining the entry point of the plugin and registering the elementfactory.
|
||||
After this step your plugin will become available for application programmers.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Setting up the basic components of the element like adding pads and setting
|
||||
up the scheduling entry points of your plugin.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Adding arguments and signals to the plugin. Users of your plugin will be
|
||||
able to listen for specific events your plugin generates as well as change and
|
||||
adjust the different properties of your plugin.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Compiling and testing the basic plugin.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
After this first section, you should be able to create a simple plugin. We will then
|
||||
introduce the more advanced concepts of plugins, including:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Adding padtemplates to the plugin. This will allow your plugin to become fully
|
||||
integrated in the GStreamer plugin registry and will allow users of your plugin
|
||||
to know what media types your plugin operates on.
|
||||
</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>
|
||||
Adding caps to the plugins input pads. This will allow other plugins to know what
|
||||
media type your plugin is handling at runtime.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Choosing between a loop-based or a chain-based plugin. We will teach you how to
|
||||
create plugins with a more complicated input/output behaviour.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Adding request pads to the plugin. Request pads allow the application programmer
|
||||
to let your plugin dynamically create a pad based on a template.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Caps negotiation will show you how your plugin can addapt to the plugins it
|
||||
is connected to.
|
||||
</para>
|
||||
</listitem>
|
||||
<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>
|
||||
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>
|
||||
<para>
|
||||
As you can see, there a lot to learn, so let's get started...
|
||||
</para>
|
||||
|
||||
</chapter>
|
|
@ -1,27 +0,0 @@
|
|||
<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>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<!ENTITY magic "pdf">
|
|
@ -1 +0,0 @@
|
|||
<!ENTITY magic "png">
|
|
@ -1,16 +0,0 @@
|
|||
<chapter id="cha-srcnsink-writesrc">
|
||||
<title>
|
||||
Writing a source
|
||||
</title>
|
||||
<para>
|
||||
Pull vs loop based
|
||||
Region pulling
|
||||
</para>
|
||||
</chapter>
|
||||
<chapter id="cha-srcnsink-writesink">
|
||||
<title>
|
||||
Writing a sink
|
||||
</title>
|
||||
<para>
|
||||
</para>
|
||||
</chapter>
|
|
@ -1,14 +0,0 @@
|
|||
<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>
|
|
@ -1,25 +0,0 @@
|
|||
<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>
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<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>
|
||||
</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><application>GStreamer</application> Plugin Writer's Guide</title>
|
||||
|
||||
</bookinfo>
|
Loading…
Reference in a new issue