mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
af236bd270
Original commit message from CVS: + small updates to plugin writer's guide
300 lines
12 KiB
XML
300 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 basic
|
|
tools to copy and modify a template plugin to create a new plugin. If you
|
|
follow the examples here, then by the end of this chapter you will have a
|
|
functional audio filter plugin that you can compile and use in &GStreamer;
|
|
applications.
|
|
</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. (Errm, that is, <quote>it is left as an exercise to the
|
|
reader.</quote>)
|
|
</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 a basic &GStreamer; plugin. To check out the
|
|
<filename>gst-template</filename> module, make sure you are connected to
|
|
the internet, and type the following commands at a command console:
|
|
</para>
|
|
<screen>
|
|
<prompt>shell $ </prompt><userinput>cd .</userinput>
|
|
<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-project-stamp" xreflabel="Using the Project Stamp">
|
|
<title>Using the Project Stamp</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 are some tools in the
|
|
<filename class="directory">./gst-template/tools/</filename> directory.
|
|
One tool, <filename>gst-quick-stamp</filename>, is a quick command line
|
|
tool. The other, <filename>gst-project-stamp</filename>, is a full GNOME
|
|
druid application that takes you through the steps of creating a new
|
|
project (either a plugin or an application).
|
|
</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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|