<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML ><HEAD ><TITLE >The Data Processing Loop</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK REL="HOME" TITLE="GStreamer Plugin Writer's Guide" HREF="index.html"><LINK REL="UP" TITLE="Supporting Dynamic Parameters" HREF="chapter-dparams.html"><LINK REL="PREVIOUS" TITLE="Defining Parameter Specificiations" HREF="section-dparam-define.html"><LINK REL="NEXT" TITLE="MIDI" HREF="chapter-advanced-midi.html"></HEAD ><BODY CLASS="sect1" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" ><SPAN CLASS="application" >GStreamer</SPAN > Plugin Writer's Guide</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="section-dparam-define.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" >Chapter 16. Supporting Dynamic Parameters</TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="chapter-advanced-midi.html" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="sect1" ><H1 CLASS="sect1" ><A NAME="chapter-dparam-loop" >16.4. The Data Processing Loop</A ></H1 ><P > This is the most critical aspect of the dparams subsystem as it relates to elements. In a traditional audio processing loop, a <TT CLASS="filename" >for</TT > 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. </P ><PRE CLASS="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; } ... } </PRE ><P > To make this dparams aware, a couple of changes are needed. </P ><PRE CLASS="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; } ... } </PRE ><P > The biggest changes here are 2 new macros, <TT CLASS="filename" >GST_DPMAN_PREPROCESS</TT > and <TT CLASS="filename" >GST_DPMAN_PROCESS_COUNTDOWN</TT >. You will also notice that the for loop has become a while loop. <TT CLASS="filename" >GST_DPMAN_PROCESS_COUNTDOWN</TT > 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 <SPAN CLASS="emphasis" ><I CLASS="emphasis" >sample accurate</I ></SPAN >. This means that parameters change at the exact timestamp that they are supposed to - not after the buffer has finished being processed. </P ><P > 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. </P ><PRE CLASS="programlisting" > #define GST_DPMAN_PROCESS_COUNTDOWN(dpman, frame_countdown, frame_count) \ (frame_countdown-- || \ (frame_countdown = GST_DPMAN_PROCESS(dpman, frame_count))) </PRE ><P > So as long as <TT CLASS="filename" >frame_countdown</TT > is greater than 0, <TT CLASS="filename" >GST_DPMAN_PROCESS</TT > will not be called at all. Also in many cases, <TT CLASS="filename" >GST_DPMAN_PROCESS</TT > will do nothing and simply return 0, meaning that there is no more data in the buffer to process. </P ><P > The macro <TT CLASS="filename" >GST_DPMAN_PREPROCESS</TT > will do the following: <P ></P ><UL ><LI ><P > Update any dparams which are due to be updated. </P ></LI ><LI ><P > Calculate how many samples should be processed before the next required update </P ></LI ><LI ><P > Return the number of samples until next update, or the number of samples in the buffer - whichever is less. </P ></LI ></UL > In fact <TT CLASS="filename" >GST_DPMAN_PROCESS</TT > may do the same things as <TT CLASS="filename" >GST_DPMAN_PREPROCESS</TT > depending on the mode that the dparam manager is running in (see below). </P ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="section-dparam-modes" >16.4.1. DParam Manager Modes</A ></H2 ><P > 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: <P ></P ><UL ><LI ><P > <SPAN CLASS="emphasis" ><I CLASS="emphasis" >Timelined</I ></SPAN > - all parameter changes are known in advance before the pipeline is run. </P ></LI ><LI ><P > <SPAN CLASS="emphasis" ><I CLASS="emphasis" >Realtime low-latency</I ></SPAN > - Nothing is known ahead of time about when a parameter might change. Changes need to be propagated to the element as soon as possible. </P ></LI ></UL > 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 <TT CLASS="filename" >"synchronous"</TT > and <TT CLASS="filename" >"asynchronous"</TT >. </P ><P > If you are in a realtime low-latency situation then the <TT CLASS="filename" >"synchronous"</TT > mode is appropriate. During <TT CLASS="filename" >GST_DPMAN_PREPROCESS</TT > this mode will poll all dparams for required updates and propagate them. <TT CLASS="filename" >GST_DPMAN_PROCESS</TT > 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. </P ><P > In a timelined situation, the <TT CLASS="filename" >"asynchronous"</TT > mode will be required. This mode hasn't actually been implemented yet but will be described anyway. The <TT CLASS="filename" >GST_DPMAN_PREPROCESS</TT > call will precalculate when and how often each dparam needs to update for the duration of the current buffer. From then on <TT CLASS="filename" >GST_DPMAN_PROCESS</TT > 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 <TT CLASS="filename" >"asynchronous"</TT > mode this could be done without affecting the sample accuracy of the parameter updates </P ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="section-dparam-audio-video" >16.4.2. DParam Manager Modes</A ></H2 ><P > 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 <TT CLASS="filename" >GST_DPMAN_PREPROCESS</TT > should be required. For more than one frame per buffer, treat it the same as the audio case. </P ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="section-dparam-define.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="chapter-advanced-midi.html" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >Defining Parameter Specificiations</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="chapter-dparams.html" ACCESSKEY="U" >Up</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >MIDI</TD ></TR ></TABLE ></DIV ></BODY ></HTML >