This topic has not yet been rated Rate this topic

3.1.8.1.7.3.1 RLGR1/RLGR3 Decode

The following pseudocode sample shows how to decode a stream of bits encoded using the RLGR1/RLGR3 algorithm.

// Constants used within the RLGR1/RLGR3 algorithm

#define KPMAX   (80)   // max value for kp or krp
#define LSGR    (3)    // shift count to convert kp to k
#define UP_GR   (4)    // increase in kp after a zero run in RL mode
#define DN_GR   (6)    // decrease in kp after a nonzero symbol in RL mode
#define UQ_GR   (3)    // increase in kp after nonzero symbol in GR mode
#define DQ_GR   (3)    // decrease in kp after zero symbol in GR mode


//
// Gets (returns) the next nBits from the bitstream
// The layout of N bits in the bitstream with regard to a byte array is: 
//     [0..N] -> [0..7](MSB..LSB),[8..15](MSB..LSB) ...,
// where (MSB..LSB) denotes a byte.  
//

UINT GetBits(
    UINT nBits
    );


//
// From current output pointer, write "value", check and update *termsToDecode
// 
VOID
WriteValue(
    INT value,
    INT *termsToDecode
    );


//
// From current output pointer, write next nZeroes terms with value 0; 
// check and update *termsToDecode
//
VOID
WriteZeroes(
    UINT nZeroes, 
    INT *termsToDecode
    );


//
// Returns the least number of bits required to represent a given value
// 
UINT 
GetMinBits(
    UINT val// returns ceil(log2(val))
    );



// 
// Converts from (2 * magnitude - sign) to integer
//
INT
GetIntFrom2MagSign(
    UINT twoMs
    );


//
// Update the passed parameter and clamp it to the range [0,KPMAX]
// Return the value of parameter right-shifted by LSGR
//
INT 
UpdateParam(
    INT*  param,    // parameter to update
    INT   deltaP    // update delta
    )
{
    *param += deltaP;// adjust parameter
    if (*param > KPMAX) *param = KPMAX;// max clamp
    if (*param < 0) *param = 0;// min clamp
    return (*param >> LSGR);
}



//
// Outputs the Golomb/Rice encoding of a non-negative integer
//
UINT
GetGRCode(
    INT*   krp,
    INT*   kr
    )
{
    INT vk;
    UINT mag;

    // chew up/count leading 1s and escape 0
    for (vk=0;GetBits(1)==1;)    {
        vk++;
    }

    // get next *kr bits, and combine with leading 1s
    mag = (vk<<*kr) | GetBits(*kr);


    // adjust kpr and kr based on vk
    if (!vk)
    {
        *kr = UpdateParam(kpr, -2);
    }
    else if (vk!=1)// at 1, no change!
    {
        *kr = UpdateParam(kpr, vk);
    }

    return (mag);
}



//
// Routine that reads and decodes stream of RLGR data
//
VOID 
RLGR_Decode(
    RLGR_MODE rlgrMode,    // RLGR1 || RLGR3
    INT termsToDecode
    )
{
    // initialize the parameters
    INT k = 1;
    INT kp = k << LSGR;
    INT kr = 1;
    INT krp = kr << LSGR;

    while (termsToDecode > 0)
    {
        INT run;

        if (k)
        {
            // RL MODE
            while (GetBits(1) == 0)
            {
                // we have an RL escape "0", which translates to a run (1<<k) of zeros
                WriteZeroes(1<<k, &termsToDecode);
                k = UpdateParam(&kp,UpGR);  // raise k and kp up because of zero run
            }

            if (termsToDecode > 0)
            {
                // next k bits will contain remaining run of zeros
                run = GetBits(k);
                WriteZeroes(run, &termsToDecode);
            }

            if (termsToDecode > 0)
            {
                // get nonzero value, starting with sign bit and 
                // then GRCode for magnitude - 1
                UINT sign = GetBits(1);

                // magnitude - 1 was coded (because it was nonzero)
                INT mag = (INT)GetGRCode(&krp,&kr) + 1;

                WriteValue(sign ? -mag : mag, &termsToDecode);
                k = UpdateParam(&kp, -DnGR); // lower k and kp because of nonzero term
            }
        }
        else 
        {
            // GR (GOLOMB-RICE) MODE
            UINT mag = GetGRCode(&krp, &kr); // values coded are 2*magnitude - sign

            if (rlgrMode == RLGR1)
            {
                if (!mag)
                {
                    WriteValue(0, &termsToDecode);
                    k = UpdateParam(&kp, UqGR); // raise k and kp due to zero
                }
                else
                {
                    WriteValue(GetIntFrom2MagSign(mag), &termsToDecode);
                    k = UpdateParam(&kp, -DqGR);  // lower k and kp due to nonzero
                }

            }
            else // rlgrMode == RLGR3
            {
                // In GR mode FOR RLGR3, we have encoded the 
                // sum of two (2*mag - sign) values

                // maximum possible bits for first term
                UINT nIdx = GetMinBits(mag);

                // decode val1 is first term's (2*mag - sign) value
                UINT val1 = GetBits(nIdx);
              
                // val2 is second term's (2*mag - sign) value
                UINT val2 = mag - val1;

                if (val1 && val2) {
                    // raise k and kp if both terms nonzero
                    k = UpdateParam(&kp, -2*DqGR);
                } 
                else if (!val1 && !val2) {
                    // lower k and kp if both terms zero
                    k = UpdateParam(&kp, 2*UqGR);
                }


                WriteValue(GetIntFrom2MagSign(val1), &termsToDecode);
                WriteValue(GetIntFrom2MagSign(val2), &termsToDecode);
            }
        }
    }
}
 
Did you find this helpful?
(1500 characters remaining)