mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
docs/: more dparam docs
Original commit message from CVS: * docs/manual/advanced-dparams.xml: * docs/pwg/advanced-dparams.xml: more dparam docs * gst/gstindex.c: fix docs * libs/gst/controller/lib.c: (gst_controller_init): init just once
This commit is contained in:
parent
93d14f9c64
commit
dad303a342
5 changed files with 48 additions and 314 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2006-01-31 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* docs/manual/advanced-dparams.xml:
|
||||
* docs/pwg/advanced-dparams.xml:
|
||||
more dparam docs
|
||||
* gst/gstindex.c:
|
||||
fix docs
|
||||
* libs/gst/controller/lib.c: (gst_controller_init):
|
||||
init just once
|
||||
|
||||
2006-01-31 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* gst/gstelement.c: (gst_element_message_full):
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</para>
|
||||
<para>
|
||||
This subsystem is contained within the
|
||||
<filename>gstcontrol</filename> library.
|
||||
<filename>gstcontroller</filename> library.
|
||||
You need to include the header in your application's source file:
|
||||
</para>
|
||||
<programlisting>
|
||||
|
@ -39,10 +39,11 @@
|
|||
</sect1>
|
||||
|
||||
<sect1 id="section-dparams-parameters">
|
||||
<title>Setting up parameters</title>
|
||||
<title>Setting up parameter control</title>
|
||||
<para>
|
||||
It makes not sense for all GObject parameter to be real-time controlled.
|
||||
Therefore the first step is to mark controllable parameters.
|
||||
The first step is to select the parameters that should be controlled.
|
||||
This returns a controller object that is needed to further adjust the
|
||||
behaviour.
|
||||
</para>
|
||||
<programlisting>
|
||||
controller = g_object_control_properties(object, "prop1", "prop2",...);
|
||||
|
|
|
@ -5,343 +5,60 @@
|
|||
<title>Supporting Dynamic Parameters</title>
|
||||
<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.
|
||||
parameters that affect the behaviour of your element.
|
||||
When this is the case you can mark these parameters as beeing Controllable.
|
||||
Aware appliations can use the controller subsystem to dynamically adjust
|
||||
the property values over time.
|
||||
</para>
|
||||
<para>
|
||||
Throughout this section, the term <emphasis>dparams</emphasis> will be used
|
||||
as an abbreviation for "Dynamic Parameters".
|
||||
</para>
|
||||
|
||||
<sect1 id="section-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 independent of calls to _get, _chain or _loop up to sample-level accuracy</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="section-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
|
||||
The controller subsystem is contained within the
|
||||
<filename>gstcontroller</filename> library. You need to include the header in
|
||||
your element's source file:
|
||||
</para>
|
||||
<programlisting>
|
||||
#include <gst/control/control.h>
|
||||
...
|
||||
#include <gst/gst.h>
|
||||
#include <gst/controller/gstcontroller.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
|
||||
Even though the <filename>gstcontroller</filename> library may be linked into
|
||||
the host application, you should make sure it is initialized in your
|
||||
<filename>plugin_init</filename> function:
|
||||
</para>
|
||||
<programlisting>
|
||||
static gboolean
|
||||
plugin_init (GModule *module, GstPlugin *plugin)
|
||||
plugin_init (GstPlugin *plugin)
|
||||
{
|
||||
...
|
||||
|
||||
/* load dparam support library */
|
||||
if (!gst_library_load ("gstcontrol"))
|
||||
{
|
||||
gst_info ("example: could not load support library: 'gstcontrol'\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* initialize library */
|
||||
gst_controller_init (NULL, NULL);
|
||||
...
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
You need to store an instance of <filename>GstDParamManager</filename> in
|
||||
your element's struct:
|
||||
It makes not sense for all GObject parameter to be real-time controlled.
|
||||
Therefore the next step is to mark controllable parameters.
|
||||
This is done by using the special flag <constant>GST_PARAM_CONTROLLABLE</constant>.
|
||||
when setting up GObject params in the <function>_class_init</function> method.
|
||||
</para>
|
||||
<programlisting>
|
||||
struct _GstExample {
|
||||
GstElement element;
|
||||
...
|
||||
|
||||
GstDParamManager *dpman;
|
||||
|
||||
...
|
||||
};
|
||||
g_object_class_install_property (gobject_class, PROP_FREQ,
|
||||
g_param_spec_double ("freq", "Frequency", "Frequency of test signal",
|
||||
0.0, 20000.0, 440.0,
|
||||
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
||||
</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>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="section-dparam-define">
|
||||
<title>Defining Parameter Specifications</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>
|
||||
<para>
|
||||
In the element <filename>init</filename> function, just after the call
|
||||
to <filename>gst_dpman_new</filename>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
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 separate volume parameter is needed on every pad.
|
||||
</para>
|
||||
</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>
|
||||
<!-- FIXME: are we sure we need to use filename for function calls ??? -->
|
||||
<listitem><para><filename>gst_dpman_add_required_dparam_direct</filename></para></listitem>
|
||||
<listitem><para><filename>gst_dpman_add_required_dparam_callback</filename></para></listitem>
|
||||
<listitem><para><filename>gst_dpman_add_required_dparam_array</filename></para></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>
|
||||
<para>
|
||||
<filename>GstDParamManager *dpman</filename> the element's dparam
|
||||
manager
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<filename>GParamSpec *param_spec</filename> the param spec which defines
|
||||
the required dparam
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<filename>gboolean is_log</filename> whether this dparam value should be
|
||||
interpreted on a log scale (such as a frequency or a decibel value)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<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.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<sect2 id="section-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
|
||||
struct.
|
||||
</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="section-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 arithmetic. 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 signature
|
||||
</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="section-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>
|
||||
<para>
|
||||
Certain optimisations may be possible since you can iterate over your
|
||||
dparams array and your buffer data together.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</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 existence for the future.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="chapter-dparam-loop">
|
||||
<title>The Data Processing Loop</title>
|
||||
<!-- FIXME -->
|
||||
<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>
|
||||
|
|
|
@ -667,7 +667,6 @@ gst_index_add_entry (GstIndex * index, GstIndexEntry * entry)
|
|||
* @flags: optinal flags for this entry
|
||||
* @n: number of associations
|
||||
* @list: list of associations
|
||||
* @...: other format/value pairs or 0 to end the list
|
||||
*
|
||||
* Associate given format/value pairs with each other.
|
||||
*
|
||||
|
|
|
@ -43,6 +43,13 @@ GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
|
|||
gboolean
|
||||
gst_controller_init (int *argc, char ***argv)
|
||||
{
|
||||
static gboolean _gst_controller_initialized = FALSE;
|
||||
|
||||
if (_gst_controller_initialized)
|
||||
return TRUE;
|
||||
|
||||
_gst_controller_initialized = TRUE;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gstcontroller", 0,
|
||||
"dynamic parameter control for gstreamer elements");
|
||||
|
||||
|
|
Loading…
Reference in a new issue