Chapter 23. The Data Processing Loop

Table of Contents

DParam Manager Modes
DParam Manager Modes

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:

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