[gst-devel] dynamic parameters about to land

Baker, Steve SBaker at CHELLO.com
Sat Sep 8 12:04:10 CEST 2001


I am about ready to commit an initial implementation of dynamic parameters.
I think the API is pretty close to being complete even though there isn't a
lot of functionality there yet.

The commit will add 4 files to core:
gst/dparammanager.[ch]
gst/dparam.[ch]

Each element which uses dparams will have a single instance of
GstDparamManager. This instance will contain and manage all dparams that the
element requires.
GstDparamManager provides an API for the element to:
- add and remove info about the params it requires
- update the values in the element during _chain and _loop funcions
- register callbacks which will update the values in the element
GstDparamManager provides an API for the application to:
- attach GstDparam instances to an element that requires them
- change the behaviour of GstDparamManager for different usage requierments
such as real-time or NLE

The current default (and only) GstDparam implementation allows simple
real-time updating of values. To implement different behaviour GstDparam
needs to be subclassed.  The GstDparam API assumes that the data will be
stored as a series of points on a timeline. With realtime dparams there may
be no timeline but the API is flexible enough to deal with that.  Each point
in the timeline is basically a timestamped array of Gvalues. The contents of
the GValue array depends entirely on the GstDparam implementation in
question.

GstDparam provides an API for the element to:
- do nothing. elements don't need direct access to GstDparams
GstDparam provides an API for the application to:
- attach it to an existing GstDparamManager instance
- find/get/insert/remove points in the timeline (if there is one)
- change the data stored in points (which will affect the value in the
element)

My TODO list after this commit includes:
- object lifecycle
- saving/loading thineselves
- (many) more implementations of GstDparam (smooth realtime, linear
interpolation etc)
- async param updating mode
- thread safety
- integration with element's get/set property funcs
- do param value init on state change
- sending signal on gst_dpman_add_required_dparam 
- getting a list of required dparams
- non-trivial element (like a mixer)

I have used sinesrc as the lab rat for dparams. Here is a code walkthrough
of the public dparams api as currently used in gst/elements/gstsinesrc.c and
test/sinesliders.c

In the sinesrc init function:
  // new instance
  dpman = gst_dpman_new ("sinesrc_dpman", GST_ELEMENT(src));

  // this adds a required parameter, along with type and callback to update
the actual value
  gst_dpman_add_required_dparam (dpman, "volume",
G_TYPE_FLOAT,gst_sinesrc_update_volume, src);
  gst_dpman_add_required_dparam (dpman, "freq",
G_TYPE_FLOAT,gst_sinesrc_update_freq, src);

  // this sets the pad to listen to for caps changes so that the "rate" can
be stored (if "rate" exists)
  gst_dpman_set_rate_change_pad(dpman, src->srcpad);
  
  // so it can be found.
  GST_ELEMENT_DPARAM_MANAGER(element) = dpman;

In the sinesrc _get function the old for() loop is replaced with:
  dpman = GST_ELEMENT_DPARAM_MANAGER(GST_ELEMENT(src));

  // in synchronous mode this is when the actual update will happen
  frame_countdown = GST_DPMAN_FIRST_COUNTDOWN(dpman, buffer_size,
timestamp);

  // the actual countdown function will only be called when
frame_countdown-- reaches 0
  while(GST_DPMAN_COUNTDOWN(dpman, frame_countdown, i)) {
    //... process each sample in the buffer
  }


this is the callback function which actually updates the parameter. It is
only called when the value changes
static void
gst_sinesrc_update_volume(GValue *value, gpointer data)
{
  GstSineSrc *src = (GstSineSrc*)data;
  g_return_if_fail(GST_IS_SINESRC(src));

  src->volume = g_value_get_float(value);
}


In the actual sinesliders test application the following is done after the
pipeline is created.
  dpman = GST_ELEMENT_DPARAM_MANAGER(sinesrc);
  volume = gst_dparam_new();
  freq = gst_dparam_new();

  gst_dpman_attach_dparam (dpman, "volume", volume);
  gst_dpman_attach_dparam (dpman, "freq", freq);
  
  // this is a realtime app so we want synchronous mode
  gst_dpman_set_mode(dpman, "synchronous");

  // set up signal handlers for the sliders
  g_signal_connect(volume_adj,"value-changed",
	
GTK_SIGNAL_FUNC(dynparm_value_changed),
					 volume);

  g_signal_connect(freq_adj,"value-changed",
	
GTK_SIGNAL_FUNC(dynparm_value_changed),
					 freq);


and the code that actually triggers the change of value
handler
static void dynparm_value_changed(GtkAdjustment *adj,GstDparam *dparam)
{
  GstDparamPoint *point;
  GValue *value;

  // there is only one point in this particular dparam implementation
  // so this is a bit contrived
  point = GST_DPARAM_GET_POINT(dparam, 0LL);
  value = point->values[0];

  g_print("setting value from %f to %f\n", g_value_get_float(value),
adj->value);  
  g_value_set_float(value, adj->value);

  // this flag will be noticed next time a sinesrc buffer is processed and
an update will happen
  GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE;
}

There is a lot more to the api which isn't used in this example, but you
should get the idea.

I'd like to commit this soon so if anyone has any major objections then mail
the list or check me out on irc.

cheers





More information about the gstreamer-devel mailing list