mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
622a80da54
Original commit message from CVS: Moved "Filter Writer's Guide" to "Plugin Writer's Guide". Divided existing info from old guide into several files, one per chapter. The guide still needs much work ...
295 lines
12 KiB
XML
295 lines
12 KiB
XML
<!-- ############ 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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|