The optimum choice for the bit precision of the video signals of a video processing algorithm may
differ for each particular implementation of that algorithm. The re-usability of an application
model therefore improves when it allows a range of bit precisions. In support of this, VYA
requires that the bit precision of the video input and the video output signals of each model is
parametrized. An adverse impact on the simulation speed is prevented by adopting a very simple
mechanism for this purpose: type VYApixel is assumed to range from to
, while the
effective range of the video input and/or output pixels is defined by parameters. To reflect that
the bit precision of an implementation is fixed, the bit precision parameters are passed as
arguments in the constructor of a process (network), which allows them to be programmable yet
forces them to be constant during each instantiation. For example:
class myVYAprocess : public VYAprocess { public: // constructor myVYAprocess( Id n, VYAbitPrecision inPrec, VYAbitPrecision outPrec, ... }; |
Class VYAbitPrecision is defined in vya.h,cc as follows:
class VYAbitPrecision { public: // constructors VYAbitPrecision(); VYAbitPrecision(VYAbitPrecision&); VYAbitPrecision(unsigned int, bool); // member variables unsigned int bits; bool signbit; }; |
Table 2 explains how the bit precision parameters determine the pixel range. These parameters must be supplied for input as well as output video interfaces. When a module has multiple video input and/or output interfaces, the programmer can choose to provide separate parameters for each interface or to combine them into a single parameter - e.g., UbitPrecIn and VbitPrecIn vs. UVbitPrecIn. To prevent incorrect behavior caused by illegal parameter values (e.g. signbit = true for a Y interface), modules must check parameter correctness by calling function VYAcheckPrecision which is a member function of VYAprocess provided in vya.h,cc.
The internal precision of an algorithm must be sufficient to handle the maximum input pixel range indicated in Table 2. Generally, it will suffice to use a 32-bit data type like int for intermediate results. Final results must be normalized to the required output precision; for this purpose, vya.h provides inline functions for rounding, shifting, clipping etc.
Because mapping an algorithm to an efficient implementation is
facilitated by understanding its internals, the internal precision of
a VYA module is preferably indicated by means of comments. In the
example shown below, a filter with gain 29 is applied to a
luminance line. By definition, the overall gain of a module equals
, which implies that the filter
output must be normalized by dividing it by
using round and shift
operations. Luminance data being unsigned, the result must finally be
clipped between 0 and 2outPrec.bits-1 to ensure the correct output
range. Comments indicate the bit precision of the input data and of
the result of every processing step. The format used is s.n.m,
where, s indicates the sign bit (0: positive; 1: negative; s:
positive or negative), n indicates unused bits, and m indicates
magnitude bits. Besides 16 bits for type VYApixel, this example
assumes 32 bits for type int.
void myVYAprocess::processLine() { int min, max, sf, data; unsigned int pix; min = 0; max = (1 << outPrec.bits) - 1; sf = inPrec.bits - outPrec.bits; // scale factor for (pix=0; pix<imgWidth; pix++) { // read pixel data = (int) Yin[pix]; // {0.31-inBits.inBits} // insert processing here // round, normalize and clip data = RNORM(data, sf); // {0.31-outBits.outBits} data = CLIP(data, min, max); // {0.31-outBits.outBits} // write pixel Yout[pix] = (VYApixel) data; // {0.15-outBits.outBits} } } |