2002-09-27 18:34:33 +00:00
|
|
|
<!-- ############ chapter ############# -->
|
|
|
|
|
2004-01-28 15:51:14 +00:00
|
|
|
<chapter id="chapter-building-boiler" xreflabel="Constructing the Boilerplate">
|
2002-09-27 18:34:33 +00:00
|
|
|
<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
|
2002-11-28 08:37:12 +00:00
|
|
|
&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.
|
2002-09-27 18:34:33 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<!-- ############ sect1 ############# -->
|
|
|
|
|
2004-01-28 15:51:14 +00:00
|
|
|
<sect1 id="section-boiler-source" xreflabel="Getting the GStreamer Plugin Templates">
|
2003-12-05 12:26:58 +00:00
|
|
|
<title>Getting the GStreamer Plugin Templates</title>
|
2002-09-27 18:34:33 +00:00
|
|
|
<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
|
2002-11-28 08:37:12 +00:00
|
|
|
here. (Errm, that is, <quote>it is left as an exercise to the
|
|
|
|
reader.</quote>)
|
2002-09-27 18:34:33 +00:00
|
|
|
</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
|
2002-11-28 08:37:12 +00:00
|
|
|
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:
|
2002-09-27 18:34:33 +00:00
|
|
|
</para>
|
|
|
|
<screen>
|
2005-08-31 21:01:35 +00:00
|
|
|
<prompt>shell $ </prompt><userinput>cvs -d:pserver:anoncvs@cvs.freedesktop.org/cvs/gstreamer login</userinput>
|
2004-11-06 10:28:07 +00:00
|
|
|
Logging in to :pserver:anoncvs@cvs.freedesktop.org:/cvs/gstreamer
|
2004-04-03 03:00:38 +00:00
|
|
|
CVS password: <keycap>[ENTER]</keycap>
|
|
|
|
|
|
|
|
<prompt>shell $ </prompt><userinput>cvs -z3 -d:pserver:anoncvs@cvs.freedesktop.org:/cvs/gstreamer co gst-template</userinput>
|
2002-09-27 18:34:33 +00:00
|
|
|
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
|
2002-11-28 08:37:12 +00:00
|
|
|
log in to the CVS server. (You might have to log in twice.) The second
|
2002-09-27 18:34:33 +00:00
|
|
|
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 ############# -->
|
|
|
|
|
2004-01-28 15:51:14 +00:00
|
|
|
<sect1 id="section-boiler-project-stamp" xreflabel="Using the Project Stamp">
|
2004-12-23 14:26:14 +00:00
|
|
|
<title>Using the Project Stamp</title>
|
|
|
|
<!-- FIXME
|
|
|
|
This section needs some fixing from someone that is aware of how this
|
|
|
|
works. The only tool that looks like the ones cited there is
|
|
|
|
<filename>gst-plugins/tools/filterstamp.sh</filename>
|
|
|
|
-->
|
2002-09-27 18:34:33 +00:00
|
|
|
<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
|
2006-02-09 23:40:43 +00:00
|
|
|
according to your needs. To help you do so, there is a tool in the
|
2004-05-01 15:45:48 +00:00
|
|
|
<filename class="directory">./gst-plugins/tools/</filename> directory.
|
2006-02-09 23:40:43 +00:00
|
|
|
This tool, <filename>make_element</filename>, is a quick command line
|
|
|
|
tool.
|
2002-09-27 18:34:33 +00:00
|
|
|
</para>
|
|
|
|
<para>
|
2006-02-09 23:40:43 +00:00
|
|
|
To use <command>make_element</command>, first open up a terminal window.
|
|
|
|
Change to the <filename class="directory">gst-template/gst-plugin/src</filename>
|
|
|
|
directory, and then run the <command>make_element</command> command. The
|
|
|
|
arguments to the <command>make_element</command> are:
|
2002-09-27 18:34:33 +00:00
|
|
|
</para>
|
|
|
|
<orderedlist>
|
|
|
|
<listitem>
|
|
|
|
<para>the name of the plugin, and</para>
|
|
|
|
</listitem>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2006-02-09 23:40:43 +00:00
|
|
|
the source file that the tool will use. By default,
|
|
|
|
gstplugin.{c,h} is used.
|
2002-09-27 18:34:33 +00:00
|
|
|
</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
|
2002-11-28 08:37:12 +00:00
|
|
|
directory names. For example, the following commands create the
|
|
|
|
ExampleFilter plugin based on the plugin template and put the output files
|
2006-02-09 23:40:43 +00:00
|
|
|
in the <filename class="directory">gst-template/gst-plugin/src</filename>
|
|
|
|
directory:
|
2002-09-27 18:34:33 +00:00
|
|
|
</para>
|
|
|
|
<screen>
|
2006-02-09 23:40:43 +00:00
|
|
|
<prompt>shell $ </prompt><userinput>cd gst-template/gst-plugin/src</userinput>
|
|
|
|
<prompt>shell $ </prompt><userinput>../tools/make_element ExampleFilter</userinput>
|
2002-09-27 18:34:33 +00:00
|
|
|
</screen>
|
2006-02-09 23:40:43 +00:00
|
|
|
<para>
|
|
|
|
The last command creates two files:
|
|
|
|
<filename>gstexamplefilter.c</filename> and
|
|
|
|
<filename>gstexamplefilter.h</filename>.
|
|
|
|
</para>
|
2002-09-27 18:34:33 +00:00
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<!-- ############ sect1 ############# -->
|
|
|
|
|
2004-01-28 15:51:14 +00:00
|
|
|
<sect1 id="section-boiler-examine">
|
2002-09-27 18:34:33 +00:00
|
|
|
<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
|
gst/gstelement.c (gst_element_dispose): Protect against multiple invocations.
Original commit message from CVS:
2004-02-24 Andy Wingo <wingo@pobox.com>
* gst/gstelement.c (gst_element_dispose): Protect against multiple
invocations.
* gst/schedulers/gstoptimalscheduler.c
I added a mess of prototypes at the top of the file by way of
documentation. Some of the operations on chains and groups were
re-organized.
(create_group): Added a type argument so if the group is enabled,
the setup_group_scheduler knows what to do.
(group_elements): Added a type argument here, too, to be passed on
to create_group.
(group_element_set_enabled): If an unlinked PLAYING element is
added to a bin, we have to create a new group to hold the element,
and this function will be called before the group is added to the
chain. Thus we have a valid case for group->chain==NULL. Instead
of calling chain_group_set_enabled, just set the flag on the group
(the chain's status will be set when the group is added to it).
(gst_opt_scheduler_state_transition, chain_group_set_enabled):
Setup the group scheduler when the group is enabled, not
specifically when an element goes PAUSED->PLAYING. This means
PLAYING elements can be added, linked, and scheduled into a
PLAYING pipeline, as was intended.
(add_to_group): Don't ref the group twice. I don't know when this
double-ref got in here. Removing it has the potential to cause
segfaults if other parts of the scheduler are buggy. If you find
that the scheduler is segfaulting for you, put in an extra ref
here and see if that hacks over the underlying issue. Of course,
then find out what code is unreffing a group it doesn't own...
(create_group): Make the extra refcount floating, and remove it
after adding the element. This means that...
(unref_group): Destroy when the refcount reaches 0, not 1, like
every other refcounted object in the known universe.
(remove_from_group): When a group becomes empty, set it to be not
active, and remove it from its chain. Don't unref it again,
there's no floating reference any more.
(destroy_group): We have to remove the group from the chain in
remove_from_group (rather than here) to break refcounting cycles
(the chain always has a ref on the group). So assert that
group->chain==NULL.
(ref_group_by_count): Removed, it was commented out anyway.
(merge_chains): Use the remove_from_chain and add_to_chain
primitives to do the reparenting, instead of rolling our own
implementation.
(add_to_chain): The first non-disabled group in the chain's group
list will be the entry point for the chain. Because buffers can
accumulate in loop elements' peer bufpens, we preferentially
schedule loop groups before get groups to avoid unnecessary
execution of get-based groups when the bufpens are already full.
(gst_opt_scheduler_schedule_run_queue): Debug fixes.
(get_group_schedule_function): Ditto.
(loop_group_schedule_function): Ditto.
(gst_opt_scheduler_loop_wrapper): Ditto.
(gst_opt_scheduler_iterate): Ditto.
I understand the opt scheduler now, yippee!
* gst/gstpad.c: All throughout, added FIXMEs to look at for 0.9.
(gst_pad_get_name, gst_pad_set_chain_function)
(gst_pad_set_get_function, gst_pad_set_event_function)
(gst_pad_set_event_mask_function, gst_pad_get_event_masks)
(gst_pad_get_event_masks_default, gst_pad_set_convert_function)
(gst_pad_set_query_function, gst_pad_get_query_types)
(gst_pad_get_query_types_default)
(gst_pad_set_internal_link_function)
(gst_pad_set_formats_function, gst_pad_set_link_function)
(gst_pad_set_fixate_function, gst_pad_set_getcaps_function)
(gst_pad_set_bufferalloc_function, gst_pad_unlink)
(gst_pad_renegotiate, gst_pad_set_parent, gst_pad_get_parent)
(gst_pad_add_ghost_pad, gst_pad_proxy_getcaps)
(gst_pad_proxy_pad_link, gst_pad_proxy_fixate)
(gst_pad_get_pad_template_caps, gst_pad_check_compatibility)
(gst_pad_get_peer, gst_pad_get_allowed_caps)
(gst_pad_alloc_buffer, gst_pad_push, gst_pad_pull)
(gst_pad_selectv, gst_pad_select, gst_pad_template_get_caps)
(gst_pad_event_default_dispatch, gst_pad_event_default)
(gst_pad_dispatcher, gst_pad_send_event, gst_pad_convert_default)
(gst_pad_convert, gst_pad_query_default, gst_pad_query)
(gst_pad_get_formats_default, gst_pad_get_formats): Better
argument checks, and some doc fixes.
(gst_pad_custom_new_from_template): Um, does anyone
use these functions? Actually make a custom pad instead of a
normal one.
(gst_pad_try_set_caps): Transpose some checks.
(gst_pad_try_set_caps_nonfixed): Same, and use a macro to check if
the pad is in negotiation.
(gst_pad_try_relink_filtered): Use pad_link_prepare.
* gst/gstelement.c: Remove prototypes also defined in gstclock.h.
* gst/gstelement.h:
* gst/gstclock.h: Un-deprecate the old clocking API, as discussed
on the list.
2004-02-25 13:16:12 +00:00
|
|
|
plugin system, and doesn't depend on reading a header file, this is not
|
2002-09-27 18:34:33 +00:00
|
|
|
crucial.)
|
|
|
|
|
|
|
|
The code here can be found in
|
|
|
|
<filename>examples/pwg/examplefilter/boiler/gstexamplefilter.h</filename>.
|
|
|
|
</para>
|
|
|
|
|
2002-12-18 15:14:16 +00:00
|
|
|
<example id="ex-boiler-examine-h">
|
2002-09-27 18:34:33 +00:00
|
|
|
<title>Example Plugin Header File</title>
|
2005-07-01 12:43:03 +00:00
|
|
|
<programlisting><!-- example-begin filter.h a -->
|
|
|
|
#include <gst/gst.h>
|
2002-09-27 18:34:33 +00:00
|
|
|
|
2005-07-01 12:43:03 +00:00
|
|
|
/* Definition of structure storing data for this element. */
|
|
|
|
typedef struct _GstMyFilter {
|
|
|
|
GstElement element;
|
2002-09-27 18:34:33 +00:00
|
|
|
|
2005-07-01 12:43:03 +00:00
|
|
|
GstPad *sinkpad, *srcpad;
|
2002-09-27 18:34:33 +00:00
|
|
|
|
2005-07-01 12:43:03 +00:00
|
|
|
gboolean silent;
|
|
|
|
<!-- example-end filter.h a -->
|
|
|
|
<!-- example-begin filter.h b --><!--
|
|
|
|
gint samplerate, channels;
|
2005-07-06 12:18:00 +00:00
|
|
|
gint from_samplerate, to_samplerate;
|
|
|
|
gboolean passthrough;
|
2005-07-11 15:18:32 +00:00
|
|
|
guint64 offset;
|
2005-07-01 12:43:03 +00:00
|
|
|
--><!-- example-end filter.h b -->
|
|
|
|
<!-- example-begin filter.h c -->
|
|
|
|
} GstMyFilter;
|
2002-09-27 18:34:33 +00:00
|
|
|
|
2005-07-01 12:43:03 +00:00
|
|
|
/* Standard definition defining a class for this element. */
|
|
|
|
typedef struct _GstMyFilterClass {
|
|
|
|
GstElementClass parent_class;
|
|
|
|
} GstMyFilterClass;
|
2002-09-27 18:34:33 +00:00
|
|
|
|
2005-07-01 12:43:03 +00:00
|
|
|
/* Standard macros for defining types for this element. */
|
|
|
|
#define GST_TYPE_MY_FILTER \
|
|
|
|
(gst_my_filter_get_type())
|
|
|
|
#define GST_MY_FILTER(obj) \
|
|
|
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MY_FILTER,GstMyFilter))
|
|
|
|
#define GST_MY_FILTER_CLASS(klass) \
|
|
|
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MY_FILTER,GstMyFilterClass))
|
|
|
|
#define GST_IS_MY_FILTER(obj) \
|
|
|
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MY_FILTER))
|
|
|
|
#define GST_IS_MY_FILTER_CLASS(obj) \
|
|
|
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MY_FILTER))
|
2002-09-27 18:34:33 +00:00
|
|
|
|
2005-07-01 12:43:03 +00:00
|
|
|
/* Standard function returning type information. */
|
|
|
|
GType gst_my_filter_get_type (void);
|
|
|
|
<!-- example-end filter.h c --></programlisting>
|
2002-09-27 18:34:33 +00:00
|
|
|
</example>
|
2005-07-01 12:43:03 +00:00
|
|
|
<para>
|
|
|
|
Using this header file, you can use the following macro to setup
|
|
|
|
the <classname>GObject</classname> basics in your source file so
|
|
|
|
that all functions will be called appropriately:
|
|
|
|
</para>
|
|
|
|
<programlisting><!-- example-begin boilerplate.c a -->
|
|
|
|
#include "filter.h"
|
|
|
|
|
|
|
|
GST_BOILERPLATE (GstMyFilter, gst_my_filter, GstElement, GST_TYPE_ELEMENT);
|
|
|
|
<!-- example-end boilerplate.c a --></programlisting>
|
2002-09-27 18:34:33 +00:00
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<!-- ############ sect1 ############# -->
|
|
|
|
|
2004-01-28 15:51:14 +00:00
|
|
|
<sect1 id="section-boiler-details">
|
2002-09-27 18:34:33 +00:00
|
|
|
<title>GstElementDetails</title>
|
|
|
|
<para>
|
2004-07-21 11:32:09 +00:00
|
|
|
The GstElementDetails structure gives a hierarchical type for the element,
|
2002-09-27 18:34:33 +00:00
|
|
|
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>
|
2004-07-21 11:32:09 +00:00
|
|
|
The type of the element, as a hierarchy. The hierarchy is defined by
|
2002-09-27 18:34:33 +00:00
|
|
|
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 name of the author of the element, optionally followed by a contact
|
|
|
|
email address in angle brackets.
|
|
|
|
</para></listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
|
|
For example:
|
|
|
|
</para>
|
2005-07-01 12:43:03 +00:00
|
|
|
<programlisting><!-- example-begin boilerplate.c b -->
|
|
|
|
static GstElementDetails my_filter_details = {
|
2004-01-27 13:33:39 +00:00
|
|
|
"An example plugin",
|
|
|
|
"Example/FirstExample",
|
|
|
|
"Shows the basic structure of a plugin",
|
|
|
|
"your name <your.name@your.isp>"
|
|
|
|
};
|
2005-07-01 12:43:03 +00:00
|
|
|
<!-- example-end boilerplate.c b --></programlisting>
|
2004-01-27 13:33:39 +00:00
|
|
|
<para>
|
|
|
|
The element details are registered with the plugin during
|
2004-11-06 10:28:07 +00:00
|
|
|
the <function>_base_init ()</function> function, which is part of
|
|
|
|
the GObject system. The <function>_base_init ()</function> function
|
|
|
|
should be set for this GObject in the function where you register
|
|
|
|
the type with Glib.
|
2004-01-27 13:33:39 +00:00
|
|
|
</para>
|
2005-07-01 12:43:03 +00:00
|
|
|
<programlisting><!-- example-begin boilerplate.c c -->
|
2004-01-27 13:33:39 +00:00
|
|
|
static void
|
2005-07-01 12:43:03 +00:00
|
|
|
gst_my_filter_base_init (gpointer klass)
|
2004-01-27 13:33:39 +00:00
|
|
|
{
|
2005-07-01 12:43:03 +00:00
|
|
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
|
|
|
<!-- example-end boilerplate.c c -->
|
2004-01-27 13:33:39 +00:00
|
|
|
static GstElementDetails my_filter_details = {
|
|
|
|
[..]
|
2002-09-27 18:34:33 +00:00
|
|
|
};
|
2004-01-27 13:33:39 +00:00
|
|
|
|
2005-07-01 12:43:03 +00:00
|
|
|
[..]<!-- example-begin boilerplate.c d -->
|
2004-01-27 13:33:39 +00:00
|
|
|
gst_element_class_set_details (element_class, &my_filter_details);
|
2005-07-01 12:43:03 +00:00
|
|
|
<!-- example-end boilerplate.c d -->
|
2004-01-27 13:33:39 +00:00
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<!-- ############ sect1 ############# -->
|
|
|
|
|
2004-01-28 15:51:14 +00:00
|
|
|
<sect1 id="section-boiler-padtemplates">
|
2004-01-27 13:33:39 +00:00
|
|
|
<title>GstStaticPadTemplate</title>
|
|
|
|
<para>
|
|
|
|
A GstStaticPadTemplate is a description of a pad that the element will
|
|
|
|
(or might) create and use. It contains:
|
|
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
|
|
<listitem>
|
|
|
|
<para>A short name for the pad.</para>
|
|
|
|
</listitem>
|
|
|
|
<listitem>
|
|
|
|
<para>Pad direction.</para>
|
|
|
|
</listitem>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Existence property. This indicates whether the pad exists always (an
|
|
|
|
<quote>always</quote> pad), only in some cases (a
|
|
|
|
<quote>sometimes</quote> pad) or only if the application requested
|
|
|
|
such a pad (a <quote>request</quote> pad).
|
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
<listitem>
|
|
|
|
<para>Supported types by this element (capabilities).</para>
|
|
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
|
|
For example:
|
|
|
|
</para>
|
2005-07-01 12:43:03 +00:00
|
|
|
<programlisting><!-- example-begin boilerplate.c e -->
|
2004-01-27 13:33:39 +00:00
|
|
|
static GstStaticPadTemplate sink_factory =
|
|
|
|
GST_STATIC_PAD_TEMPLATE (
|
|
|
|
"sink",
|
|
|
|
GST_PAD_SINK,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS ("ANY")
|
|
|
|
);
|
2005-07-01 12:43:03 +00:00
|
|
|
<!-- example-end boilerplate.c e -->
|
|
|
|
<!-- example-begin boilerplate.c f --><!--
|
|
|
|
static GstStaticPadTemplate src_factory =
|
|
|
|
GST_STATIC_PAD_TEMPLATE (
|
|
|
|
"src",
|
|
|
|
GST_PAD_SRC,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS ("ANY")
|
|
|
|
);
|
|
|
|
--><!-- example-end boilerplate.c f -->
|
2004-01-27 13:33:39 +00:00
|
|
|
</programlisting>
|
|
|
|
<para>
|
|
|
|
Those pad templates are registered during the
|
|
|
|
<function>_base_init ()</function> function. Pads are created from these
|
|
|
|
templates in the element's <function>_init ()</function> function using
|
|
|
|
<function>gst_pad_new_from_template ()</function>. The template can be
|
|
|
|
retrieved from the element class using
|
|
|
|
<function>gst_element_class_get_pad_template ()</function>. See below
|
2004-11-06 10:28:07 +00:00
|
|
|
for more details on this. In order to create a new pad from this
|
|
|
|
template using <function>gst_pad_new_from_template ()</function>, you
|
|
|
|
will need to declare the pad template as a global variable. More on
|
|
|
|
this subject in <xref linkend="chapter-building-pads"/>.
|
2004-01-27 13:33:39 +00:00
|
|
|
</para>
|
|
|
|
<programlisting>
|
2004-11-06 10:28:07 +00:00
|
|
|
static GstStaticPadTemplate sink_factory = [..],
|
|
|
|
src_factory = [..];
|
|
|
|
|
2004-01-27 13:33:39 +00:00
|
|
|
static void
|
2005-07-01 12:43:03 +00:00
|
|
|
gst_my_filter_base_init (gpointer klass)
|
2004-01-27 13:33:39 +00:00
|
|
|
{
|
|
|
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
2005-07-01 12:43:03 +00:00
|
|
|
[..]
|
|
|
|
<!-- example-begin boilerplate.c g -->
|
2004-01-27 13:33:39 +00:00
|
|
|
gst_element_class_add_pad_template (element_class,
|
|
|
|
gst_static_pad_template_get (&src_factory));
|
|
|
|
gst_element_class_add_pad_template (element_class,
|
|
|
|
gst_static_pad_template_get (&sink_factory));
|
|
|
|
}
|
2005-07-01 12:43:03 +00:00
|
|
|
<!-- example-end boilerplate.c g -->
|
|
|
|
<!-- example-begin boilerplate.c h --><!--
|
|
|
|
static void
|
|
|
|
gst_my_filter_class_init (GstMyFilterClass * klass)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_my_filter_init (GstMyFilter * filter)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "register.func"
|
|
|
|
--><!-- example-end boilerplate.c h --></programlisting>
|
2004-01-28 10:03:51 +00:00
|
|
|
<para>
|
|
|
|
The last argument in a template is its type
|
|
|
|
or list of supported types. In this example, we use 'ANY', which means
|
|
|
|
that this element will accept all input. In real-life situations, you
|
|
|
|
would set a mimetype and optionally a set of properties to make sure
|
|
|
|
that only supported input will come in. This representation should be
|
|
|
|
a string that starts with a mimetype, then a set of comma-separates
|
|
|
|
properties with their supported values. In case of an audio filter that
|
|
|
|
supports raw integer 16-bit audio, mono or stereo at any samplerate, the
|
|
|
|
correct template would look like this:
|
|
|
|
</para>
|
|
|
|
<programlisting>
|
|
|
|
static GstStaticPadTemplate sink_factory =
|
|
|
|
GST_STATIC_PAD_TEMPLATE (
|
|
|
|
"sink",
|
|
|
|
GST_PAD_SINK,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS (
|
|
|
|
"audio/x-raw-int, "
|
|
|
|
"width = (int) 16, "
|
|
|
|
"depth = (int) 16, "
|
|
|
|
"endianness = (int) BYTE_ORDER, "
|
|
|
|
"channels = (int) { 1, 2 }, "
|
|
|
|
"rate = (int) [ 8000, 96000 ]"
|
|
|
|
)
|
|
|
|
);
|
|
|
|
</programlisting>
|
|
|
|
<para>
|
2004-11-23 23:03:10 +00:00
|
|
|
Values surrounded by curly brackets (<quote>{</quote> and
|
|
|
|
<quote>}</quote>) are lists, values surrounded by square brackets
|
|
|
|
(<quote>[</quote> and <quote>]</quote>) are ranges.
|
2004-01-28 10:03:51 +00:00
|
|
|
Multiple sets of types are supported too, and should be separated by
|
|
|
|
a semicolon (<quote>;</quote>). Later, in the chapter on pads, we will
|
|
|
|
see how to use types to know the exact format of a stream:
|
2004-01-28 15:51:14 +00:00
|
|
|
<xref linkend="chapter-building-pads"/>.
|
2004-01-28 10:03:51 +00:00
|
|
|
</para>
|
2002-09-27 18:34:33 +00:00
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<!-- ############ sect1 ############# -->
|
|
|
|
|
2004-01-28 15:51:14 +00:00
|
|
|
<sect1 id="section-boiler-constructors">
|
2002-09-27 18:34:33 +00:00
|
|
|
<title>Constructor Functions</title>
|
|
|
|
<para>
|
2004-01-27 13:33:39 +00:00
|
|
|
Each element has three functions which are used for construction of an
|
|
|
|
element. These are the <function>_base_init()</function> function which
|
|
|
|
is meant to initialize class and child class properties during each new
|
|
|
|
child class creation; the <function>_class_init()</function> function,
|
|
|
|
which is used to initialise the class only once (specifying what signals,
|
|
|
|
arguments and virtual functions the class has and setting up global
|
|
|
|
state); and the <function>_init()</function> function, which is used to
|
|
|
|
initialise a specific instance of this type.
|
2002-09-27 18:34:33 +00:00
|
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<!-- ############ sect1 ############# -->
|
|
|
|
|
2004-01-28 15:51:14 +00:00
|
|
|
<sect1 id="section-boiler-plugininit">
|
2002-09-27 18:34:33 +00:00
|
|
|
<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
|
2004-01-27 13:33:39 +00:00
|
|
|
called as soon as the plugin is loaded, and should return TRUE or FALSE
|
|
|
|
depending on whether it loaded initialized any dependencies correctly.
|
|
|
|
Also, in this function, any supported element type in the plugin should
|
|
|
|
be registered.
|
2002-09-27 18:34:33 +00:00
|
|
|
</para>
|
2005-07-01 12:43:03 +00:00
|
|
|
<programlisting><!-- example-begin register.func -->
|
2004-01-28 09:07:11 +00:00
|
|
|
static gboolean
|
|
|
|
plugin_init (GstPlugin *plugin)
|
|
|
|
{
|
|
|
|
return gst_element_register (plugin, "my_filter",
|
|
|
|
GST_RANK_NONE,
|
|
|
|
GST_TYPE_MY_FILTER);
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_PLUGIN_DEFINE (
|
|
|
|
GST_VERSION_MAJOR,
|
|
|
|
GST_VERSION_MINOR,
|
|
|
|
"my_filter",
|
|
|
|
"My filter plugin",
|
|
|
|
plugin_init,
|
|
|
|
VERSION,
|
|
|
|
"LGPL",
|
|
|
|
"GStreamer",
|
|
|
|
"http://gstreamer.net/"
|
|
|
|
)
|
2005-07-01 12:43:03 +00:00
|
|
|
<!-- example-end register.func --></programlisting>
|
2002-09-27 18:34:33 +00:00
|
|
|
<para>
|
|
|
|
Note that the information returned by the plugin_init() function will be
|
2003-01-05 22:47:42 +00:00
|
|
|
cached in a central registry. For this reason, it is important that the
|
|
|
|
same information is always returned by the function: for example, it
|
2004-01-27 13:33:39 +00:00
|
|
|
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.
|
2002-09-27 18:34:33 +00:00
|
|
|
</para>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|