question on RAC for VP8

Zhao, Halley halley.zhao at intel.com
Sun Feb 17 22:56:28 PST 2013


Hi experts:
I'm writing a vp8 parser for gstreamer (used by gst-vaapi).
though it works on my side now, I have some question on the RAC (randomized arithmetic coding) part.

I start with GstBitReader for VP8 parser, but fail to parse token_prob_update and mv_prob_update parts since these two parts use RAC.
Then I copied RAC code from ffmpeg to make it work.

Now my questions are:

1)       Is there existing RAC code in gst to use?

2)       If not, should I extend GstBitReader for RAC or use the ffmpeg directly? (both gst codec parses and ffmpeg follows LGPL, it seems there is no legal issue).



Thanks.

Here are the ffmpeg RAC code for your reference:
void ff_vp56_init_range_decoder(VP56RangeCoder *c, const guint8 *buf, int buf_size)
{
    c->high = 255;
    c->bits = -16;
    c->buffer = buf;
    c->end = buf + buf_size;
    c->code_word = bytestream_get_be24(&c->buffer);
}


// rounding is different than vp56_rac_get, is vp56_rac_get wrong?
static av_always_inline int vp8_rac_get(VP56RangeCoder *c)
{
    return vp56_rac_get_prob(c, 128);
}

static av_always_inline unsigned int vp56_rac_renorm(VP56RangeCoder *c)
{
    int shift = ff_vp56_norm_shift[c->high];
    int bits = c->bits;
    unsigned int code_word = c->code_word;

    c->high   <<= shift;
    code_word <<= shift;
    bits       += shift;
    if(bits >= 0 && c->buffer < c->end) {
        code_word |= bytestream_get_be16(&c->buffer) << bits;
        bits -= 16;
    }
    c->bits = bits;
    return code_word;
}

static av_always_inline int vp56_rac_get_prob(VP56RangeCoder *c, guint8 prob)
{
    static int count = 0;
    unsigned int code_word = vp56_rac_renorm(c);
    unsigned int low = 1 + (((c->high - 1) * prob) >> 8);
    unsigned int low_shift = low << 16;
    int bit = code_word >= low_shift;

    // PRINTF("count: %4d, prob: %4x, c->code_word: %8x, code_word: %8x, low: %8x, bit: %d ", count, prob, c->code_word, code_word, low, bit);
    c->high = bit ? c->high - low : low;
    c->code_word = bit ? code_word - low_shift : code_word;
    // PRINTF(" #### c->high: %8x, c->code_word: %8x, c->bits: %d\n", c->high, c->code_word, c->bits);
    count++;

    return bit;
}

// branchy variant, to be used where there's a branch based on the bit decoded
static av_always_inline int vp56_rac_get_prob_branchy(VP56RangeCoder *c, int prob)
{
    unsigned long code_word = vp56_rac_renorm(c);
    unsigned low = 1 + (((c->high - 1) * prob) >> 8);
    unsigned low_shift = low << 16;

    if (code_word >= low_shift) {
        c->high     -= low;
        c->code_word = code_word - low_shift;
        return 1;
    }

    c->high = low;
    c->code_word = code_word;
    return 0;
}

static av_unused int vp8_rac_get_uint(VP56RangeCoder *c, int bits)
{
    int value = 0;

    while (bits--) {
        value = (value << 1) | vp8_rac_get(c);
    }

    return value;
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20130218/e46165e2/attachment.html>


More information about the gstreamer-devel mailing list