docs/pwg/advanced_types.xml: Finish documenting the current state of mimetypes.

Original commit message from CVS:
2004-01-27  Ronald Bultje  <rbultje@ronald.bitfreak.net>

* docs/pwg/advanced_types.xml:
Finish documenting the current state of mimetypes.
* docs/pwg/building_boiler.xml:
* docs/pwg/building_chainfn.xml:
* docs/pwg/building_pads.xml:
* docs/pwg/building_props.xml:
* docs/pwg/building_testapp.xml:
Start documenting the "how to build a simple audio filter" part
of the PWG. Most stuff is ready by now. Stuff remaining: signals,
states and (maybe?) a short introduction to capsnego in the chapter
on pads (building_pads.xml). Capsnego should probably be explained
fully in advanced_capsnego.xml or so.
This commit is contained in:
Ronald S. Bultje 2004-01-27 13:33:39 +00:00
parent 3607f4f024
commit 8e29a5888a
7 changed files with 1183 additions and 93 deletions

View file

@ -1,3 +1,18 @@
2004-01-27 Ronald Bultje <rbultje@ronald.bitfreak.net>
* docs/pwg/advanced_types.xml:
Finish documenting the current state of mimetypes.
* docs/pwg/building_boiler.xml:
* docs/pwg/building_chainfn.xml:
* docs/pwg/building_pads.xml:
* docs/pwg/building_props.xml:
* docs/pwg/building_testapp.xml:
Start documenting the "how to build a simple audio filter" part
of the PWG. Most stuff is ready by now. Stuff remaining: signals,
states and (maybe?) a short introduction to capsnego in the chapter
on pads (building_pads.xml). Capsnego should probably be explained
fully in advanced_capsnego.xml or so.
2004-01-26 David Schleef <ds@schleef.org>
* gst/gstpad.c: (gst_pad_try_set_caps_nonfixed):

View file

@ -92,13 +92,33 @@
<title>List of Defined Types</title>
<para>
Below is a list of all the defined types in &GStreamer;. They are split
up in separate tables for audio, video, container, text and other
up in separate tables for audio, video, container, subtitle and other
types, for the sake of readability. Below each table might follow a
list of notes that apply to that table. In the definition of each type,
we try to follow the types and rules as defined by <ulink type="http"
url="http://www.isi.edu/in-notes/iana/assignments/media-types/media-types">
IANA</ulink> for as far as possible.
</para>
<para>
Jump directly to a specific table:
<itemizedlist>
<listitem>
<para><xref linkend="table-audio-types"/></para>
</listitem>
<listitem>
<para><xref linkend="table-video-types"/></para>
</listitem>
<listitem>
<para><xref linkend="table-container-types"/></para>
</listitem>
<listitem>
<para><xref linkend="table-subtitle-types"/></para>
</listitem>
<listitem>
<para><xref linkend="table-other-types"/></para>
</listitem>
</itemizedlist>
</para>
<para>
Note that many of the properties are not <emphasis>required</emphasis>,
but rather <emphasis>optional</emphasis> properties. This means that
@ -110,7 +130,9 @@
content. Example: the AVI header provides samplerate of the contained
audio stream in the header. MPEG system streams don't. This means that
an AVI stream demuxer would provide samplerate as a property for MPEG
audio streams, whereas an MPEG demuxer would not.
audio streams, whereas an MPEG demuxer would not. A decoder needing
this data would require a stream parser in between two extract this
from the header or calculate it from the stream.
</para>
<table frame="all" id="table-audio-types" xreflabel="Table of Audio Types">
@ -433,20 +455,6 @@
<!-- ############ type ############# -->
<row>
<entry>audio/x-pn-realaudio</entry>
<entry>Real Audio data.</entry>
<entry>raversion</entry>
<entry>integer</entry>
<entry>1 or 2</entry>
<entry>
The version of the Real Audio codec used to encode the stream.
1 stands for a 14k4 stream, 2 stands for a 28k8 stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>audio/x-qdm2</entry>
<entry>Data encoded by the QDM version 2 codec.</entry>
@ -461,6 +469,20 @@
<!-- ############ type ############# -->
<row>
<entry>audio/x-pn-realaudio</entry>
<entry>Realmedia Audio data.</entry>
<entry>raversion</entry>
<entry>integer</entry>
<entry>1 or 2</entry>
<entry>
The version of the Real Audio codec used to encode the stream.
1 stands for a 14k4 stream, 2 stands for a 28k8 stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>audio/x-speex</entry>
<entry>Data encoded by the Speex audio codec</entry>
@ -502,7 +524,7 @@
</tbody>
</tgroup>
</table>
<table frame="all" id="table-video-types" xreflabel="Table of Video Types">
<title>Table of Video Types</title>
<tgroup cols="6" align="left" colsep="1" rowsep="1">
@ -650,6 +672,20 @@
<!-- ############ type ############# -->
<row>
<entry>video/x-3ivx</entry>
<entry>3ivx video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-divx</entry>
<entry>DivX video.</entry>
@ -660,8 +696,504 @@
Version of the DivX codec used to encode the stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-dx</entry>
<entry>Digital Video.</entry>
<entry>systemstream</entry>
<entry>boolean</entry>
<entry>FALSE</entry>
<entry>
Indicates that this stream is <emphasis>not</emphasis> a system
container stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-ffv</entry>
<entry>FFMpeg video.</entry>
<entry>ffvversion</entry>
<entry>integer</entry>
<entry>1</entry>
<entry>
Version of the FFMpeg video codec used to encode the stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-h263</entry>
<entry>H-263 video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-h264</entry>
<entry>H-264 video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-huffyuv</entry>
<entry>Huffyuv video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-indeo</entry>
<entry>Indeo video.</entry>
<entry>indeoversion</entry>
<entry>integer</entry>
<entry>3</entry>
<entry>
Version of the Indeo codec used to encode this stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-jpeg</entry>
<entry>Motion-JPEG video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type. Note that video/x-jpeg only applies to Motion-JPEG
pictures (YUY2 colourspace). RGB colourspace JPEG images are
referred to as image/jpeg (JPEG image).
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry morerows="1">video/mpeg</entry>
<entry morerows="1">MPEG video.</entry>
<entry>mpegversion</entry>
<entry>integer</entry>
<entry>1, 2 or 4</entry>
<entry>
Version of the MPEG codec that this stream was encoded with.
Note that we have different mimetypes for 3ivx, XviD, DivX and
"standard" ISO MPEG-4. This is <emphasis>not</emphasis> a good
thing and we're fully aware of this. However, we do not have a
solution yet.
</entry>
</row>
<row>
<entry>systemstream</entry>
<entry>boolean</entry>
<entry>FALSE</entry>
<entry>
Indicates that this stream is <emphasis>not</emphasis> a system
container stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-msmpeg</entry>
<entry>Microsoft MPEG-4 video deviations.</entry>
<entry>msmpegversion</entry>
<entry>integer</entry>
<entry>41, 42 or 43</entry>
<entry>
Version of the MS-MPEG-4-like codec that was used to encode this
version. A value of 41 refers to MS MPEG 4.1, 42 to 4.2 and 43
to version 4.3.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-pn-realvideo</entry>
<entry>Realmedia video.</entry>
<entry>rmversion</entry>
<entry>integer</entry>
<entry>1, 2 or 3</entry>
<entry>
Version of the Real Video codec that this stream was encoded
with.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-svq</entry>
<entry>Sorensen Video.</entry>
<entry>svqversion</entry>
<entry>integer</entry>
<entry>1 or 3</entry>
<entry>
Version of the Sorensen codec that the stream was encoded with.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-tarkin</entry>
<entry>Tarkin video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-theora</entry>
<entry>Theora video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-vp3</entry>
<entry>VP-3 video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type. Note that we have different mimetypes for VP-3 and
Theora, which is not necessarily a good idea. This could probably
be improved.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-wmv</entry>
<entry>Windows Media Video.</entry>
<entry>wmvversion</entry>
<entry>integer</entry>
<entry>1 or 2</entry>
<entry>
Version of the WMV codec that the stream was encoded with.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-xvid</entry>
<entry>XviD video.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ subtitle ############# -->
<row>
<entry spanname="fullwidth">
<emphasis>All image types.</emphasis>
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>image/jpeg</entry>
<entry>Joint Picture Expert Group Image.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type. Note that image/jpeg only applies to RGB-colourspace
JPEG images; YUY2-colourspace JPEG pictures are referred to as
video/x-jpeg ("Motion JPEG").
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>image/png</entry>
<entry>Portable Network Graphics Image.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
</tbody>
</tgroup>
</table>
<table frame="all" id="table-container-types" xreflabel="Table of Container Types">
<title>Table of Container Types</title>
<tgroup cols="6" align="left" colsep="1" rowsep="1">
<colspec colnum="1" colname="colc1" colwidth="1*"/>
<colspec colnum="6" colname="colc6" colwidth="6*"/>
<spanspec spanname="fullwidth" namest="colc1" nameend="colc6"/>
<thead>
<row>
<entry>Mime Type</entry>
<entry>Description</entry>
<entry>Property</entry>
<entry>Property Type</entry>
<entry>Property Values</entry>
<entry>Property Description</entry>
</row>
</thead>
<tbody valign="top">
<!-- ############ type ############# -->
<row>
<entry>video/x-ms-asf</entry>
<entry>Advanced Streaming Format (ASF).</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-msvideo</entry>
<entry>AVI.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-dv</entry>
<entry>Digital Video.</entry>
<entry>systemstream</entry>
<entry>boolean</entry>
<entry>TRUE</entry>
<entry>
Indicates that this is a container system stream rather than an
elementary video stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-matroska</entry>
<entry>Matroska.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/mpeg</entry>
<entry>Motion Pictures Expert Group System Stream.</entry>
<entry>systemstream</entry>
<entry>boolean</entry>
<entry>TRUE</entry>
<entry>
Indicates that this is a container system stream rather than an
elementary video stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>application/ogg</entry>
<entry>Ogg.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/quicktime</entry>
<entry>Quicktime.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>video/x-pn-realvideo</entry>
<entry>Digital Video.</entry>
<entry>systemstream</entry>
<entry>boolean</entry>
<entry>TRUE</entry>
<entry>
Indicates that this is a container system stream rather than an
elementary video stream.
</entry>
</row>
<!-- ############ type ############# -->
<row>
<entry>audio/x-wav</entry>
<entry>WAV.</entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
There are currently no specific properties defined or needed for
this type.
</entry>
</row>
</tbody>
</tgroup>
</table>
<table frame="all" id="table-subtitle-types" xreflabel="Table of Subtitle Types">
<title>Table of Subtitle Types</title>
<tgroup cols="6" align="left" colsep="1" rowsep="1">
<colspec colnum="1" colname="colt1" colwidth="1*"/>
<colspec colnum="6" colname="colt6" colwidth="6*"/>
<spanspec spanname="fullwidth" namest="colt1" nameend="colt6"/>
<thead>
<row>
<entry>Mime Type</entry>
<entry>Description</entry>
<entry>Property</entry>
<entry>Property Type</entry>
<entry>Property Values</entry>
<entry>Property Description</entry>
</row>
</thead>
<tbody valign="top">
<!-- ############ type ############# -->
<row>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
None defined yet.
</entry>
</row>
</tbody>
</tgroup>
</table>
<table frame="all" id="table-other-types" xreflabel="Table of Other Types">
<title>Table of Other Types</title>
<tgroup cols="6" align="left" colsep="1" rowsep="1">
<colspec colnum="1" colname="colo1" colwidth="1*"/>
<colspec colnum="6" colname="colo6" colwidth="6*"/>
<spanspec spanname="fullwidth" namest="colo1" nameend="colo6"/>
<thead>
<row>
<entry>Mime Type</entry>
<entry>Description</entry>
<entry>Property</entry>
<entry>Property Type</entry>
<entry>Property Values</entry>
<entry>Property Description</entry>
</row>
</thead>
<tbody valign="top">
<!-- ############ type ############# -->
<row>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry>
None defined yet.
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
</chapter>

View file

@ -33,10 +33,10 @@
</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
<prompt>shell $ </prompt><userinput>cvs -d:pserver:anonymous@cvs.freedesktop.org:/home/cvs/gstreamer login</userinput>
Logging in to :pserver:anonymous@cvs.freedesktop.org:2401/home/cvs/gstreamer
CVS password:
<prompt>shell $ </prompt><userinput>cvs -z3 -d:pserver:anonymous@cvs.gstreamer.sourceforge.net:/cvsroot/gstreamer co gst-template</userinput>
<prompt>shell $ </prompt><userinput>cvs -z3 -d:pserver:anonymous@cvs.freedesktop.org:/home/cvs/gstreamer co gst-template</userinput>
U gst-template/README
U gst-template/gst-app/AUTHORS
U gst-template/gst-app/ChangeLog
@ -136,9 +136,9 @@ U gst-template/gst-app/src/Makefile.am
struct _GstExample {
GstElement element;
GstPad *sinkpad,*srcpad;
GstPad *sinkpad, *srcpad;
gint8 active;
gboolean silent;
};
/* Standard definition defining a class for this element. */
@ -160,7 +160,7 @@ U gst-template/gst-app/src/Makefile.am
(GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EXAMPLE))
/* Standard function returning type information. */
GtkType gst_example_get_type(void);
GType gst_example_get_type (void);
</programlisting>
</example>
</sect1>
@ -213,35 +213,105 @@ U gst-template/gst-app/src/Makefile.am
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 &lt;your.name@your.isp&gt;",
"(C) 2001",
static GstElementDetails example_details = {
"An example plugin",
"Example/FirstExample",
"Shows the basic structure of a plugin",
"your name &lt;your.name@your.isp&gt;"
};
</programlisting>
<para>
The element details are registered with the plugin during
<function>_base_init ()</function>.
</para>
<programlisting>
static void
gst_my_filter_base_init (GstMyFilterClass *klass)
{
static GstElementDetails my_filter_details = {
[..]
};
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
[..]
gst_element_class_set_details (element_class, &amp;my_filter_details);
}
</programlisting>
</sect1>
<!-- ############ sect1 ############# -->
<sect1 id="sect1-boiler-padtemplates">
<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>
<programlisting>
static GstStaticPadTemplate sink_factory =
GST_STATIC_PAD_TEMPLATE (
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("ANY")
);
</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
for more details on this.
</para>
<programlisting>
static void
gst_my_filter_base_init (GstMyFilterClass *klass)
{
static GstStaticPadTemplate sink_factory =
[..]
, src_factory =
[..]
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&amp;src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&amp;sink_factory));
[..]
}
</programlisting>
</sect1>
@ -250,11 +320,14 @@ U gst-template/gst-app/src/Makefile.am
<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.
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.
</para>
</sect1>
@ -265,36 +338,20 @@ U gst-template/gst-app/src/Makefile.am
<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 required that these functions are used, as
documented below, rather than attempting to access the structure directly.
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.
</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.
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>

View file

@ -4,5 +4,73 @@
<chapter id="cha-building-chainfn">
<title>The chain function</title>
<para>
The chain function is the function in which all data processing takes
place. In the case of a simple filter, <function>_chain ()</function>
functions are mostly lineair functions - so for each incoming buffer,
one buffer will go out, too. Below is a very simple implementation of
a chain function:
</para>
<programlisting>
static void
gst_my_filter_chain (GstPad *pad,
GstData *data)
{
GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
GstBuffer *buf = GST_BUFFER (data);
if (!filter->silent)
g_print ("Have data of size %u bytes!\n", GST_BUFFER_SIZE (buf));
gst_pad_push (filter->srcpad, GST_DATA (buf));
}
</programlisting>
<para>
Obviously, the above doesn't do much useful. Instead of printing that the
data is in, you would normally process the data there. Remember, however,
that buffers are not always writable. In more advanced elements (the ones
that do event processing), the incoming data might not even be a buffer.
</para>
<programlisting>
static void
gst_my_filter_chain (GstPad *pad,
GstData *data)
{
GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
GstBuffer *buf, *outbuf;
if (GST_IS_EVENT (data)) {
GstEvent *event = GST_EVENT (data);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
/* end-of-stream, we should close down all stream leftovers here */
gst_my_filter_stop_processing (filter);
/* fall-through to default event handling */
default:
gst_pad_event_default (pad, event);
break;
}
return;
}
buf = GST_BUFFER (data);
outbuf = gst_my_filter_process_data (buf);
gst_buffer_unref (buf);
if (!outbuf) {
/* something went wrong - signal an error */
gst_element_error (GST_ELEMENT (filter), STREAM, FAILED, (NULL), (NULL));
return;
}
gst_pad_push (filter->srcpad, GST_DATA (outbuf));
}
</programlisting>
<para>
In some cases, it might be useful for an element to have control over the
input data rate, too. In that case, you probably want to write a so-called
<emphasis>loop-based</emphasis> element. Source elements (with only source
pads) can also be <emphasis>get-based</emphasis> elements. These concepts
will be explained in the advanced section of this guide, and in the section
that specifically discusses source pads.
</para>
</chapter>

View file

@ -4,6 +4,192 @@
<chapter id="cha-building-pads">
<title>Specifying the pads</title>
<para>
As explained before, pads are the port through which data goes in and out
of your element, and that makes them a very important item in the process
of element creation. In the boilerplate code, we have seen how static pad
templates take care of registering pad templates with the element class.
Here, we will see how to create actual elements, use <function>_link ()</function>
and <function>_getcaps ()</function> functions to let other elements know
their capabilities and how to register functions to let data flow through
the element.
</para>
<para>
In the element <function>_init ()</function> function, you create the pad
from the pad template that has been registered with the element class in
the <function>_base_init ()</function> function. After creating the pad,
you have to set a <function>_link ()</function> function pointer and a
<function>_getcaps ()</function> function pointer. Optionally, you can
set a <function>_chain ()</function> function pointer (on sink pads in
filter and sink elements) through which data will come in to the element,
or (on source pads in source elements) a <function>_get ()</function>
function pointer through which data will be pulled from the element. After
that, you have to register the pad with the element. This happens like
this:
</para>
<programlisting>
static GstPadLinkReturn gst_my_filter_link (GstPad *pad,
const GstCaps *caps);
static GstCaps * gst_my_filter_getcaps (GstPad *pad);
static void gst_my_filter_chain (GstPad *pad,
GstData *data);
static void
gst_my_filter_init (GstMyFilter *filter)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter);
/* pad through which data comes in to the element */
filter->sinkpad = gst_pad_new_from_template (
gst_element_class_get_pad_template (klass, "sink"), "sink");
gst_pad_set_link_function (filter->sinkpad, gst_my_filter_link);
gst_pad_set_getcaps_function (filter->sinkpad, gst_my_filter_getcaps);
gst_pad_set_chain_function (filter->sinkpad, gst_my_filter_chain);
gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
/* pad through which data goes out of the element */
filter->srcpad = gst_pad_new_from_template (
gst_element_class_get_pad_template (klass, "src"), "src");
gst_pad_set_link_function (filter->srcpad, gst_my_filter_link);
gst_pad_set_getcaps_function (filter->srcpad, gst_my_filter_getcaps);
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
[..]
}
</programlisting>
<para>
The <function>_link ()</function> is called during caps negotiation. This
is the process where the linked pads decide on the streamtype that will
transfer between them. A full list of type-definitions can be found in
<xref linkend="cha-building-types"/>. A <function>_link ()</function>
receives a pointer to a <classname>GstCaps</classname> struct that
defines the proposed streamtype, and can respond with either
<quote>yes</quote> (<classname>GST_PAD_LINK_OK</classname>),
<quote>no</quote> (<classname>GST_PAD_LINK_REFUSED</classname>) or
<quote>don't know yet</quote> (<classname>GST_PAD_LINK_DELAYED</classname>).
If the element responds positively towards the streamtype, that type
will be used on the pad. An example:
</para>
<programlisting>
static GstPadLinkReturn
gst_my_filter_link (GstPad *pad,
const GstCaps *caps)
{
GstStructure *structure = gst_caps_get_structure (caps, 0);
GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad :
filter->srcpad;
GstPadLinkReturn ret;
const gchar *mime;
/* Since we're an audio filter, we want to handle raw audio
* and from that audio type, we need to get the samplerate and
* number of channels. */
mime = gst_structure_get_name (structure);
if (strcmp (mime, "audio/x-raw-int") != 0) {
GST_WARNING ("Wrong mimetype %s provided, we only support %s",
mime, "audio/x-raw-int");
return GST_PAD_LINK_REFUSED;
}
/* we're a filter and don't touch the properties of the data.
* That means we can set the given caps unmodified on the next
* element, and use that negotiation return value as ours. */
ret = gst_pad_try_set_caps (otherpad, gst_caps_copy (caps));
if (GST_PAD_LINK_FAILED (ret))
return ret;
/* Capsnego succeeded, get the stream properties for internal
* usage and return success. */
gst_structure_get_int (structure, "rate", &amp;filter->samplerate);
gst_structure_get_int (structure, "channels", &amp;filter->channels);
g_print ("Caps negotiation succeeded with %d Hz @ %d channels\n",
filter->samplerate, filter->channels);
return ret;
}
</programlisting>
<para>
If your <function>_link ()</function> function does not need to perform
any specific operation (i.e. it will only forward caps), you can set it
to <function>gst_pad_proxy_link</function>. This is a link forwarding
function implementation provided by the core. It is useful for elements
such as <classname>identity</classname>.
</para>
<para>
The <function>_getcaps ()</function> funtion is used to request the list
of supported formats and properties from the element. In some cases, this
will be equal to the formats provided by the pad template, in which case
this function can be omitted. In some cases, too, it will not depend on
anything inside this element, but it will rather depend on the input from
another element linked to this element's sink or source pads. In that case,
you can use <function>gst_pad_proxy_getcaps</function> as implementation,
it provides getcaps forwarding in the core. However, in many cases, the
format supported by this element cannot be defined externally, but is
more specific than those provided by the pad template. In this case, you
should use a <function>_getcaps ()</function> function. In the case as
specified below, we assume that our filter is able to resample sound, so
it would be able to provide any samplerate (indifferent from the samplerate
specified on the other pad) on both pads. It explains how a
<function>_getcaps ()</function> can be used to do this.
</para>
<programlisting>
static GstCaps *
gst_my_filter_getcaps (GstPad *pad)
{
GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad :
filter->srcpad;
GstCaps *othercaps = gst_pad_get_allowed_caps (otherpad), *caps;
gint n;
if (gst_caps_is_empty (othercaps))
return othercaps;
/* We support *any* samplerate, indifferent from the samplerate
* supported by the linked elements on both sides. */
for (i = 0; i < gst_caps_get_size (othercaps); i++) {
GstStructure *structure = gst_caps_get_structure (othercaps, i);
gst_structure_remove_field (structure, "rate");
}
caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad));
gst_caps_free (othercaps);
return caps;
}
</programlisting>
<para>
Obviously, many elements will not need this complex mechanism, because they
are much simpler than that. They only support one format, or their format
is fixed but the contents of the format depend on the stream or something
else. In those cases, <emphasis>explicit caps</emphasis> are an easy way
of handling caps. Explicit caps are an easy way of specifying one, fixed,
supported format on a pad. Pads using explicit caps do not implement their
own <function>_getcaps ()</function> or <function>_link ()</function>
functions. When the exact format is known, an elements uses
<function>gst_pad_set_explicit_caps ()</function> to specify the exact
format. This is very useful for demuxers, for example.
</para>
<programlisting>
static void
gst_my_filter_init (GstMyFilter *filter)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter);
[..]
filter->srcpad = gst_pad_new_from_template (
gst_element_class_get_pad_template (klass, "src"), "src");
gst_pad_use_explicit_caps (filter->srcpad);
[..]
}
static void
gst_my_filter_somefunction (GstMyFilter *filter)
{
GstCaps *caps = ..;
[..]
gst_pad_set_explicit_caps (filter->srcpad, caps);
[..]
}
</programlisting>
</chapter>

View file

@ -3,7 +3,143 @@
<chapter id="cha-building-args" xreflabel="Adding Arguments">
<title>Adding Arguments</title>
<para>
Define arguments in enum.
The primary and most important way of controlling how an element behaves,
is through GObject properties. GObject properties are defined in the
<function>_class_init ()</function> function. The element optionally
implements a <function>_get_property ()</function> and a
<function>_set_property ()</function> function. These functions will be
notified if an application changes or requests the value of a property,
and can then fill in the value or take action required for that property
to change value internally.
</para>
</chapter>
<programlisting>
/* properties */
enum {
ARG_0,
ARG_SILENT
/* FILL ME */
};
static void gst_my_filter_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gst_my_filter_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void
gst_my_filter_class_init (GstMyFilterClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
/* define properties */
g_object_class_install_property (object_class, ARG_SILENT,
g_param_spec_boolean ("silent", "Silent",
"Whether to be very verbose or not",
FALSE, G_PARAM_READWRITE));
/* define virtual function pointers */
object_class->set_property = gst_my_filter_set_property;
object_class->get_property = gst_my_filter_get_property;
}
static void
gst_my_filter_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GstMyFilter *filter = GST_MY_FILTER (object);
switch (prop_id) {
case ARG_SILENT:
filter->silent = g_value_get_boolean (value);
g_print ("Silent argument was changed to %s\n",
filter->silent ? "true" : "false");
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_my_filter_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GstMyFilter *filter = GST_MY_FILTER (object);
switch (prop_id) {
case ARG_SILENT:
g_value_set_boolean (value, filter->silent);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
</programlisting>
<para>
The above is a very simple example of how arguments are used. Graphical
applications - for example GStreamer Editor - will use these properties
and will display a user-controlleable widget with which these properties
can be changed. This means that - for the property to be as user-friendly
as possible - you should be as exact as possible in the definition of the
property. Not only in defining ranges in between which valid properties
can be located (for integers, floats, etc.), but also in using very
descriptive (better yet: internationalized) strings in the definition of
the property, and if possible using enums and flags instead of integers.
The GObject documentation describes these in a very complete way, but
below, we'll give a short example of where this is useful. Note that using
integers here would probably completely confuse the user, because they
make no sense in this context. The example is stolen from videotestsrc.
</para>
<programlisting>
typedef enum {
GST_VIDEOTESTSRC_SMPTE,
GST_VIDEOTESTSRC_SNOW,
GST_VIDEOTESTSRC_BLACK
} GstVideotestsrcPattern;
[..]
#define GST_TYPE_VIDEOTESTSRC_PATTERN (gst_videotestsrc_pattern_get_type ())
static GType
gst_videotestsrc_pattern_get_type (void)
{
static GType videotestsrc_pattern_type = 0;
if (!videotestsrc_pattern_type) {
static GEnumValue pattern_types[] = {
{ GST_VIDEOTESTSRC_SMPTE, "smpte", "SMPTE 100% color bars" },
{ GST_VIDEOTESTSRC_SNOW, "snow", "Random (television snow)" },
{ GST_VIDEOTESTSRC_BLACK, "black", "0% Black" },
{ 0, NULL, NULL },
};
videotestsrc_pattern_type =
g_enum_register_static ("GstVideotestsrcPattern",
pattern_types);
}
return videotestsrc_pattern_type;
}
[..]
static void
gst_videotestsrc_class_init (GstvideotestsrcClass *klass)
{
[..]
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TYPE,
g_param_spec_enum ("pattern", "Pattern",
"Type of test pattern to generate",
GST_TYPE_VIDEOTESTSRC_PATTERN, 1, G_PARAM_READWRITE));
[..]
}
</programlisting>
</chapter>

View file

@ -1,25 +1,121 @@
<chapter id="cha-testapp-init">
<title>Initialization</title>
<para>
</para>
</chapter>
<!-- ############ chapter ############# -->
<chapter id="cha-testapp-inst">
<title>Instantiating the plugins</title>
<chapter id="cha-building-testapp">
<title>Building a Test Application</title>
<para>
(NOTE: we really should have a debugging Sink)
Often, you will want to test your newly written plugin in an as small
setting as possible. Ususally, <filename>gst-launch</filename> is a
good first step at testing a plugin. However, you will often need more
testing features than gst-launch can provide, such as seeking, events,
interactivity and more. Writing your own small testing program is the
easiest way to accomplish this. This section explains - in a few words
- how to do that. For a complete application development guide, see the
<ulink type="http" url="../manual/index.html">Application Development
Manual</ulink>.
</para>
</chapter>
<chapter id="cha-testapp-link">
<title>Linking the plugins</title>
<para>
</para>
</chapter>
<sect1 id="cha-testapp-init" xreflabel="Initialization">
<title>Initialization</title>
<para>
At the start, you need to initialize the &GStreamer; core library by
calling <function>gst_init ()</function>. You can alternatively call
<function>gst_init_with_popt_tables ()</function>, which will return
a pointer to popt tables. You can then use libpopt to handle the
given argument table, and this will finish the &GStreamer; intialization.
</para>
</sect1>
<chapter id="cha-testapp-running">
<title>Running the pipeline</title>
<para>
</para>
</chapter>
<sect1 id="cha-testapp-inst" xreflabel="Instantiating the plugins">
<title>Instantiating the plugins</title>
<para>
You can create elements using <function>gst_element_factory_make ()</function>,
where the first argument is the element type that you want to create,
and the second argument is a free-form name. The example at the end uses
a simple filesource - decoder - soundcard output pipeline, but you can
use specific debugging elements if that's necessary. For example, an
<classname>identity</classname> element can be used in the middle of
the pipeline to act as a data-to-application transmitter. This can be
used to check the data for misbehaviours or correctness in your test
application. Also, you can use a <classname>fakesink</classname>
element at the end of the pipeline to dump your data to the stdout
(in order to do this, set the <function>dump</function> property to
TRUE). Lastly, you can use the <classname>efence</classname> element
(indeed, an eletric fence memory debugger wrapper element) to check
for memory errors.
</para>
</sect1>
<sect1 id="cha-testapp-link" xreflabel="Linking the plugins">
<title>Linking the plugins</title>
<para>
During linking, your test application can use fixation or filtered caps
as a way to drive a specific type of data to or from your element. This
is a very simple and effective way of checking multiple types of input
and output in your element.
</para>
</sect1>
<sect1 id="cha-testapp-running" xreflabel="Running the pipeline">
<title>Running the pipeline</title>
<para>
Running the pipeline happens through the <function>gst_bin_iterate ()</function>
function. Note that during running, you should connect to at least the
<quote>error</quote> and <quote>eos</quote> signals on the pipeline
and/or your plugin/element to check for correct handling of this. Also,
you should add events into the pipeline and make sure your plugin handles
these correctly (with respect to clocking, internal caching, etc.).
</para>
</sect1>
<sect1 id="cha-testapp-cleanup" xreflabel="Cleaning up the memory">
<title>Cleaning up the memory</title>
<para>
Never forget to clean up memory in your plugin or your test application.
When going to the NULL state, your element should clean up allocated
memory and caches. Also, it should close down any references held to
possible support libraries. Your application should <function>unref ()</function>
the pipeline and make sure it doesn't crash.
</para>
</sect1>
<sect1 id="cha-testapp-all" xreflabel="Summary">
<title>Summary</title>
<programlisting>
#include &lt;gst/gst.h&gt;
gint
main (gint arcg,
gchar *argv[])
{
GstElement *pipeline, *filesrc, *decoder, *filter, *sink;
/* initialization */
gst_init (&amp;argc, &amp;argv);
/* create elements */
pipeline = gst_pipeline_new ("my_pipeline");
filesrc = gst_element_factory_make ("filesrc", "my_filesource");
decoder = gst_element_factory_make ("mad", "my_decoder");
filter = gst_element_factory_make ("my_filter", "my_filter");
sink = gst_element_factory_make ("osssink", "audiosink");
g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
/* link everything together */
gst_element_link_many (filesrc, decoder, filter, sink, NULL);
gst_bin_add_many (GST_BIN (pipeline), filesrc, decoder, filter, sink, NULL);
/* run */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
while (gst_bin_iterate (GST_BIN (pipeline)));
/* clean up */
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
</programlisting>
</sect1>
</chapter>