Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does anyone have an easy solution to parsing Exp-Golomb codes using C++?

Trying to decode the SDP sprop-parameter-sets values for an H.264 video stream and have found to access some of the values will involve parsing of Exp-Golomb encoded data and my method contains the base64 decoded sprop-parameter-sets data in a byte array which I now bit walking but have come up to the first part of Exp-Golomb encoded data and looking for a suitable code extract to parse these values.

like image 225
Jonathan Websdale Avatar asked Mar 02 '10 13:03

Jonathan Websdale


2 Answers

Exp.-Golomb codes of what order ?? If it you need to parse H.264 bit stream (I mean transport layer) you can write a simple functions to make an access to scecified bits in the endless bit stream. Bits indexing from left to right.

inline u_dword get_bit(const u_byte * const base, u_dword offset)
{
    return ((*(base + (offset >> 0x3))) >> (0x7 - (offset & 0x7))) & 0x1;
}

This function implement decoding of exp-Golomb codes of zero range (used in H.264).

u_dword DecodeUGolomb(const u_byte * const base, u_dword * const offset)
{
    u_dword zeros = 0;

    // calculate zero bits. Will be optimized.
    while (0 == get_bit(base, (*offset)++)) zeros++;

    // insert first 1 bit
    u_dword info = 1 << zeros;

    for (s_dword i = zeros - 1; i >= 0; i--)
    {
        info |= get_bit(base, (*offset)++) << i;
    }

    return (info - 1);

}

u_dword means unsigned 4 bytes integer. u_byte means unsigned 1 byte integer.

Note that first byte of each NAL Unit is a specified structure with forbidden bit, NAL reference, and NAL type.

like image 194
t0k3n1z3r Avatar answered Oct 05 '22 16:10

t0k3n1z3r


Accepted answer is not a correct implementation. It is giving wrong output. Correct implementation as per pseudo code from

"Sec 9.1 Parsing process for Exp-Golomb codes" spec T-REC-H.264-201304

int32_t getBitByPos(unsigned char *buffer, int32_t pos) {
    return (buffer[pos/8] >> (8 - pos%8) & 0x01);
}


uint32_t decodeGolomb(unsigned char *byteStream, uint32_t *index) {
    uint32_t leadingZeroBits = -1;
    uint32_t codeNum = 0;
    uint32_t pos = *index;

    if (byteStream == NULL || pos == 0 ) {
        printf("Invalid input\n");
        return 0;
    }

    for (int32_t b = 0; !b; leadingZeroBits++)
        b = getBitByPos(byteStream, pos++);

    for (int32_t b = leadingZeroBits; b > 0; b--)
        codeNum = codeNum | (getBitByPos(byteStream, pos++) << (b - 1));

    *index = pos;
    return ((1 << leadingZeroBits) - 1 + codeNum);
}
like image 29
Alam Avatar answered Oct 05 '22 16:10

Alam