+++ /dev/null
-<chapter id="cha-dparam-start">
- <title>Getting Started</title>
-
- <para>
- The dparams subsystem is contained within the <filename>gstcontrol</filename> library.
- You need to include the header in your element's source file:
- </para>
- <programlisting>
- #include <gst/control/control.h>
- </programlisting>
-
- <para>
- Even though the <filename>gstcontrol</filename> library may be linked into the host
- application, you should make sure it is loaded in your <filename>plugin_init</filename>
- function:
- </para>
- <programlisting>
- static gboolean
- plugin_init (GModule *module, GstPlugin *plugin)
- {
- ...
-
- /* load dparam support library */
- if (!gst_library_load ("gstcontrol"))
- {
- gst_info ("example: could not load support library: 'gstcontrol'\n");
- return FALSE;
- }
-
- ...
- }
- </programlisting>
-
- <para>
- You need to store an instance of <filename>GstDParamManager</filename> in your element's struct:
- </para>
- <programlisting>
- struct _GstExample {
- GstElement element;
- ...
-
- GstDParamManager *dpman;
-
- ...
- };
- </programlisting>
-
- <para>
- The <filename>GstDParamManager</filename> can be initialised in your element's
- init function:
- </para>
- <programlisting>
- static void
- gst_example_init (GstExample *example)
- {
- ...
-
- example->dpman = gst_dpman_new ("example_dpman", GST_ELEMENT(example));
-
- ...
- }
- </programlisting>
-
-</chapter>
-
-<chapter id="cha-dparam-define">
- <title>Defining Parameter Specificiations</title>
- <para>
- You can define the dparams you need anywhere within your element but will usually
- need to do so in only a couple of places:
- <itemizedlist>
- <listitem>
- In the element <filename>init</filename> function,
- just after the call to <filename>gst_dpman_new</filename>
- </listitem>
- <listitem>
- Whenever a new pad is created so that parameters can affect data going into
- or out of a specific pad. An example of this would be a mixer element where
- a seperate volume parameter is needed on every pad.
- </listitem>
- </itemizedlist>
- </para>
- <para>
- There are three different ways the dparams subsystem can pass parameters into your element.
- Which one you use will depend on how that parameter is used within your element.
- Each of these methods has its own function to define a required dparam:
- <itemizedlist>
- <listitem><filename>gst_dpman_add_required_dparam_direct</filename></listitem>
- <listitem><filename>gst_dpman_add_required_dparam_callback</filename></listitem>
- <listitem><filename>gst_dpman_add_required_dparam_array</filename></listitem>
- </itemizedlist>
- These functions will return TRUE if the required dparam was added successfully.
- </para>
- <para>
- The following function will be used as an example.
- <programlisting>
- gboolean
- gst_dpman_add_required_dparam_direct (GstDParamManager *dpman,
- GParamSpec *param_spec,
- gboolean is_log,
- gboolean is_rate,
- gpointer update_data)
- </programlisting>
- The common parameters to these functions are:
- <itemizedlist>
- <listitem><filename>GstDParamManager *dpman</filename> the element's dparam manager</listitem>
- <listitem><filename>GParamSpec *param_spec</filename> the param spec which defines the required dparam</listitem>
- <listitem>
- <filename>gboolean is_log</filename> whether this dparam value should be
- interpreted on a log scale (such as a frequency or a decibel value)
- </listitem>
- <listitem>
- <filename>gboolean is_rate</filename> whether this dparam value is a proportion of the
- sample rate. For example with a sample rate of 44100, 0.5 would be 22050 Hz and 0.25 would be 11025 Hz.
- </listitem>
- </itemizedlist>
- </para>
- <sect2 id="sect-dparam-direct">
- <title>Direct Method</title>
- <para>
- This method is the simplest and has the lowest overhead for parameters which change
- less frequently than the sample rate. First you need somewhere to store the parameter -
- this will usually be in your element's stuct.
- </para>
- <programlisting>
- struct _GstExample {
- GstElement element;
- ...
-
- GstDParamManager *dpman;
- gfloat volume;
- ...
- };
- </programlisting>
- <para>
- Then to define the required dparam just call <filename>gst_dpman_add_required_dparam_direct</filename>
- and pass in the location of the parameter to change.
- In this case the location is <filename>&(example->volume)</filename>.
- </para>
- <programlisting>
- gst_dpman_add_required_dparam_direct (
- example->dpman,
- g_param_spec_float("volume","Volume","Volume of the audio",
- 0.0, 1.0, 0.8, G_PARAM_READWRITE),
- FALSE,
- FALSE,
- &(example->volume)
- );
- </programlisting>
- <para>
- You can now use <filename>example->volume</filename> anywhere in your element knowing
- that it will always contain the correct value to use.
- </para>
- </sect2>
- <sect2 id="sect-dparam-callback">
- <title>Callback Method</title>
- <para>
- This should be used if the you have other values to calculate whenever a parameter changes.
- If you used the direct method you wouldn't know if a parameter had changed so you would have to
- recalculate the other values every time you needed them. By using the callback method, other values
- only have to be recalculated when the dparam value actually changes.
- </para>
- <para>
- The following code illustrates an instance where you might want to use the callback method.
- If you had a volume dparam which was represented by a gfloat number, your element may only deal
- with integer arithmatic. The callback could be used to calculate the integer scaler when the volume
- changes. First you will need somewhere to store these values.
- </para>
- <programlisting>
- struct _GstExample {
- GstElement element;
- ...
-
- GstDParamManager *dpman;
- gfloat volume_f;
- gint volume_i;
- ...
- };
- </programlisting>
- <para>
- When the required dparam is defined, the callback function <filename>gst_example_update_volume</filename>
- and some user data (which in this case is our element instance) is passed in to the call to
- <filename>gst_dpman_add_required_dparam_callback</filename>.
- </para>
- <programlisting>
- gst_dpman_add_required_dparam_callback (
- example->dpman,
- g_param_spec_float("volume","Volume","Volume of the audio",
- 0.0, 1.0, 0.8, G_PARAM_READWRITE),
- FALSE,
- FALSE,
- gst_example_update_volume,
- example
- );
- </programlisting>
- <para>
- The callback function needs to conform to this signiture
- </para>
- <programlisting>
-typedef void (*GstDPMUpdateFunction) (GValue *value, gpointer data);
- </programlisting>
- <para>
- In our example the callback function looks like this
- </para>
- <programlisting>
-static void
-gst_example_update_volume(GValue *value, gpointer data)
-{
- GstExample *example = (GstExample*)data;
- g_return_if_fail(GST_IS_EXAMPLE(example));
-
- example->volume_f = g_value_get_float(value);
- example->volume_i = example->volume_f * 8192;
-}
- </programlisting>
- <para>
- Now <filename>example->volume_i</filename> can be used elsewhere and it will always contain the correct value.
- </para>
- </sect2>
- <sect2 id="sect-dparam-array">
- <title>Array Method</title>
- <para>
- This method is quite different from the other two. It could be thought of as
- a specialised method which should only be used if you need the advantages that it
- provides. Instead of giving the element a single value it provides an array of values
- where each item in the array corresponds to a sample of audio in your buffer.
- There are a couple of reasons why this might be useful.
- </para>
-
- <itemizedlist>
- <listitem>
- Certain optimisations may be possible since you can iterate over your dparams array
- and your buffer data together.
- </listitem>
- <listitem>
- Some dparams may be able to interpolate changing values at the sample rate. This would allow
- the array to contain very smoothly changing values which may be required for the stability
- and quality of some DSP algorithms.
- </listitem>
- </itemizedlist>
- <para>
- The array method is currently the least mature of the three methods and is not yet ready to be
- used in elements, but plugin writers should be aware of its existance for the future.
- </para>
- </sect2>
-</chapter>
-
-<chapter id="cha-dparam-loop">
- <title>The Data Processing Loop</title>
- <para>
- This is the most critical aspect of the dparams subsystem as it relates to elements.
- In a traditional audio processing loop, a <filename>for</filename> loop will usually iterate over each
- sample in the buffer, processing one sample at a time until the buffer is finished.
- A simplified loop with no error checking might look something like this.
- </para>
- <programlisting>
-static void
-example_chain (GstPad *pad, GstBuffer *buf)
-{
- ...
- gfloat *float_data;
- int j;
- GstExample *example = GST_EXAMPLE(GST_OBJECT_PARENT (pad));
- int num_samples = GST_BUFFER_SIZE(buf)/sizeof(gfloat);
- float_data = (gfloat *)GST_BUFFER_DATA(buf);
- ...
- for (j = 0; j < num_samples; j++) {
- float_data[j] *= example->volume;
- }
- ...
-}
- </programlisting>
- <para>
- To make this dparams aware, a couple of changes are needed.
- </para>
- <programlisting>
-static void
-example_chain (GstPad *pad, GstBuffer *buf)
-{
- ...
- int j = 0;
- GstExample *example = GST_EXAMPLE(GST_OBJECT_PARENT (pad));
- int num_samples = GST_BUFFER_SIZE(buf)/sizeof(gfloat);
- gfloat *float_data = (gfloat *)GST_BUFFER_DATA(buf);
- int frame_countdown = GST_DPMAN_PREPROCESS(example->dpman, num_samples, GST_BUFFER_TIMESTAMP(buf));
- ...
- while (GST_DPMAN_PROCESS_COUNTDOWN(example->dpman, frame_countdown, j)) {
- float_data[j++] *= example->volume;
- }
- ...
-}
- </programlisting>
- <para>
- The biggest changes here are 2 new macros, <filename>GST_DPMAN_PREPROCESS</filename>
- and <filename>GST_DPMAN_PROCESS_COUNTDOWN</filename>.
- You will also notice that the for loop has become a while loop. <filename>GST_DPMAN_PROCESS_COUNTDOWN</filename>
- is called as the condition for the while loop so that any required dparams can be updated in the
- middle of a buffer if required. This is because one of the required behaviours of dparams is that they
- can be <emphasis>sample accurate</emphasis>. This means that parameters change at the exact timestamp
- that they are supposed to - not after the buffer has finished being processed.
- </para>
- <para>
- It may be alarming to see a macro as the condition for a while loop, but it is actually very efficient.
- The macro expands to the following.
- </para>
- <programlisting>
-#define GST_DPMAN_PROCESS_COUNTDOWN(dpman, frame_countdown, frame_count) \
- (frame_countdown-- || \
- (frame_countdown = GST_DPMAN_PROCESS(dpman, frame_count)))
- </programlisting>
- <para>
- So as long as <filename>frame_countdown</filename> is greater than 0, <filename>GST_DPMAN_PROCESS</filename>
- will not be called at all.
- Also in many cases, <filename>GST_DPMAN_PROCESS</filename> will do nothing and simply
- return 0, meaning that there is no more data in the buffer to process.
- </para>
- <para>
- The macro <filename>GST_DPMAN_PREPROCESS</filename> will do the following:
- <itemizedlist>
- <listitem>
- Update any dparams which are due to be updated.
- </listitem>
- <listitem>
- Calculate how many samples should be processed before the next required update
- </listitem>
- <listitem>
- Return the number of samples until next update, or the number of samples in the buffer -
- whichever is less.
- </listitem>
- </itemizedlist>
- In fact <filename>GST_DPMAN_PROCESS</filename> may do the same things as <filename>GST_DPMAN_PREPROCESS</filename>
- depending on the mode that the dparam manager is running in (see below).
- </para>
- <sect2 id="sect-dparam-modes">
- <title>DParam Manager Modes</title>
- <para>
- A brief explanation of dparam manager modes might be useful here even though it doesn't generally affect
- the way your element is written. There are different ways media applications will be used which
- require that an element's parameters be updated in differently. These include:
- <itemizedlist>
- <listitem>
- <emphasis>Timelined</emphasis> - all parameter changes are known in advance before the pipeline is run.
- </listitem>
- <listitem>
- <emphasis>Realtime low-latency</emphasis> - Nothing is known ahead of time about when a parameter
- might change. Changes need to be propagated to the element as soon as possible.
- </listitem>
- </itemizedlist>
- When a dparam-aware application gets the dparam manager for an element, the first thing it will do
- is set the dparam manager mode. Current modes are <filename>"synchronous"</filename>
- and <filename>"asynchronous"</filename>.
- </para>
- <para>
- If you are in a realtime low-latency situation then the <filename>"synchronous"</filename> mode is appropriate.
- During <filename>GST_DPMAN_PREPROCESS</filename> this mode will poll all dparams for required updates
- and propagate them. <filename>GST_DPMAN_PROCESS</filename> will do nothing in this mode.
- To then achieve the desired latency, the size of the buffers needs to be reduced so that the dparams will be
- polled for updates at the desired frequency.
- </para>
- <para>
- In a timelined situation, the <filename>"asynchronous"</filename> mode will be required. This mode
- hasn't actually been implemented yet but will be described anyway.
- The <filename>GST_DPMAN_PREPROCESS</filename> call will precalculate when and how often each dparam needs
- to update for the duration of the current buffer. From then on <filename>GST_DPMAN_PROCESS</filename> will
- propagate the calculated updates each time it is called until end of the buffer. If the application is rendering
- to disk in non-realtime, the render could be sped up by increasing the buffer size. In the <filename>"asynchronous"</filename>
- mode this could be done without affecting the sample accuracy of the parameter updates
- </para>
- </sect2>
- <sect2 id="sect-dparam-audio-video">
- <title>DParam Manager Modes</title>
- <para>
- All of the explanation so far has presumed that the buffer contains audio data with many samples.
- Video should be regarded differently since a video buffer often contains only 1 frame. In this case
- some of the complexity of dparams isn't required but the other benefits still make it useful for video
- parameters. If a buffer only contains one frame of video, only a single call to <filename>GST_DPMAN_PREPROCESS</filename>
- should be required. For more than one frame per buffer, treat it the same as the audio case.
- </para>
- </sect2>
-</chapter>
+++ /dev/null
-<?xml version='1.0'?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY % magic-entities SYSTEM "magic">
-%magic-entities;
-
-<!ENTITY TITLEPAGE SYSTEM "titlepage.xml">
-<!ENTITY INTRO SYSTEM "intro.xml">
-<!ENTITY TESTAPP SYSTEM "testapp.xml">
-<!ENTITY LOOPBASED SYSTEM "loopbased.xml">
-<!ENTITY BUFFERS SYSTEM "buffers.xml">
-<!ENTITY SRCNSINK SYSTEM "srcnsink.xml">
-<!ENTITY STATEMANAGE SYSTEM "statemanage.xml">
-<!ENTITY CHECKLIST SYSTEM "checklist.xml">
-<!ENTITY DPARAMS SYSTEM "dparams.xml">
-<!ENTITY GStreamer "<application>GStreamer</application>">
-]>
-
-<book id="index">
- &TITLEPAGE;
-
-<!-- ############# part ############### -->
-
- <part id="introduction"><title>Introduction</title>
- <partintro>
- <para>
- &GStreamer; is a framework for creating
- streaming media applications. It is extremely powerful and versatile,
- and this versatility stems in part from its modularity, and its ability
- to incorporate new modules seamlessly into its framework.
- This document describes how to extend the capabilities of
- &GStreamer; by creating new plugins.
- </para>
- <para>
- It first describes the concepts required and the ways in which
- &GStreamer; can be extended. It then goes
- through a worked example of how to write a simple filter (for data
- processing), and how to test and debug it. More advanced concepts are
- then introduced, with worked examples of each. Next, writing source
- and sink elements (for performing input and output) is discussed.
- Finally, checklists of things to be sure to do when extending
- &GStreamer; are presented.
- </para>
- </partintro>
-
- &INTRO;
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="basic-concepts"><title>Basic concepts</title>
- <partintro>
- <para>
-
- This section introduces the basic concepts required to understand the
- issues involved in extending &GStreamer;
- </para>
- <para>
- Many of these concepts are explained in greater detail in the
- GStreamer Application Development Manual, and are merely mentioned
- here to refresh your memory.
-
- </para>
- </partintro>
-
-
- <chapter id="cha-plugins">
- <title>Plugins</title>
- <para>
- Extensions to &GStreamer; can be made using a plugin mechanism. This is
- used extensively in &GStreamer; even if only the standard package is
- being used: a few very basic functions reside in the core library, and
- all others are implemented in plugins.
- </para>
- <para>
- Plugins are only loaded when needed: a plugin registry is used to
- store the details of the plugins so that it is not neccessary to load
- all plugins to determine which are needed.
- This registry needs to be updated whenever a new plugin is added to the
- system: see the <emphasis>gstreamer-register</emphasis> utility and the
- documentation in the <emphasis>GStreamer Application Development
- Manual</emphasis> for more details.
- </para>
- <para>
- User extensions to &GStreamer; can be installed in the main plugin
- directory, and will immediately be available for use in applications.
- <emphasis>gstreamer-register</emphasis> should be run to update
- the repository: but the system should work correctly even if it hasn't
- been - it will just take longer to load the correct plugin.
- </para>
- <para>
- User specific plugin directories and registries will be available
- in future versions of &GStreamer;.
- </para>
- </chapter>
-
- <chapter id="cha-elements">
- <title>Elements</title>
- <para>
- Elements are at the core of &GStreamer;. Without elements, &GStreamer;
- is just
- a bunch of pipe fittings with nothing to connect. A large number of
- elements (filters, sources and sinks) ship with &GStreamer;, but extra
- elements can also be written.
- </para>
- <para>
- An element may be constructed in several different ways, but all must
- conform to the same basic rules. A simple filter may be built with the
- FilterFactory, where the only code that need be written is the actual
- filter code. A more complex filter, or a source or sink, will need to
- be written out fully for complete access to the features and
- performance possible with &GStreamer;.
- </para>
- <para>
- The implementation of a new element will be contained in a plugin:
- a single plugin may contain the implementation of several elements, or
- just a single one.
- </para>
- </chapter>
-
- <chapter id="cha-buffers">
- <title>Buffers</title>
- <para>
- Buffers are structures used to pass data between elements. All streams
- of data are chopped up into chunks which are stored in buffers.
- Buffers can be of any size, and also contain metadata indicating the
- type of data contained in them. Buffers can be allocated by various
- different schemes, and may either be passed on by elements or
- unreferenced (and the memory used by the buffer freed).
- </para>
- </chapter>
-
- <chapter id="cha-typing">
- <title>Typing and Properties</title>
- <para>
- A type system is used to ensure that the data passed between elements
- is in a recognised format, and that the various parameters required
- to fully specify that format match up correctly. Each connection
- that is made between elements has a specified type. This is related,
- but different, to the metadata in buffers which describes the type
- of data in that particular buffer. See later in this document for
- details of the available types.
- </para>
- </chapter>
-
- <chapter id="cha-metadata">
- <title>Metadata</title>
- <para>
- </para>
- </chapter>
-
- <chapter id="cha-scheduling">
- <title>Scheduling</title>
- <para>
- </para>
- </chapter>
-
- <chapter id="cha-chainloop">
- <title>Chain vs Loop Elements</title>
- <para>
- </para>
- </chapter>
-
- <chapter id="cha-autopluggers">
- <title>Autopluggers</title>
- <para>
- &GStreamer; has an autoplugging mechanism, which enables application
- writers to simply specify start and end elements for a path, and
- the system will then create a path which links these elements,
- in accordance with the type information provided by the elements.
- </para>
- <para>
- It is possible to devise many different schemes for generating such
- pathways, perhaps to optimise based on special criteria, or with
- some specific constraints. It is thus possible to define new
- autoplugging systems, using the plugin system.
- </para>
- </chapter>
-
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="typesnprops"><title>Types and Properties</title>
- <partintro>
- <para>
- There is a very large set of possible types that may be used to
- pass data between elements. Indeed, each new element that is defined
- may use a new data format (though unless at least one other element
- recognises that format, it will be most likely be useless since
- nothing will be able to link with it).
- </para>
- <para>
- In order for types to be useful, and for systems like autopluggers to
- work, it is neccessary that all elements
- agree on the type definitions, and which properties are required
- for each type. The &GStreamer; framework itself
- simply provides the ability to define types and parameters, but does
- not fix the meaning of types and parameters, and does not enforce
- standards on the creation of new types. This is a matter for
- a policy to decide, not technical systems to enforce.
- </para>
- <para>
- For now, the policy is simple:
- <itemizedlist>
- <listitem>
- <para>
- Do not create a new type if you could use one which already
- exists.
- </para>
- </listitem>
- <listitem>
- <para>
- If creating a new type, discuss it first with the other
- &GStreamer; developers, on at least one of: IRC, mailing lists,
- the &GStreamer; wiki.
- </para>
- </listitem>
- <listitem>
- <para>
- Try to ensure that the name for a new format is as unlikely to
- conflict with anything else created already, and is not a more
- generalised name than it should be. For example:
- "audio/compressed" would be too generalised a name to represent
- audio data compressed with an mp3 codec. Instead "audio/mp3"
- might be an appropriate name, or "audio/compressed" could exist
- and have a property indicating the type of compression used.
- </para>
- </listitem>
- <listitem>
- <para>
- Ensure that, when you do create a new type, you specify it
- clearly, and get it added to the list of known types so that
- other developers can use the type correctly when writing their
- elements.
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </partintro>
-
- <chapter id="cha-basic-types">
- <title>The basic types</title>
- <para>
- This is a list of the basic types used for buffers. For each type, we
- give the name ("mime type") of the type, the list of properties which
- are associated with the type, the meaning of each property, and the
- purpose of the type.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>audio/raw</emphasis>
- - Unstructured and uncompressed raw audio data.
- </para><para>
- <emphasis>rate</emphasis>
- - The sample rate of the data, in samples per second.
- </para><para>
- <emphasis>channels</emphasis>
- - The number of channels of audio data.
- </para><para>
- <emphasis>format</emphasis>
- - This describes the format in which the audio data is passed.
- This is a string for which there are currently two valid values:
- "int" for integer data and "float" for floating point data.
- </para><para>
- <emphasis>law</emphasis>
- - Valid only if format=int. The law used to describe the data.
- This is an integer for which there are three valid values: 0 for
- linear, 1 for mu law, 2 for A law.
- </para><para>
- <emphasis>endianness</emphasis>
- - Valid only if format=int. The order of bytes in a sample. This
- is a boolean: 0 means little-endian (ie, bytes are least
- significant first), 1 means big-endian (ie, most significant byte
- first).
- </para><para>
- <emphasis>signed</emphasis>
- - Valid only if format=int. Whether the samples are signed or not.
- This is a boolean: 0 means unsigned, 1 means signed.
- </para><para>
- <emphasis>width</emphasis>
- - Valid only if format=int. The number of bits per sample. This
- is extremely likely to be a multiple of 8, but as ever this is up
- to each element supporting this format to specify.
- </para><para>
- <emphasis>depth</emphasis>
- - Valid only if format=int. The number of bits used per sample.
- This must be less than or equal to the width: if less than the
- width, the low bits are assumed to be the ones used. For example,
- width=32, depth=24 means that each sample is stored in a 32 bit
- word, but only the low 24 bits are actually used.
- </para><para>
- <emphasis>layout</emphasis>
- - Valid only if format=float. A string representing the way in
- which the floating point data is represented. For now, the only
- valid value is gfloat, meaning that the data is passed as a series
- of gfloat values.
- </para><para>
- <emphasis>intercept</emphasis>
- - Valid only if format=float. A floating point value representing
- the value that the signal "centres" on.
- </para><para>
- <emphasis>slope</emphasis>
- - Valid only if format=float. A floating point value representing
- how far the signal deviates from the intercept. So a slope of 1.0
- and an intercept of 0.0 would mean an audio signal with minimum
- and maximum values of -1.0 and 1.0. A slope of 0.5 and intercept
- of 0.5 would represent values in the range 0.0 to 1.0.
- </para>
- <para>
- For example: 16 bit integer, unsigned, linear, monophonic, big-endian,
- 44100KHz audio would be represented by
- "format=int,law=0,endianness=1,signed=0,width=16,depth=16,rate=44100,channels=1"
- and floating point, using gfloat's, in the range -1.0 to 1.0,
- 8000KHz stereo audio would be represented by
- "format=float,layout=gfloat,intercept=0.0,slope=1.0,rate=8000,channels=2"
- </para>
- </listitem>
- </itemizedlist>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>audio/mp3</emphasis>
- - Audio data compressed using the mp3 encoding scheme.
- </para><para>
- <emphasis>framed</emphasis>
- - This is a boolean. If true (1), each buffer contains exactly
- one frame. If false (0), frames and buffers do not (necessarily)
- match up. If the data is not framed, the values of some of the
- properties will not be available, but others will be assumed to
- be constant throughout the file, or may be found in other ways.
- </para><para>
- <emphasis>layer</emphasis>
- - The compression scheme layer used to compress the data.
- This is an integer, and can currently have the value 1, 2
- or 3.
- </para><para>
- <emphasis>bitrate</emphasis>
- - The bitrate, in kilobits per second.
- For VBR (variable bitrate) mp3 data, this is the average bitrate.
- </para><para>
- <emphasis>channels</emphasis>
- - The number of channels of audio data present. This could
- theoretically be any integer greater than 0, but in practice will
- be either 1 or 2.
- </para><para>
- <emphasis>joint-stereo</emphasis>
- - Boolean. If true, channels must not be zero. If true, this
- implies that stereo data is stored as a combined signal and
- the difference between the signals, rather than as two entirely
- separate signals.
- </para><para>
- There are many other properties relevant for
- <emphasis>audio/mp3</emphasis> data: these may be added to this
- specification at a later date.
- </para>
- </listitem>
- </itemizedlist>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>audio/x-ogg</emphasis>
- - Audio data compressed using the Ogg Vorbis encoding scheme.
- There are currently no parameters defined for this type. FIXME.
- </para>
- </listitem>
- </itemizedlist>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>video/raw</emphasis>
- - Raw video data.
- </para><para>
- <emphasis>fourcc</emphasis>
- - A FOURCC code identifying the format in which this data is
- stored. FOURCC (Four Character Code) is a simple system to
- allow unambiguous identification of a video datastream format.
- See <ulink
- url="http://www.webartz.com/fourcc/"
- type="http">http://www.webartz.com/fourcc/</ulink>
- </para><para>
- <emphasis>width</emphasis>
- - The number of pixels wide that each video frame is.
- </para><para>
- <emphasis>height</emphasis>
- - The number of pixels high that each video frame is.
- </para>
- </listitem>
- </itemizedlist>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>video/mpeg</emphasis>
- - Video data compressed using an mpeg encoding scheme.
- </para><para>
- <emphasis>mpegversion</emphasis>
- </para><para>
- <emphasis>systemstream</emphasis>
- </para>
- </listitem>
- </itemizedlist>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>video/avi</emphasis>
- - Video data compressed using the AVI encoding scheme.
- There are currently no parameters defined for this type. FIXME.
- </para>
- </listitem>
- </itemizedlist>
- </chapter>
-
- <chapter id="cha-types-test">
- <title>Building a simple format for testing</title>
- <para>
- </para>
- </chapter>
-
- <chapter id="cha-types-simplemime">
- <title>A simple MIME type</title>
- <para>
- </para>
- </chapter>
-
- <chapter id="cha-types-props">
- <title>Type properties</title>
- <para>
- </para>
- </chapter>
-
- <chapter id="cha-types-typefind">
- <title>Typefind functions and autoplugging</title>
- <para>
- </para>
- </chapter>
-
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="first-plugin"><title>Building our first plugin</title>
- <partintro>
- <para>
- We are now have the neccessary concepts to build our first plugin.
- We are going to build an element which has a single input pad and
- a single output pad, and simply passes anything it reads on
- the input pad through and out on the output pad. We will also
- see where we could add code to convert this plugin into something
- more useful.
- </para>
- <para>
- The example code used in this section can be found in
- <filename>examples/plugins/</filename>
- </para>
- </partintro>
-
- <chapter id="cha-boilerplate">
- <title>Constructing the boilerplate</title>
- <para>
- The first thing to do when making a new element is to specify some basic
- details about it: what its name is, who wrote it, what version number it
- is, etc. We also need to define an object to represent the element and to
- store the data the element needs. I shall refer to these details
- collectively as the <emphasis>boilerplate</emphasis>.
- </para>
-
- <sect1 id="sect-boilerplate-gobject">
- <title>Doing it the hard way with GstObject</title>
- <para>
- The standard way of defining the boilerplate is simply to write some
- code, and fill in some structures. The easiest way to do this is to
- copy an example and modify according to your needs.
- </para>
- <para>
- First we will examine the code you would be likely to place in a header
- file (although since the interface to the code is entirely defined
- by the pluging system, and doesn't depend on reading a header file,
- this is not crucial.)
-
- The code here can be found in
- <filename>examples/plugins/example.h</filename>
- </para>
-
- <programlisting>
- /* Definition of structure storing data for this element. */
- typedef struct _GstExample GstExample;
-
- struct _GstExample {
- GstElement element;
-
- GstPad *sinkpad,*srcpad;
-
- gint8 active;
- };
-
- /* Standard definition defining a class for this element. */
- typedef struct _GstExampleClass GstExampleClass;
- struct _GstExampleClass {
- GstElementClass parent_class;
- };
-
- /* Standard macros for defining types for this element. */
- #define GST_TYPE_EXAMPLE \
- (gst_example_get_type())
- #define GST_EXAMPLE(obj) \
- (GTK_CHECK_CAST((obj),GST_TYPE_EXAMPLE,GstExample))
- #define GST_EXAMPLE_CLASS(klass) \
- (GTK_CHECK_CLASS_CAST((klass),GST_TYPE_EXAMPLE,GstExample))
- #define GST_IS_EXAMPLE(obj) \
- (GTK_CHECK_TYPE((obj),GST_TYPE_EXAMPLE))
- #define GST_IS_EXAMPLE_CLASS(obj) \
- (GTK_CHECK_CLASS_TYPE((klass),GST_TYPE_EXAMPLE))
-
- /* Standard function returning type information. */
- GtkType gst_example_get_type(void);
- </programlisting>
-
- </sect1>
-
- <sect1 id="sect-boilerplate-filterfactory">
- <title>Doing it the easy way with FilterFactory</title>
- <para>
- A plan for the future is to create a FilterFactory, to make the
- process of making a new filter a simple process of specifying a few
- details, and writing a small amount of code to perform the actual
- data processing.
- </para>
- <para>
- Unfortunately, this hasn't yet been implemented. It is also likely
- that when it is, it will not be possible to cover all the possibilities
- available by writing the boilerplate yourself, so some plugins will
- always need to be manually registered.
- </para>
- <para>
- As a rough outline of what is planned: the FilterFactory will take a
- list of appropriate function pointers, and data structures to define
- a filter. With a reasonable measure of preprocessor magic, the
- plugin writer will then simply need to provide definitions of the
- functions and data structures desired, and a name for the filter, and
- then call a macro from within plugin_init() which will register the
- new filter. All the fluff that goes into the definition of a filter
- will thus be hidden from view.
- </para>
- <para>
- Ideally, we will come up with a way for various FilterFactory-provided
- functions to be overridden, to the point where you can construct
- almost the most complex stuff with it, it just saves typing.
- </para>
- <para>
- Of course, the filter factory can be used to create sources and sinks
- too: simply create a filter with only source or sink pads.
- </para>
- <para>
- You may be thinking that this should really be called an
- ElementFactory. Well, we agree, but there is already something else
- justifiably ealled an ElementFactory (this is the thing which actually
- makes instances of elements). There is also already something called
- a PluginFactory. We just have too many factories and not enough words.
- And since this isn't yet written, it doesn't get priority for claiming
- a name.
- </para>
- </sect1>
- </chapter>
-
- <chapter id="cha-defineelt">
- <title>Defining an element</title>
- <para>
- A new element is defined by creating an element factory. This is a
- structure containing all the information needed to create an instance
- of the element. Creating a factory requires two things: a type for
- the element to be created
- (this was defined in the boilerplate above: FIXME - reorganise),
- and a GstElementDetails structure, which contains some
- general information about the element to be created.
- </para>
-
- <sect1 id="sect-defineelt-eltdetails">
- <title>GstElementDetails</title>
- <para>
- The GstElementDetails structure gives a heirarchical type for
- the element, a human-readable description of the element, as
- well as author and version data. The entries are:
- </para>
- <itemizedlist>
- <listitem><para>
- A long, english, name for the element.
- </para></listitem><listitem><para>
- The type of the element, as a heirarchy. The heirarchy is defined
- by specifying the top level category, followed by a "/", followed
- by the next level category, etc. The type should be defined
- according to the guidelines elsewhere in this document.
- (FIXME: write the guidelines, and give a better reference to them)
- </para></listitem><listitem><para>
- A brief description of the purpose of the element.
- </para></listitem><listitem><para>
- The version number of the element. For elements in the main
- GStreamer source code, this will often simply be VERSION, which is
- a macro defined to be the version number of the current GStreamer
- version. The only requirement, however, is that the version
- number should increase monotonically.
- </para><para>
- Version numbers should be stored in major.minor.patch form: ie, 3
- (decimal) numbers, separated by ".".
- </para></listitem><listitem><para>
- The name of the author of the element, optionally followed by
- a contact email address in angle brackets.
- </para></listitem><listitem><para>
- The copyright details for the element.
- </para></listitem>
- </itemizedlist>
- <para>
- For example:
- </para>
- <programlisting>
- static GstElementDetails example_details = {
- "An example plugin",
- "Example/FirstExample",
- "Shows the basic structure of a plugin",
- VERSION,
- "your name <your.name@your.isp>",
- "(C) 2001",
- };
- </programlisting>
- </sect1>
-
- <sect1 id="sect-defineelt-constructors">
- <title>Constructor functions</title>
- <para>
- Each element has two functions which are used for construction of
- an element. These are the _class_init() function, which is used to
- initialise the class (specifying what signals and arguments the class
- has and setting up global state), and the _init() function, which
- is used to initialise a specific instance of the class.
- </para>
- </sect1>
-
- <sect1 id="sect-defineelt-pads">
- <title>Specifying the pads</title>
- <para>
- </para>
- </sect1>
-
- <sect1 id="sect-defineelt-fns">
- <title>Attaching functions</title>
- <para>
- </para>
- </sect1>
-
- <sect1 id="sect-defineelt-chainfn">
- <title>The chain function</title>
- <para>
- </para>
- </sect1>
-
- <sect1 id="sect-defineelt-arguments">
- <title>Adding arguments</title>
- <para>
- Define arguments in enum.
-
- </para>
- </sect1>
-
- <sect1 id="sect-defineelt-signals">
- <title>Signals</title>
- <para>
- Define signals in enum.
-
- </para>
- </sect1>
- </chapter>
-
- <chapter id="cha-definetype">
- <title>Defining a type</title>
- <para>
- A new type is defined by creating an type factory. This is a
- structure containing all the information needed to create an instance
- of the type.
- </para>
- </chapter>
-
- <chapter id="cha-plugininit">
- <title>The plugin_init function</title>
- <para>
- Once we have written code defining all the parts of the plugin,
- we need to write the plugin_init() function. This is a special
- function, which is called as soon as the plugin is loaded, and
- must return a pointer to a newly allocated GstPlugin structure.
- This structure contains the details of all the facilities provided
- by the plugin, and is the mechanism by which the definitions are
- made available to the rest of the &GStreamer; system. Helper
- functions are provided to help fill the
- structure: for future compatability it is recommended that these
- functions are used, as documented below, rather than attempting to
- access the structure directly.
- </para>
- <para>
- Note that the information returned by the plugin_init() function
- will be cached in a central registry. For this reason, it is
- important that the same information is always returned by
- the function: for example, it must not make element factories
- available based on runtime conditions. If an element can only
- work in certain conditions (for example, if the soundcard is not
- being used by some other process) this must be reflected by the
- element being unable to enter the READY state if unavailable, rather
- than the plugin attempting to deny existence of the plugin.
- </para>
-
- <sect1 id="sect-plugininit-types">
- <title>Registering new types</title>
- <para>
-
- </para>
- <programlisting>
- void gst_plugin_add_type(GstPlugin *plugin,
- GstTypeFactory *factory);
- </programlisting>
- <para>
- </para>
- </sect1>
-
- <sect1 id="sect-plugininit-filter">
- <title>Registering new element factories</title>
- <para>
- </para>
- <programlisting>
- void gst_plugin_add_factory(GstPlugin *plugin,
- GstElementFactory *factory);
- </programlisting>
- <para>
- Multiple element factories can be provided by a single plugin:
- all it needs to do is call gst_plugin_add_factory() for each
- element factory it wishes to provide.
- </para>
- </sect1>
-
- <sect1 id="sect-plugininit-autopluggers">
- <title>Registering new autopluggers</title>
- <para>
- </para>
- <programlisting>
- void gst_plugin_add_autoplugger(GstPlugin *plugin,
- GstAutoplugFactory *factory);
- </programlisting>
- </sect1>
-
- </chapter>
-
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="dparams"><title>Supporting Dynamic Parameters</title>
- <partintro>
- <para>
- Sometimes object properties are not powerful enough to control the
- parameters that affect the behaviour of your element. When this is
- the case you can expose these parameters as Dynamic Parameters
- which can be manipulated by any Dynamic Parameters aware application.
- </para>
- <para>
- Throughout this section, the term dparams will be used as an abbreviation for Dynamic Parameters.
- </para>
- </partintro>
- <sect2 id="sect-dparams-compare">
- <title>Comparing Dynamic Parameters with GObject Properties</title>
- <para>
- Your first exposure to dparams may be to convert an existing element from
- using object properties to using dparams. The following table gives an overview
- of the difference between these approaches. The significance of these
- differences should become apparent later on.
- </para>
- <informaltable frame="all">
- <tgroup cols="3">
- <thead>
- <row>
- <entry></entry>
- <entry>Object Properties</entry>
- <entry>Dynamic Parameters</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><emphasis>Parameter definition</emphasis></entry>
- <entry>Class level at compile time</entry>
- <entry>Any level at run time</entry>
- </row>
- <row>
- <entry><emphasis>Getting and setting</emphasis></entry>
- <entry>Implemented by element subclass as functions</entry>
- <entry>Handled entirely by dparams subsystem</entry>
- </row>
- <row>
- <entry><emphasis>Extra objects required</emphasis></entry>
- <entry>None - all functionality is derived from base GObject</entry>
- <entry>Element needs to create and store a <filename>GstDParamManager</filename> at object creation</entry>
- </row>
- <row>
- <entry><emphasis>Frequency and resolution of updates</emphasis></entry>
- <entry>Object properties will only be updated between calls to _get, _chain or _loop</entry>
- <entry>dparams can be updated at any rate independant of calls to _get, _chain or _loop
- up to sample-level accuracy</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </sect2>
-
- &DPARAMS;
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="test-app"><title>Building a simple test application</title>
- <partintro>
- <para>
- </para>
- </partintro>
-
- &TESTAPP;
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="loopbased"><title>Loop-based Elements</title>
- <partintro>
- <para>
- </para>
- </partintro>
-
- &LOOPBASED;
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="buffersnmeta"><title>Buffers and Metadata</title>
- <partintro>
- <para>
- </para>
- </partintro>
-
- &BUFFERS;
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="srcnsink"><title>Sources and Sinks</title>
- <partintro>
- <para>
- </para>
- </partintro>
-
- &SRCNSINK;
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="statemanage"><title>State management</title>
- <partintro>
- <para>
- </para>
- </partintro>
-
- &STATEMANAGE;
- </part>
-
-<!-- ############ part ############# -->
-
- <part id="checklist"><title>Checklist</title>
- <partintro>
- <para>
- </para>
- </partintro>
-
- &CHECKLIST;
- </part>
-
-</book>