diff --git a/docs/fwg/dparams.xml b/docs/fwg/dparams.xml
new file mode 100644
index 0000000000..f8e0bd9965
--- /dev/null
+++ b/docs/fwg/dparams.xml
@@ -0,0 +1,380 @@
+
+ Getting Started
+
+
+ The dparams subsystem is contained within the gstcontrol library.
+ You need to include the header in your element's source file:
+
+
+ #include <gst/control/control.h>
+
+
+
+ Even though the gstcontrol library may be linked into the host
+ application, you should make sure it is loaded in your plugin_init
+ function:
+
+
+ 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;
+ }
+
+ ...
+ }
+
+
+
+ You need to store an instance of GstDParamManager in your element's struct:
+
+
+ struct _GstExample {
+ GstElement element;
+ ...
+
+ GstDParamManager *dpman;
+
+ ...
+ };
+
+
+
+ The GstDParamManager can be initialised in your element's
+ init function:
+
+
+ static void
+ gst_example_init (GstExample *example)
+ {
+ ...
+
+ example->dpman = gst_dpman_new ("example_dpman", GST_ELEMENT(example));
+
+ ...
+ }
+
+
+
+
+
+ Defining Parameter Specificiations
+
+ You can define the dparams you need anywhere within your element but will usually
+ need to do so in only a couple of places:
+
+
+ In the element init function,
+ just after the call to gst_dpman_new
+
+
+ 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.
+
+
+
+
+ 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:
+
+ gst_dpman_add_required_dparam_direct
+ gst_dpman_add_required_dparam_callback
+ gst_dpman_add_required_dparam_array
+
+ These functions will return TRUE if the required dparam was added successfully.
+
+
+ The following function will be used as an example.
+
+ gboolean
+ gst_dpman_add_required_dparam_direct (GstDParamManager *dpman,
+ GParamSpec *param_spec,
+ gboolean is_log,
+ gboolean is_rate,
+ gpointer update_data)
+
+ The common parameters to these functions are:
+
+ GstDParamManager *dpman the element's dparam manager
+ GParamSpec *param_spec the param spec which defines the required dparam
+
+ gboolean is_log whether this dparam value should be
+ interpreted on a log scale (such as a frequency or a decibel value)
+
+
+ gboolean is_rate 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.
+
+
+
+
+ Direct Method
+
+ 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.
+
+
+ struct _GstExample {
+ GstElement element;
+ ...
+
+ GstDParamManager *dpman;
+ gfloat volume;
+ ...
+ };
+
+
+ Then to define the required dparam just call gst_dpman_add_required_dparam_direct
+ and pass in the location of the parameter to change.
+ In this case the location is &(example->volume).
+
+
+ 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)
+ );
+
+
+ You can now use example->volume anywhere in your element knowing
+ that it will always contain the correct value to use.
+
+
+
+ Callback Method
+
+ 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.
+
+
+ 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.
+
+
+ struct _GstExample {
+ GstElement element;
+ ...
+
+ GstDParamManager *dpman;
+ gfloat volume_f;
+ gint volume_i;
+ ...
+ };
+
+
+ When the required dparam is defined, the callback function gst_example_update_volume
+ and some user data (which in this case is our element instance) is passed in to the call to
+ gst_dpman_add_required_dparam_callback.
+
+
+ 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
+ );
+
+
+ The callback function needs to conform to this signiture
+
+
+typedef void (*GstDPMUpdateFunction) (GValue *value, gpointer data);
+
+
+ In our example the callback function looks like this
+
+
+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;
+}
+
+
+ Now example->volume_i can be used elsewhere and it will always contain the correct value.
+
+
+
+ Array Method
+
+ 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.
+
+
+
+
+ Certain optimisations may be possible since you can iterate over your dparams array
+ and your buffer data together.
+
+
+ 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.
+
+
+
+ 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.
+
+
+
+
+
+ The Data Processing Loop
+
+ This is the most critical aspect of the dparams subsystem as it relates to elements.
+ In a traditional audio processing loop, a for 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.
+
+
+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;
+ }
+ ...
+}
+
+
+ To make this dparams aware, a couple of changes are needed.
+
+
+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;
+ }
+ ...
+}
+
+
+ The biggest changes here are 2 new macros, GST_DPMAN_PREPROCESS
+ and GST_DPMAN_PROCESS_COUNTDOWN.
+ You will also notice that the for loop has become a while loop. GST_DPMAN_PROCESS_COUNTDOWN
+ 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 sample accurate. This means that parameters change at the exact timestamp
+ that they are supposed to - not after the buffer has finished being processed.
+
+
+ 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.
+
+
+#define GST_DPMAN_PROCESS_COUNTDOWN(dpman, frame_countdown, frame_count) \
+ (frame_countdown-- || \
+ (frame_countdown = GST_DPMAN_PROCESS(dpman, frame_count)))
+
+
+ So as long as frame_countdown is greater than 0, GST_DPMAN_PROCESS
+ will not be called at all.
+ Also in many cases, GST_DPMAN_PROCESS will do nothing and simply
+ return 0, meaning that there is no more data in the buffer to process.
+
+
+ The macro GST_DPMAN_PREPROCESS will do the following:
+
+
+ Update any dparams which are due to be updated.
+
+
+ Calculate how many samples should be processed before the next required update
+
+
+ Return the number of samples until next update, or the number of samples in the buffer -
+ whichever is less.
+
+
+ In fact GST_DPMAN_PROCESS may do the same things as GST_DPMAN_PREPROCESS
+ depending on the mode that the dparam manager is running in (see below).
+
+
+ DParam Manager Modes
+
+ 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:
+
+
+ Timelined - all parameter changes are known in advance before the pipeline is run.
+
+
+ Realtime low-latency - Nothing is known ahead of time about when a parameter
+ might change. Changes need to be propagated to the element as soon as possible.
+
+
+ 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 "synchronous"
+ and "asynchronous".
+
+
+ If you are in a realtime low-latency situation then the "synchronous" mode is appropriate.
+ During GST_DPMAN_PREPROCESS this mode will poll all dparams for required updates
+ and propagate them. GST_DPMAN_PROCESS 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.
+
+
+ In a timelined situation, the "asynchronous" mode will be required. This mode
+ hasn't actually been implemented yet but will be described anyway.
+ The GST_DPMAN_PREPROCESS call will precalculate when and how often each dparam needs
+ to update for the duration of the current buffer. From then on GST_DPMAN_PROCESS 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 "asynchronous"
+ mode this could be done without affecting the sample accuracy of the parameter updates
+
+
+
+ DParam Manager Modes
+
+ 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 GST_DPMAN_PREPROCESS
+ should be required. For more than one frame per buffer, treat it the same as the audio case.
+
+
+
diff --git a/docs/fwg/gst-plugin-writers-guide.xml b/docs/fwg/gst-plugin-writers-guide.xml
index d17edd21b1..3774220067 100644
--- a/docs/fwg/gst-plugin-writers-guide.xml
+++ b/docs/fwg/gst-plugin-writers-guide.xml
@@ -12,6 +12,7 @@
+
GStreamer">
]>
@@ -747,6 +748,67 @@
+
+
+ Supporting Dynamic Parameters
+
+
+ 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.
+
+
+ Throughout this section, the term dparams will be used as an abbreviation for Dynamic Parameters.
+
+
+
+ Comparing Dynamic Parameters with GObject Properties
+
+ 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.
+
+
+
+
+
+
+ Object Properties
+ Dynamic Parameters
+
+
+
+
+ Parameter definition
+ Class level at compile time
+ Any level at run time
+
+
+ Getting and setting
+ Implemented by element subclass as functions
+ Handled entirely by dparams subsystem
+
+
+ Extra objects required
+ None - all functionality is derived from base GObject
+ Element needs to create and store a GstDParamManager at object creation
+
+
+ Frequency and resolution of updates
+ Object properties will only be updated between calls to _get, _chain or _loop
+ dparams can be updated at any rate independant of calls to _get, _chain or _loop
+ up to sample-level accuracy
+
+
+
+
+
+
+ &DPARAMS;
+
+
Building a simple test application
diff --git a/docs/fwg/titlepage.xml b/docs/fwg/titlepage.xml
index c7b46aca1b..1a7dd862a2 100644
--- a/docs/fwg/titlepage.xml
+++ b/docs/fwg/titlepage.xml
@@ -21,6 +21,16 @@
+
+
+ Steve
+ Baker
+
+
+ stevebaker_org@yahoo.co.uk
+
+
+