diff mbox

[FFmpeg-devel,PATCHv3] VP4 video decoder

Message ID 929bfb61875495b9bafeb928ef2d50e67975a264.1558006168.git.pross@xvid.org
State Superseded
Headers show

Commit Message

Peter Ross May 16, 2019, 11:35 a.m. UTC
---

what's changed:
* reordered AV_CODEC_ID_VP4
* minor read_mb_values improvement (reproducible 0.5% speedup)
* configure/Makefile fix
* squished data tables to fill 80 columns.

UNCHECKED_BITSTREAM_READER doesn't give any performance improvement
on my i7, even with unrealisticly huge 4k vp4 video files.

 Changelog               |    1 +
 configure               |    1 +
 doc/general.texi        |    2 +
 libavcodec/Makefile     |    1 +
 libavcodec/allcodecs.c  |    1 +
 libavcodec/avcodec.h    |    1 +
 libavcodec/codec_desc.c |    7 +
 libavcodec/vp3.c        |  732 ++++++++++++++++++++++--
 libavcodec/vp4data.h    | 1186 +++++++++++++++++++++++++++++++++++++++
 9 files changed, 1896 insertions(+), 36 deletions(-)
 create mode 100644 libavcodec/vp4data.h

Comments

James Almer May 16, 2019, 1:49 p.m. UTC | #1
On 5/16/2019 8:35 AM, Peter Ross wrote:
> ---
> 
> what's changed:
> * reordered AV_CODEC_ID_VP4
> * minor read_mb_values improvement (reproducible 0.5% speedup)
> * configure/Makefile fix
> * squished data tables to fill 80 columns.
> 
> UNCHECKED_BITSTREAM_READER doesn't give any performance improvement
> on my i7, even with unrealisticly huge 4k vp4 video files.

I hope that was a typo and you tested CACHED_BITSTREAM_READER, not
UNCHECKED_BITSTREAM_READER :p

In any case, I wouldn't bother. Ricing a VP4 decoder is hardly worth
anyone's time.

> 
>  Changelog               |    1 +
>  configure               |    1 +
>  doc/general.texi        |    2 +
>  libavcodec/Makefile     |    1 +
>  libavcodec/allcodecs.c  |    1 +
>  libavcodec/avcodec.h    |    1 +
>  libavcodec/codec_desc.c |    7 +
>  libavcodec/vp3.c        |  732 ++++++++++++++++++++++--
>  libavcodec/vp4data.h    | 1186 +++++++++++++++++++++++++++++++++++++++
>  9 files changed, 1896 insertions(+), 36 deletions(-)
>  create mode 100644 libavcodec/vp4data.h
> 
> diff --git a/Changelog b/Changelog
> index e6b209ae0a..1c4e02d3aa 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -30,6 +30,7 @@ version <next>:
>  - colorhold filter
>  - xmedian filter
>  - asr filter
> +- VP4 video decoder
>  
>  
>  version 4.1:
> diff --git a/configure b/configure
> index 9b4305cf0d..8281174afd 100755
> --- a/configure
> +++ b/configure
> @@ -2825,6 +2825,7 @@ vc1image_decoder_select="vc1_decoder"
>  vorbis_decoder_select="mdct"
>  vorbis_encoder_select="audio_frame_queue mdct"
>  vp3_decoder_select="hpeldsp vp3dsp videodsp"
> +vp4_decoder_select="hpeldsp vp3dsp videodsp"

Theora enables the vp3 decoder instead of only the related modules
because by compiling vp3.c it's already compiling the entirety of the
vp3 decoder, so might as well have it enabled and available. IMO for vp4
you should do the same.

Also, big vp4 specific functions and big chunks of code within shared
functions should ideally be wrapped inside CONFIG_VP4_DECODER checks.

>  vp5_decoder_select="h264chroma hpeldsp videodsp vp3dsp vp56dsp"
>  vp6_decoder_select="h264chroma hpeldsp huffman videodsp vp3dsp vp56dsp"
>  vp6a_decoder_select="vp6_decoder"
Reimar Döffinger May 16, 2019, 6 p.m. UTC | #2
On Thu, May 16, 2019 at 09:35:00PM +1000, Peter Ross wrote:
> +static int read_mb_value(GetBitContext *gb)
> +{
> +    int v = 1;
> +    int size;
> +    OPEN_READER(re, gb);
> +
> +    do {
> +        int bit;
> +        size = 0;
> +
> +        UPDATE_CACHE(re, gb);
> +        bit = SHOW_UBITS(re, gb, 1);
> +        SKIP_BITS(re, gb, 1);
> +        if (!bit)
> +            break;
> +
> +        do {
> +            bit = SHOW_UBITS(re, gb, 1);
> +            SKIP_BITS(re, gb, 1);
> +            if (!bit)
> +                break;
> +            size++;
> +        } while (size < 8);
> +
> +        v += 1 << size;
> +
> +    } while (size == 8);
> +
> +    if (size) {
> +        v += SHOW_UBITS(re, gb, size);
> +        LAST_SKIP_BITS(re, gb, size);
> +    }
> +
> +    CLOSE_READER(re, gb);
> +    return v;
> +}

I meant that you should do something like
(could maybe be made less messy, and not
sure it's really necessary to use the macro
version, I think it'd prefer the plain
show_bits etc)

int v = 0;
int bits = SHOW_UBITS(re, gb, 9);
while (bits == 0x1ff) {
    // Note: relies on 0-padding to guarantee termination!
    SKIP_BITS(re, gb, 9);
    bits = SHOW_UBITS(re, gb, 9);
}
if (bits < 0x100) {
    LAST_SKIP_BITS(re, gb, 1);
    v = 1;
} else if (bits < 0x180) {
    LAST_SKIP_BITS(re, gb, 2);
    v = 2;
} else if (bits < 0x1c0) {
    LAST_SKIP_BITS(re, gb, 3 + 1);
    v = 3 + ((bits >> 5) & 1);
} else if (bits < 0x1e0) {
    LAST_SKIP_BITS(re, gb, 4 + 2);
    v = 5 + ((bits >> 3) & 3);
} else if (bits < 0x1f0) {
    LAST_SKIP_BITS(re, gb, 5 + 3);
    v = 9 + ((bits >> 1) & 7);
} else if (bits < 0x1f8) {
    SKIP_BITS(re, gb, 6);
    v = 17 + SHOW_UBITS(re, gb, 4);
    LAST_SKIP_BITS(re, gb, 4);
} else if (bits < 0x1fc) {
    SKIP_BITS(re, gb, 7);
    v = 33 + SHOW_UBITS(re, gb, 5);
    LAST_SKIP_BITS(re, gb, 5);
} else if (bits < 0x1fe) {
    SKIP_BITS(re, gb, 8);
    v = 65 + SHOW_UBITS(re, gb, 6);
    LAST_SKIP_BITS(re, gb, 6);
} else {
    SKIP_BITS(re, gb, 9);
    v = 127 + SHOW_UBITS(re, gb, 7);
    LAST_SKIP_BITS(re, gb, 7);
}

CLOSE_READER(re, gb);
return v;
Reimar Döffinger May 16, 2019, 6:48 p.m. UTC | #3
On Thu, May 16, 2019 at 08:00:55PM +0200, Reimar Döffinger wrote:
>     v = 127 + SHOW_UBITS(re, gb, 7);

Sorry typo, must be 129 instead of 127.
Reimar Döffinger May 16, 2019, 6:52 p.m. UTC | #4
On Thu, May 16, 2019 at 08:00:55PM +0200, Reimar Döffinger wrote:
> On Thu, May 16, 2019 at 09:35:00PM +1000, Peter Ross wrote:
> > +static int read_mb_value(GetBitContext *gb)
> > +{
> > +    int v = 1;
> > +    int size;
> > +    OPEN_READER(re, gb);
> > +
> > +    do {
> > +        int bit;
> > +        size = 0;
> > +
> > +        UPDATE_CACHE(re, gb);
> > +        bit = SHOW_UBITS(re, gb, 1);
> > +        SKIP_BITS(re, gb, 1);
> > +        if (!bit)
> > +            break;
> > +
> > +        do {
> > +            bit = SHOW_UBITS(re, gb, 1);
> > +            SKIP_BITS(re, gb, 1);
> > +            if (!bit)
> > +                break;
> > +            size++;
> > +        } while (size < 8);
> > +
> > +        v += 1 << size;
> > +
> > +    } while (size == 8);
> > +
> > +    if (size) {
> > +        v += SHOW_UBITS(re, gb, size);
> > +        LAST_SKIP_BITS(re, gb, size);
> > +    }
> > +
> > +    CLOSE_READER(re, gb);
> > +    return v;
> > +}
>
> I meant that you should do something like
> (could maybe be made less messy, and not
> sure it's really necessary to use the macro
> version, I think it'd prefer the plain
> show_bits etc)
>

So many bugs in the previous version, this
one is at least a bit more correct...

int v = 1;
int bits = SHOW_UBITS(re, gb, 9);
while (bits == 0x1ff) {
    // Note: relies on 0-padding to guarantee termination!
    SKIP_BITS(re, gb, 9);
    v += 256;
    bits = SHOW_UBITS(re, gb, 9);
}
if (bits < 0x100) {
    LAST_SKIP_BITS(re, gb, 1);
} else if (bits < 0x180) {
    LAST_SKIP_BITS(re, gb, 2);
    v += 1;
} else if (bits < 0x1c0) {
    LAST_SKIP_BITS(re, gb, 3 + 1);
    v += 2 + ((bits >> 5) & 1);
} else if (bits < 0x1e0) {
    LAST_SKIP_BITS(re, gb, 4 + 2);
    v += 4 + ((bits >> 3) & 3);
} else if (bits < 0x1f0) {
    LAST_SKIP_BITS(re, gb, 5 + 3);
    v += 8 + ((bits >> 1) & 7);
} else if (bits < 0x1f8) {
    SKIP_BITS(re, gb, 6);
    v += 16 + SHOW_UBITS(re, gb, 4);
    LAST_SKIP_BITS(re, gb, 4);
} else if (bits < 0x1fc) {
    SKIP_BITS(re, gb, 7);
    v += 32 + SHOW_UBITS(re, gb, 5);
    LAST_SKIP_BITS(re, gb, 5);
} else if (bits < 0x1fe) {
    SKIP_BITS(re, gb, 8);
    v += 64 + SHOW_UBITS(re, gb, 6);
    LAST_SKIP_BITS(re, gb, 6);
} else {
    SKIP_BITS(re, gb, 9);
    v += 128 + SHOW_UBITS(re, gb, 7);
    LAST_SKIP_BITS(re, gb, 7);
}

CLOSE_READER(re, gb);
return v;
Peter Ross May 17, 2019, 10:09 a.m. UTC | #5
On Thu, May 16, 2019 at 08:52:39PM +0200, Reimar Döffinger wrote:
> On Thu, May 16, 2019 at 08:00:55PM +0200, Reimar Döffinger wrote:
> > On Thu, May 16, 2019 at 09:35:00PM +1000, Peter Ross wrote:
> > > +static int read_mb_value(GetBitContext *gb)
> > > +{
> > > +    int v = 1;
> > > +    int size;
> > > +    OPEN_READER(re, gb);
> > > +
> > > +    do {
> > > +        int bit;
> > > +        size = 0;
> > > +
> > > +        UPDATE_CACHE(re, gb);
> > > +        bit = SHOW_UBITS(re, gb, 1);
> > > +        SKIP_BITS(re, gb, 1);
> > > +        if (!bit)
> > > +            break;
> > > +
> > > +        do {
> > > +            bit = SHOW_UBITS(re, gb, 1);
> > > +            SKIP_BITS(re, gb, 1);
> > > +            if (!bit)
> > > +                break;
> > > +            size++;
> > > +        } while (size < 8);
> > > +
> > > +        v += 1 << size;
> > > +
> > > +    } while (size == 8);
> > > +
> > > +    if (size) {
> > > +        v += SHOW_UBITS(re, gb, size);
> > > +        LAST_SKIP_BITS(re, gb, size);
> > > +    }
> > > +
> > > +    CLOSE_READER(re, gb);
> > > +    return v;
> > > +}
> >
> > I meant that you should do something like
> > (could maybe be made less messy, and not
> > sure it's really necessary to use the macro
> > version, I think it'd prefer the plain
> > show_bits etc)
> >
> 
> So many bugs in the previous version, this
> one is at least a bit more correct...

ah, i see what you did there! it works perfectly, just missing
UPDATE_CACHE at the start and in the loop.

test results on i7 decoding 3 minute long 4k video with vp4.

vp4 patch v3:
bench: utime=113.439s stime=0.414s rtime=30.161s
bench: utime=113.406s stime=0.403s rtime=30.123s
bench: utime=113.533s stime=0.310s rtime=30.104s
bench: utime=113.691s stime=0.414s rtime=30.148s
bench: utime=113.414s stime=0.435s rtime=30.102s
bench: utime=113.449s stime=0.370s rtime=30.138s
bench: utime=113.277s stime=0.470s rtime=30.139s

your patch + UPDATE_CACHE:
bench: utime=113.373s stime=0.386s rtime=30.109s
bench: utime=113.284s stime=0.378s rtime=30.122s
bench: utime=113.314s stime=0.414s rtime=30.125s
bench: utime=113.369s stime=0.378s rtime=30.130s
bench: utime=113.309s stime=0.394s rtime=30.108s
bench: utime=113.285s stime=0.435s rtime=30.048s
bench: utime=113.506s stime=0.362s rtime=30.182s

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
Peter Ross May 17, 2019, 10:10 a.m. UTC | #6
On Thu, May 16, 2019 at 10:49:41AM -0300, James Almer wrote:
> On 5/16/2019 8:35 AM, Peter Ross wrote:
> > ---
> > 
> > what's changed:
> > * reordered AV_CODEC_ID_VP4
> > * minor read_mb_values improvement (reproducible 0.5% speedup)
> > * configure/Makefile fix
> > * squished data tables to fill 80 columns.
> > 
> > UNCHECKED_BITSTREAM_READER doesn't give any performance improvement
> > on my i7, even with unrealisticly huge 4k vp4 video files.
> 
> I hope that was a typo and you tested CACHED_BITSTREAM_READER, not
> UNCHECKED_BITSTREAM_READER :p
> 
> In any case, I wouldn't bother. Ricing a VP4 decoder is hardly worth
> anyone's time.

oops, yes. and i agree.

> > @@ -2825,6 +2825,7 @@ vc1image_decoder_select="vc1_decoder"
> >  vorbis_decoder_select="mdct"
> >  vorbis_encoder_select="audio_frame_queue mdct"
> >  vp3_decoder_select="hpeldsp vp3dsp videodsp"
> > +vp4_decoder_select="hpeldsp vp3dsp videodsp"
> 
> Theora enables the vp3 decoder instead of only the related modules
> because by compiling vp3.c it's already compiling the entirety of the
> vp3 decoder, so might as well have it enabled and available. IMO for vp4
> you should do the same.
> 
> Also, big vp4 specific functions and big chunks of code within shared
> functions should ideally be wrapped inside CONFIG_VP4_DECODER checks.

thanks for spotting these. fixed and fixed.

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
Reimar Döffinger May 17, 2019, 6:13 p.m. UTC | #7
On Fri, May 17, 2019 at 08:09:45PM +1000, Peter Ross wrote:
> ah, i see what you did there! it works perfectly, just missing
> UPDATE_CACHE at the start and in the loop.
>
> test results on i7 decoding 3 minute long 4k video with vp4.

Looks fairly close to noise to me, though for me
it seemed a bit more obvious how the encoding
works from it (which was the primary reason to suggest it).
If one really wanted to optimize it for performance the
arrangement of the conditions can probably be improved, e.g.
the 0x1ff check is now the very first one even though
it is the least likely one (but avoids duplicating code
or needing crazy goto or loop constructs and thus
is more readable), and depending on probabilities
doing the range checks in a more tree-like structure
might also be better.
But as said, optimizing this has probably at most
curiosity value :)

> vp4 patch v3:
> bench: utime=113.439s stime=0.414s rtime=30.161s
> bench: utime=113.406s stime=0.403s rtime=30.123s
> bench: utime=113.533s stime=0.310s rtime=30.104s
> bench: utime=113.691s stime=0.414s rtime=30.148s
> bench: utime=113.414s stime=0.435s rtime=30.102s
> bench: utime=113.449s stime=0.370s rtime=30.138s
> bench: utime=113.277s stime=0.470s rtime=30.139s
>
> your patch + UPDATE_CACHE:
> bench: utime=113.373s stime=0.386s rtime=30.109s
> bench: utime=113.284s stime=0.378s rtime=30.122s
> bench: utime=113.314s stime=0.414s rtime=30.125s
> bench: utime=113.369s stime=0.378s rtime=30.130s
> bench: utime=113.309s stime=0.394s rtime=30.108s
> bench: utime=113.285s stime=0.435s rtime=30.048s
> bench: utime=113.506s stime=0.362s rtime=30.182s
Peter Ross May 19, 2019, 7:22 a.m. UTC | #8
On Fri, May 17, 2019 at 08:13:51PM +0200, Reimar Döffinger wrote:
> On Fri, May 17, 2019 at 08:09:45PM +1000, Peter Ross wrote:
> > ah, i see what you did there! it works perfectly, just missing
> > UPDATE_CACHE at the start and in the loop.
> >
> > test results on i7 decoding 3 minute long 4k video with vp4.
> 
> Looks fairly close to noise to me, though for me
> it seemed a bit more obvious how the encoding
> works from it (which was the primary reason to suggest it).
> If one really wanted to optimize it for performance the
> arrangement of the conditions can probably be improved, e.g.
> the 0x1ff check is now the very first one even though
> it is the least likely one (but avoids duplicating code
> or needing crazy goto or loop constructs and thus
> is more readable), and depending on probabilities
> doing the range checks in a more tree-like structure
> might also be better.
> But as said, optimizing this has probably at most
> curiosity value :)

i like your the while loop, it makes it more obvious
i don't have enough source sequences (or interest), do generate
those probabilities.

another run, on original raspberry pi with 720p sequence.

vp4 patch v3:
bench: utime=110.393s stime=5.232s rtime=115.835s
bench: utime=112.869s stime=4.981s rtime=118.235s
bench: utime=111.737s stime=5.220s rtime=117.168s
bench: utime=113.265s stime=5.250s rtime=118.730s
bench: utime=112.638s stime=5.120s rtime=117.938s
bench: utime=110.732s stime=5.190s rtime=116.133s
bench: utime=111.218s stime=5.013s rtime=116.444s
bench: utime=111.096s stime=4.768s rtime=116.076s
bench: utime=111.318s stime=5.073s rtime=116.603s

your patch + UPDATE_CACHE:
bnnch: utime=111.583s stime=5.421s rtime=117.251s
bench: utime=112.145s stime=4.799s rtime=117.155s
bench: utime=111.235s stime=5.552s rtime=116.967s
bench: utime=112.169s stime=5.248s rtime=117.628s
bench: utime=112.424s stime=5.178s rtime=117.813s
bench: utime=112.721s stime=5.182s rtime=118.115s
bench: utime=112.753s stime=5.162s rtime=118.125s
bench: utime=111.587s stime=5.267s rtime=117.065s
bench: utime=112.641s stime=4.952s rtime=117.805s

averaging the results your patch is a only marginally slower.
but basically no differnce.

converting your patch to use ordinary get_bits/show_bits however
does make it slower. average approx 0.4 seconds slower:

bench: utime=114.315s stime=5.292s rtime=119.820s
bench: utime=111.625s stime=5.481s rtime=117.317s
bench: utime=112.706s stime=5.063s rtime=117.982s
bench: utime=111.707s stime=5.221s rtime=117.137s
bench: utime=113.653s stime=5.451s rtime=119.318s
bench: utime=113.559s stime=5.332s rtime=119.104s
bench: utime=113.149s stime=5.261s rtime=118.621s
bench: utime=112.254s stime=5.401s rtime=117.868s
bench: utime=112.954s stime=5.532s rtime=118.698s

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
James Almer May 19, 2019, 2:20 p.m. UTC | #9
On 5/19/2019 4:22 AM, Peter Ross wrote:
> On Fri, May 17, 2019 at 08:13:51PM +0200, Reimar Döffinger wrote:
>> On Fri, May 17, 2019 at 08:09:45PM +1000, Peter Ross wrote:
>>> ah, i see what you did there! it works perfectly, just missing
>>> UPDATE_CACHE at the start and in the loop.
>>>
>>> test results on i7 decoding 3 minute long 4k video with vp4.
>>
>> Looks fairly close to noise to me, though for me
>> it seemed a bit more obvious how the encoding
>> works from it (which was the primary reason to suggest it).
>> If one really wanted to optimize it for performance the
>> arrangement of the conditions can probably be improved, e.g.
>> the 0x1ff check is now the very first one even though
>> it is the least likely one (but avoids duplicating code
>> or needing crazy goto or loop constructs and thus
>> is more readable), and depending on probabilities
>> doing the range checks in a more tree-like structure
>> might also be better.
>> But as said, optimizing this has probably at most
>> curiosity value :)
> 
> i like your the while loop, it makes it more obvious
> i don't have enough source sequences (or interest), do generate
> those probabilities.
> 
> another run, on original raspberry pi with 720p sequence.
> 
> vp4 patch v3:
> bench: utime=110.393s stime=5.232s rtime=115.835s
> bench: utime=112.869s stime=4.981s rtime=118.235s
> bench: utime=111.737s stime=5.220s rtime=117.168s
> bench: utime=113.265s stime=5.250s rtime=118.730s
> bench: utime=112.638s stime=5.120s rtime=117.938s
> bench: utime=110.732s stime=5.190s rtime=116.133s
> bench: utime=111.218s stime=5.013s rtime=116.444s
> bench: utime=111.096s stime=4.768s rtime=116.076s
> bench: utime=111.318s stime=5.073s rtime=116.603s
> 
> your patch + UPDATE_CACHE:
> bnnch: utime=111.583s stime=5.421s rtime=117.251s
> bench: utime=112.145s stime=4.799s rtime=117.155s
> bench: utime=111.235s stime=5.552s rtime=116.967s
> bench: utime=112.169s stime=5.248s rtime=117.628s
> bench: utime=112.424s stime=5.178s rtime=117.813s
> bench: utime=112.721s stime=5.182s rtime=118.115s
> bench: utime=112.753s stime=5.162s rtime=118.125s
> bench: utime=111.587s stime=5.267s rtime=117.065s
> bench: utime=112.641s stime=4.952s rtime=117.805s
> 
> averaging the results your patch is a only marginally slower.
> but basically no differnce.
> 
> converting your patch to use ordinary get_bits/show_bits however
> does make it slower. average approx 0.4 seconds slower:
> 
> bench: utime=114.315s stime=5.292s rtime=119.820s
> bench: utime=111.625s stime=5.481s rtime=117.317s
> bench: utime=112.706s stime=5.063s rtime=117.982s
> bench: utime=111.707s stime=5.221s rtime=117.137s
> bench: utime=113.653s stime=5.451s rtime=119.318s
> bench: utime=113.559s stime=5.332s rtime=119.104s
> bench: utime=113.149s stime=5.261s rtime=118.621s
> bench: utime=112.254s stime=5.401s rtime=117.868s
> bench: utime=112.954s stime=5.532s rtime=118.698s

Is it really important? VP4 samples are apparently not even available in
the wild. This decoder is IMO more important as an open source reference
implementation for the codec than a speed focused implementation, so
simplicity and readability should be the priority, which standard
get_bits() calls provide.

A 0.4 second speed boost on a 720p sample on a raspberri pi is not worth
making the code harder to read and port (You can easily port a get_bits
call to different bit reader frameworks, something you can't do if you
instead use the internal macro definitions).
diff mbox

Patch

diff --git a/Changelog b/Changelog
index e6b209ae0a..1c4e02d3aa 100644
--- a/Changelog
+++ b/Changelog
@@ -30,6 +30,7 @@  version <next>:
 - colorhold filter
 - xmedian filter
 - asr filter
+- VP4 video decoder
 
 
 version 4.1:
diff --git a/configure b/configure
index 9b4305cf0d..8281174afd 100755
--- a/configure
+++ b/configure
@@ -2825,6 +2825,7 @@  vc1image_decoder_select="vc1_decoder"
 vorbis_decoder_select="mdct"
 vorbis_encoder_select="audio_frame_queue mdct"
 vp3_decoder_select="hpeldsp vp3dsp videodsp"
+vp4_decoder_select="hpeldsp vp3dsp videodsp"
 vp5_decoder_select="h264chroma hpeldsp videodsp vp3dsp vp56dsp"
 vp6_decoder_select="h264chroma hpeldsp huffman videodsp vp3dsp vp56dsp"
 vp6a_decoder_select="vp6_decoder"
diff --git a/doc/general.texi b/doc/general.texi
index d2324612c2..146ab18dc8 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -937,6 +937,8 @@  following image formats are supported:
     @tab Video encoding used in NuppelVideo files.
 @item On2 VP3                @tab     @tab  X
     @tab still experimental
+@item On2 VP4                @tab     @tab  X
+    @tab fourcc: VP40
 @item On2 VP5                @tab     @tab  X
     @tab fourcc: VP50
 @item On2 VP6                @tab     @tab  X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index edccd73037..d76f392f1e 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -663,6 +663,7 @@  OBJS-$(CONFIG_VORBIS_DECODER)          += vorbisdec.o vorbisdsp.o vorbis.o \
 OBJS-$(CONFIG_VORBIS_ENCODER)          += vorbisenc.o vorbis.o \
                                           vorbis_data.o
 OBJS-$(CONFIG_VP3_DECODER)             += vp3.o
+OBJS-$(CONFIG_VP4_DECODER)             += vp3.o
 OBJS-$(CONFIG_VP5_DECODER)             += vp5.o vp56.o vp56data.o vp56rac.o
 OBJS-$(CONFIG_VP6_DECODER)             += vp6.o vp56.o vp56data.o \
                                           vp6dsp.o vp56rac.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 6178d31b5c..d2f9a39ce5 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -330,6 +330,7 @@  extern AVCodec ff_vcr1_decoder;
 extern AVCodec ff_vmdvideo_decoder;
 extern AVCodec ff_vmnc_decoder;
 extern AVCodec ff_vp3_decoder;
+extern AVCodec ff_vp4_decoder;
 extern AVCodec ff_vp5_decoder;
 extern AVCodec ff_vp6_decoder;
 extern AVCodec ff_vp6a_decoder;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index b749946633..586bbbca4e 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -456,6 +456,7 @@  enum AVCodecID {
     AV_CODEC_ID_ARBC,
     AV_CODEC_ID_AGM,
     AV_CODEC_ID_LSCR,
+    AV_CODEC_ID_VP4,
 
     /* various PCM "codecs" */
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 621b16e160..4d033c20ff 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1719,6 +1719,13 @@  static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("LEAD Screen Capture"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_VP4,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "vp4",
+        .long_name = NULL_IF_CONFIG_SMALL("On2 VP4"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
 
     /* various PCM "codecs" */
     {
diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index b248c90413..63920c60bd 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -1,5 +1,6 @@ 
 /*
  * Copyright (C) 2003-2004 The FFmpeg project
+ * Copyright (C) 2019 Peter Ross
  *
  * This file is part of FFmpeg.
  *
@@ -20,7 +21,7 @@ 
 
 /**
  * @file
- * On2 VP3 Video Decoder
+ * On2 VP3/VP4 Video Decoder
  *
  * VP3 Video Decoder by Mike Melanson (mike at multimedia.cx)
  * For more information about the VP3 coding process, visit:
@@ -43,6 +44,7 @@ 
 #include "thread.h"
 #include "videodsp.h"
 #include "vp3data.h"
+#include "vp4data.h"
 #include "vp3dsp.h"
 #include "xiph.h"
 
@@ -127,6 +129,30 @@  static const uint8_t hilbert_offset[16][2] = {
     { 3, 1 }, { 2, 1 }, { 2, 0 }, { 3, 0 }
 };
 
+enum {
+    VP4_DC_INTRA  = 0,
+    VP4_DC_INTER  = 1,
+    VP4_DC_GOLDEN = 2,
+    NB_VP4_DC_TYPES,
+    VP4_DC_UNDEFINED = NB_VP4_DC_TYPES
+};
+
+static const uint8_t vp4_pred_block_type_map[8] = {
+    [MODE_INTER_NO_MV]      = VP4_DC_INTER,
+    [MODE_INTRA]            = VP4_DC_INTRA,
+    [MODE_INTER_PLUS_MV]    = VP4_DC_INTER,
+    [MODE_INTER_LAST_MV]    = VP4_DC_INTER,
+    [MODE_INTER_PRIOR_LAST] = VP4_DC_INTER,
+    [MODE_USING_GOLDEN]     = VP4_DC_GOLDEN,
+    [MODE_GOLDEN_MV]        = VP4_DC_GOLDEN,
+    [MODE_INTER_FOURMV]     = VP4_DC_INTER,
+};
+
+typedef struct {
+    int dc;
+    int type;
+} VP4Predictor;
+
 #define MIN_DEQUANT_VAL 2
 
 typedef struct Vp3DecodeContext {
@@ -164,9 +190,13 @@  typedef struct Vp3DecodeContext {
     int v_superblock_start;
     unsigned char *superblock_coding;
 
-    int macroblock_count;
+    int macroblock_count; /* y macroblock count */
     int macroblock_width;
     int macroblock_height;
+    int c_macroblock_count;
+    int c_macroblock_width;
+    int c_macroblock_height;
+    int yuv_macroblock_count; /* y+u+v macroblock count */
 
     int fragment_count;
     int fragment_width[2];
@@ -182,7 +212,7 @@  typedef struct Vp3DecodeContext {
     int8_t (*motion_val[2])[2];
 
     /* tables */
-    uint16_t coded_dc_scale_factor[64];
+    uint16_t coded_dc_scale_factor[2][64];
     uint32_t coded_ac_scale_factor[64];
     uint8_t base_matrix[384][64];
     uint8_t qr_count[2][3];
@@ -233,10 +263,12 @@  typedef struct Vp3DecodeContext {
     VLC ac_vlc_3[16];
     VLC ac_vlc_4[16];
 
-    VLC superblock_run_length_vlc;
-    VLC fragment_run_length_vlc;
+    VLC superblock_run_length_vlc; /* version < 2 */
+    VLC fragment_run_length_vlc; /* version < 2 */
+    VLC block_pattern_vlc[2]; /* version >= 2*/
     VLC mode_code_vlc;
-    VLC motion_vector_vlc;
+    VLC motion_vector_vlc; /* version < 2 */
+    VLC vp4_mv_vlc[2][7]; /* version >=2 */
 
     /* these arrays need to be on 16-byte boundaries since SSE2 operations
      * index into them */
@@ -263,6 +295,8 @@  typedef struct Vp3DecodeContext {
 
     uint8_t filter_limit_values[64];
     DECLARE_ALIGNED(8, int, bounding_values_array)[256 + 2];
+
+    VP4Predictor * dc_pred_row; /* dc_pred_row[y_superblock_width * 4] */
 } Vp3DecodeContext;
 
 /************************************************************************
@@ -280,6 +314,7 @@  static av_cold void free_tables(AVCodecContext *avctx)
     av_freep(&s->dct_tokens_base);
     av_freep(&s->superblock_fragments);
     av_freep(&s->macroblock_coding);
+    av_freep(&s->dc_pred_row);
     av_freep(&s->motion_val[0]);
     av_freep(&s->motion_val[1]);
 }
@@ -299,7 +334,7 @@  static void vp3_decode_flush(AVCodecContext *avctx)
 static av_cold int vp3_decode_end(AVCodecContext *avctx)
 {
     Vp3DecodeContext *s = avctx->priv_data;
-    int i;
+    int i, j;
 
     free_tables(avctx);
     av_freep(&s->edge_emu_buffer);
@@ -328,6 +363,12 @@  static av_cold int vp3_decode_end(AVCodecContext *avctx)
     ff_free_vlc(&s->mode_code_vlc);
     ff_free_vlc(&s->motion_vector_vlc);
 
+    for (j = 0; j < 2; j++)
+        for (i = 0; i < 7; i++)
+            ff_free_vlc(&s->vp4_mv_vlc[j][i]);
+
+    for (i = 0; i < 2; i++)
+        ff_free_vlc(&s->block_pattern_vlc[i]);
     return 0;
 }
 
@@ -375,11 +416,11 @@  static int init_block_mapping(Vp3DecodeContext *s)
 static void init_dequantizer(Vp3DecodeContext *s, int qpi)
 {
     int ac_scale_factor = s->coded_ac_scale_factor[s->qps[qpi]];
-    int dc_scale_factor = s->coded_dc_scale_factor[s->qps[qpi]];
     int i, plane, inter, qri, bmi, bmj, qistart;
 
     for (inter = 0; inter < 2; inter++) {
         for (plane = 0; plane < 3; plane++) {
+            int dc_scale_factor = s->coded_dc_scale_factor[!!plane][s->qps[qpi]];
             int sum = 0;
             for (qri = 0; qri < s->qr_count[inter][plane]; qri++) {
                 sum += s->qr_size[inter][plane][qri];
@@ -397,9 +438,10 @@  static void init_dequantizer(Vp3DecodeContext *s, int qpi)
 
                 int qmin   = 8 << (inter + !i);
                 int qscale = i ? ac_scale_factor : dc_scale_factor;
-
+                int qbias = (1 + inter) * 3;
                 s->qmat[qpi][inter][plane][s->idct_permutation[i]] =
-                    av_clip((qscale * coeff) / 100 * 4, qmin, 4096);
+                    (i == 0 || s->version < 2) ? av_clip((qscale * coeff) / 100 * 4, qmin, 4096)
+                                               : (qscale * (coeff - qbias) / 100 + qbias) * 4;
             }
             /* all DC coefficients use the same quant so as not to interfere
              * with DC prediction */
@@ -598,6 +640,145 @@  static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
     return 0;
 }
 
+static int read_mb_value(GetBitContext *gb)
+{
+    int v = 1;
+    int size;
+    OPEN_READER(re, gb);
+
+    do {
+        int bit;
+        size = 0;
+
+        UPDATE_CACHE(re, gb);
+        bit = SHOW_UBITS(re, gb, 1);
+        SKIP_BITS(re, gb, 1);
+        if (!bit)
+            break;
+
+        do {
+            bit = SHOW_UBITS(re, gb, 1);
+            SKIP_BITS(re, gb, 1);
+            if (!bit)
+                break;
+            size++;
+        } while (size < 8);
+
+        v += 1 << size;
+
+    } while (size == 8);
+
+    if (size) {
+        v += SHOW_UBITS(re, gb, size);
+        LAST_SKIP_BITS(re, gb, size);
+    }
+
+    CLOSE_READER(re, gb);
+    return v;
+}
+
+static int vp4_get_block_pattern(Vp3DecodeContext *s, GetBitContext *gb, int *next_block_pattern_table)
+{
+    int v = get_vlc2(gb, s->block_pattern_vlc[*next_block_pattern_table].table, 3, 2);
+    if (v == -1) {
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid block pattern\n");
+        *next_block_pattern_table = 0;
+        return 0;
+    }
+    *next_block_pattern_table = vp4_block_pattern_table_selector[v];
+    return v + 1;
+}
+
+static int vp4_unpack_macroblocks(Vp3DecodeContext *s, GetBitContext *gb)
+{
+    int plane, i, j, k, fragment;
+    int next_block_pattern_table;
+    int bit, current_run, has_partial;
+
+    memset(s->macroblock_coding, MODE_COPY, s->macroblock_count);
+
+    if (s->keyframe)
+        return 0;
+
+    has_partial = 0;
+    bit         = get_bits1(gb);
+    current_run = read_mb_value(gb);
+
+    for (i = 0; i < s->yuv_macroblock_count; i++) {
+        if (!current_run) {
+            bit ^= 1;
+            current_run = read_mb_value(gb);
+        }
+        s->superblock_coding[i] = 2 * bit;
+        has_partial |= bit == 0;
+        current_run--;
+    }
+
+    if (has_partial) {
+        bit  = get_bits1(gb);
+        current_run = read_mb_value(gb);
+        for (i = 0; i < s->yuv_macroblock_count; i++) {
+            if (!s->superblock_coding[i]) {
+                if (!current_run) {
+                    bit ^= 1;
+                    current_run = read_mb_value(gb);
+                }
+                s->superblock_coding[i] = bit;
+                current_run--;
+            }
+        }
+    }
+
+    next_block_pattern_table = 0;
+    i = 0;
+    for (plane = 0; plane < 3; plane++) {
+        int sb_x, sb_y;
+        int sb_width = plane ? s->c_superblock_width : s->y_superblock_width;
+        int sb_height = plane ? s->c_superblock_height : s->y_superblock_height;
+        int mb_width = plane ? s->c_macroblock_width : s->macroblock_width;
+        int mb_height = plane ? s->c_macroblock_height : s->macroblock_height;
+        int fragment_width = s->fragment_width[!!plane];
+        int fragment_height = s->fragment_height[!!plane];
+
+        for (sb_y = 0; sb_y < sb_height; sb_y++) {
+            for (sb_x = 0; sb_x < sb_width; sb_x++) {
+                for (j = 0; j < 4; j++) {
+                    int mb_x = 2 * sb_x + (j >> 1);
+                    int mb_y = 2 * sb_y + (((j >> 1) + j) & 1);
+                    int mb_coded, pattern, coded;
+
+                    if (mb_x >= mb_width || mb_y >= mb_height)
+                        continue;
+
+                    mb_coded = s->superblock_coding[i++];
+
+                    if (mb_coded == SB_FULLY_CODED)
+                        pattern = 0xF;
+                    else if (mb_coded == SB_PARTIALLY_CODED)
+                        pattern = vp4_get_block_pattern(s, gb, &next_block_pattern_table);
+                    else
+                        pattern = 0;
+
+#define BLOCK_X (2 * mb_x + (k & 1))
+#define BLOCK_Y (2 * mb_y + (k >> 1))
+                    for (k = 0; k < 4; k++) {
+                        if (BLOCK_X >= fragment_width || BLOCK_Y >= fragment_height)
+                            continue;
+                        fragment = s->fragment_start[plane] + BLOCK_Y * fragment_width + BLOCK_X;
+
+                        coded = pattern & (1 << (3 - k));
+
+                        /* MODE_INTER_NO_MV is the default for coded fragments.
+                           the actual method is decoded in the next phase. */
+                        s->all_fragments[fragment].coding_method = coded ? MODE_INTER_NO_MV : MODE_COPY;
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+}
+
 /*
  * This function unpacks all the coding mode data for individual macroblocks
  * from the bitstream.
@@ -646,8 +827,6 @@  static int unpack_modes(Vp3DecodeContext *s, GetBitContext *gb)
                         mb_y >= s->macroblock_height)
                         continue;
 
-#define BLOCK_X (2 * mb_x + (k & 1))
-#define BLOCK_Y (2 * mb_y + (k >> 1))
                     /* coding modes are only stored if the macroblock has
                      * at least one luma block coded, otherwise it must be
                      * INTER_NO_MV */
@@ -707,6 +886,15 @@  static int unpack_modes(Vp3DecodeContext *s, GetBitContext *gb)
     return 0;
 }
 
+static int vp4_get_mv(Vp3DecodeContext *s, GetBitContext *gb, int axis, int last_motion)
+{
+    int v = get_vlc2(gb, s->vp4_mv_vlc[axis][vp4_mv_table_selector[FFABS(last_motion)]].table, 6, 2);
+    v -= 31;
+    if (last_motion < 0)
+        v = -v;
+    return v;
+}
+
 /*
  * This function unpacks all the motion vectors for the individual
  * macroblocks from the bitstream.
@@ -721,6 +909,8 @@  static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
     int last_motion_y = 0;
     int prior_last_motion_x = 0;
     int prior_last_motion_y = 0;
+    int last_gold_motion_x = 0;
+    int last_gold_motion_y = 0;
     int current_macroblock;
     int current_fragment;
     int frag;
@@ -728,8 +918,8 @@  static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
     if (s->keyframe)
         return 0;
 
-    /* coding mode 0 is the VLC scheme; 1 is the fixed code scheme */
-    coding_mode = get_bits1(gb);
+    /* coding mode 0 is the VLC scheme; 1 is the fixed code scheme; 2 is VP4 code scheme */
+    coding_mode = s->version < 2 ? get_bits1(gb) : 2;
 
     /* iterate through all of the macroblocks that contain 1 or more
      * coded fragments */
@@ -749,15 +939,25 @@  static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
                     continue;
 
                 switch (s->macroblock_coding[current_macroblock]) {
-                case MODE_INTER_PLUS_MV:
                 case MODE_GOLDEN_MV:
+                    if (coding_mode == 2) { /* VP4 */
+                        motion_x[0] = vp4_get_mv(s, gb, 0, last_gold_motion_x);
+                        motion_y[0] = vp4_get_mv(s, gb, 1, last_gold_motion_y);
+                        last_gold_motion_x = motion_x[0];
+                        last_gold_motion_y = motion_y[0];
+                        break;
+                    } /* otherwise fall through */
+                case MODE_INTER_PLUS_MV:
                     /* all 6 fragments use the same motion vector */
                     if (coding_mode == 0) {
                         motion_x[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
                         motion_y[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
-                    } else {
+                    } else if (coding_mode == 1) {
                         motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)];
                         motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)];
+                    } else { /* VP4 */
+                        motion_x[0] = vp4_get_mv(s, gb, 0, last_motion_x);
+                        motion_y[0] = vp4_get_mv(s, gb, 1, last_motion_y);
                     }
 
                     /* vector maintenance, only on MODE_INTER_PLUS_MV */
@@ -782,9 +982,12 @@  static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
                             if (coding_mode == 0) {
                                 motion_x[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
                                 motion_y[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
-                            } else {
+                            } else if (coding_mode == 1) {
                                 motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)];
                                 motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)];
+                            } else { /* VP4 */
+                                motion_x[k] = vp4_get_mv(s, gb, 0, prior_last_motion_x);
+                                motion_y[k] = vp4_get_mv(s, gb, 1, prior_last_motion_y);
                             }
                             last_motion_x = motion_x[k];
                             last_motion_y = motion_y[k];
@@ -846,8 +1049,10 @@  static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
                         motion_y[0] = RSHIFT(motion_y[0] + motion_y[1] +
                                              motion_y[2] + motion_y[3], 2);
                     }
-                    motion_x[0] = (motion_x[0] >> 1) | (motion_x[0] & 1);
-                    motion_y[0] = (motion_y[0] >> 1) | (motion_y[0] & 1);
+                    if (s->version <= 2) {
+                        motion_x[0] = (motion_x[0] >> 1) | (motion_x[0] & 1);
+                        motion_y[0] = (motion_y[0] >> 1) | (motion_y[0] & 1);
+                    }
                     frag = mb_y * s->fragment_width[1] + mb_x;
                     s->motion_val[1][frag][0] = motion_x[0];
                     s->motion_val[1][frag][1] = motion_y[0];
@@ -861,9 +1066,10 @@  static int unpack_vectors(Vp3DecodeContext *s, GetBitContext *gb)
                         motion_x[1] = motion_x[0];
                         motion_y[1] = motion_y[0];
                     }
-                    motion_x[0] = (motion_x[0] >> 1) | (motion_x[0] & 1);
-                    motion_x[1] = (motion_x[1] >> 1) | (motion_x[1] & 1);
-
+                    if (s->version <= 2) {
+                        motion_x[0] = (motion_x[0] >> 1) | (motion_x[0] & 1);
+                        motion_x[1] = (motion_x[1] >> 1) | (motion_x[1] & 1);
+                    }
                     frag = 2 * mb_y * s->fragment_width[1] + mb_x;
                     for (k = 0; k < 2; k++) {
                         s->motion_val[1][frag][0] = motion_x[k];
@@ -1012,8 +1218,8 @@  static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
             bits_to_get = coeff_get_bits[token];
             if (bits_to_get)
                 bits_to_get = get_bits(gb, bits_to_get);
-            coeff = coeff_tables[token][bits_to_get];
 
+            coeff = coeff_tables[token][bits_to_get];
             zero_run = zero_run_base[token];
             if (zero_run_get_bits[token])
                 zero_run += get_bits(gb, zero_run_get_bits[token]);
@@ -1168,6 +1374,242 @@  static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb)
     return 0;
 }
 
+/**
+ * eob_tracker[] is instead of TOKEN_EOB(value)
+ * a dummy TOKEN_EOB(0) value is used to make vp3_dequant work
+ *
+ * @return < 0 on error
+ */
+static int vp4_unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
+                       VLC *vlc_tables[64],
+                       int plane, int eob_tracker[64], int fragment)
+{
+    int token;
+    int zero_run  = 0;
+    int16_t coeff = 0;
+    int bits_to_get;
+    int coeff_i = 0;
+    int eob_run;
+
+    while (!eob_tracker[coeff_i]) {
+
+        token = get_vlc2(gb, vlc_tables[coeff_i]->table, 11, 3);
+
+        /* use the token to get a zero run, a coefficient, and an eob run */
+        if ((unsigned) token <= 6U) {
+            eob_run = eob_run_base[token];
+            if (eob_run_get_bits[token])
+                eob_run += get_bits(gb, eob_run_get_bits[token]);
+            *s->dct_tokens[plane][coeff_i]++ = TOKEN_EOB(0);
+            eob_tracker[coeff_i] = eob_run - 1;
+            return 0;
+        } else if (token >= 0) {
+            bits_to_get = coeff_get_bits[token];
+
+            if (bits_to_get)
+                bits_to_get = get_bits(gb, bits_to_get);
+            coeff = coeff_tables[token][bits_to_get];
+
+            zero_run = zero_run_base[token];
+            if (zero_run_get_bits[token])
+                zero_run += get_bits(gb, zero_run_get_bits[token]);
+
+            if (zero_run) {
+                if (coeff_i + zero_run > 64) {
+                    av_log(s->avctx, AV_LOG_DEBUG,
+                        "Invalid zero run of %d with %d coeffs left\n",
+                        zero_run, 64 - coeff_i);
+                    zero_run = 64 - coeff_i;
+                }
+                *s->dct_tokens[plane][coeff_i]++ = TOKEN_ZERO_RUN(coeff, zero_run);
+                coeff_i += zero_run;
+            } else {
+                if (!coeff_i)
+                    s->all_fragments[fragment].dc = coeff;
+
+                *s->dct_tokens[plane][coeff_i]++ = TOKEN_COEFF(coeff);
+            }
+            coeff_i++;
+            if (coeff_i >= 64) /* > 64 occurs when there is a zero_run overflow */
+                return 0; /* stop */
+        } else {
+            av_log(s->avctx, AV_LOG_ERROR, "Invalid token %d\n", token);
+            return -1;
+        }
+    }
+    *s->dct_tokens[plane][coeff_i]++ = TOKEN_EOB(0);
+    eob_tracker[coeff_i]--;
+    return 0;
+}
+
+static void vp4_dc_predictor_reset(VP4Predictor *p)
+{
+    p->dc = 0;
+    p->type = VP4_DC_UNDEFINED;
+}
+
+static void vp4_dc_pred_before(const Vp3DecodeContext *s, VP4Predictor * dc_pred, int sb_x)
+{
+    int i, j;
+
+    for (i = 0; i < 4; i++)
+        dc_pred[i + 1] = s->dc_pred_row[sb_x * 4 + i];
+
+    for (j = 0; j < 4; j++)
+        for (i = 0; i < 4; i++)
+            vp4_dc_predictor_reset(&dc_pred[j * 6 + i + 7]);
+}
+
+static void vp4_dc_pred_after(Vp3DecodeContext *s, VP4Predictor * dc_pred, int sb_x)
+{
+    int i;
+
+    for (i = 0; i < 4; i++)
+        s->dc_pred_row[sb_x * 4 + i] = dc_pred[25 + i];
+
+    for (i = 1; i < 5; i++)
+        dc_pred[6 * i] = dc_pred[6 * i + 4];
+}
+
+static int vp4_dc_pred(const Vp3DecodeContext *s, const VP4Predictor * dc_pred, const int * last_dc, int idx, int type, int plane)
+{
+    int count = 0;
+    int dc = 0;
+
+    if (dc_pred[idx - 6].type == type) {
+        dc += dc_pred[idx - 6].dc;
+        count++;
+    }
+
+    if (dc_pred[idx + 6].type == type) {
+        dc += dc_pred[idx + 6].dc;
+        count++;
+    }
+
+    if (count != 2 && dc_pred[idx - 1].type == type) {
+        dc += dc_pred[idx - 1].dc;
+        count++;
+    }
+
+    if (count != 2 && dc_pred[idx + 1].type == type) {
+        dc += dc_pred[idx + 1].dc;
+        count++;
+    }
+
+    return count == 2 ? dc / count : last_dc[type];
+}
+
+static void vp4_set_tokens_base(Vp3DecodeContext *s)
+{
+    int plane, i;
+    int16_t *base = s->dct_tokens_base;
+    for (plane = 0; plane < 3; plane++) {
+        for (i = 0; i < 64; i++) {
+            s->dct_tokens[plane][i] = base;
+            base += s->fragment_width[!!plane] * s->fragment_height[!!plane];
+        }
+    }
+}
+
+static int vp4_unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb)
+{
+    int i, j;
+    int dc_y_table;
+    int dc_c_table;
+    int ac_y_table;
+    int ac_c_table;
+    VLC *tables[2][64];
+    int plane, sb_y, sb_x;
+    int eob_tracker[64];
+    VP4Predictor dc_pred[6 * 6];
+    int last_dc[NB_VP4_DC_TYPES];
+
+    if (get_bits_left(gb) < 16)
+        return AVERROR_INVALIDDATA;
+
+    /* fetch the DC table indexes */
+    dc_y_table = get_bits(gb, 4);
+    dc_c_table = get_bits(gb, 4);
+
+    ac_y_table = get_bits(gb, 4);
+    ac_c_table = get_bits(gb, 4);
+
+    /* build tables of DC/AC VLC tables */
+
+    tables[0][0] = &s->dc_vlc[dc_y_table];
+    tables[1][0] = &s->dc_vlc[dc_c_table];
+    for (i = 1; i <= 5; i++) {
+        tables[0][i] = &s->ac_vlc_1[ac_y_table];
+        tables[1][i] = &s->ac_vlc_1[ac_c_table];
+    }
+    for (i = 6; i <= 14; i++) {
+        tables[0][i] = &s->ac_vlc_2[ac_y_table];
+        tables[1][i] = &s->ac_vlc_2[ac_c_table];
+    }
+    for (i = 15; i <= 27; i++) {
+        tables[0][i] = &s->ac_vlc_3[ac_y_table];
+        tables[1][i] = &s->ac_vlc_3[ac_c_table];
+    }
+    for (i = 28; i <= 63; i++) {
+        tables[0][i] = &s->ac_vlc_4[ac_y_table];
+        tables[1][i] = &s->ac_vlc_4[ac_c_table];
+    }
+
+    vp4_set_tokens_base(s);
+
+    memset(last_dc, 0, sizeof(last_dc));
+
+    for (plane = 0; plane < ((s->avctx->flags & AV_CODEC_FLAG_GRAY) ? 1 : 3); plane++) {
+        memset(eob_tracker, 0, sizeof(eob_tracker));
+
+        /* initialise dc prediction */
+        for (i = 0; i < s->fragment_width[!!plane]; i++)
+            vp4_dc_predictor_reset(&s->dc_pred_row[i]);
+
+        for (i = 1; i < 35; i++)
+            vp4_dc_predictor_reset(&dc_pred[i]);
+
+        for (sb_y = 0; sb_y * 4 < s->fragment_height[!!plane]; sb_y++) {
+            for (sb_x = 0; sb_x *4 < s->fragment_width[!!plane]; sb_x++) {
+                vp4_dc_pred_before(s, dc_pred, sb_x);
+                for (j = 0; j < 16; j++) {
+                        int hx = hilbert_offset[j][0];
+                        int hy = hilbert_offset[j][1];
+                        int x  = 4 * sb_x + hilbert_offset[j][0];
+                        int y  = 4 * sb_y + hilbert_offset[j][1];
+                        int fragment, dc_block_idx, dc_block_type;
+
+                        if (x >= s->fragment_width[!!plane] || y >= s->fragment_height[!!plane])
+                            continue;
+
+                        fragment = s->fragment_start[plane] + y * s->fragment_width[!!plane] + x;
+
+                        if (s->all_fragments[fragment].coding_method == MODE_COPY)
+                            continue;
+
+                        if (vp4_unpack_vlcs(s, gb, tables[!!plane], plane, eob_tracker, fragment) < 0)
+                            return -1;
+
+                        dc_block_idx = 6 * (hy + 1) + (hx + 1);
+                        dc_block_type = vp4_pred_block_type_map[s->all_fragments[fragment].coding_method];
+
+                        s->all_fragments[fragment].dc +=
+                            vp4_dc_pred(s, dc_pred, last_dc, dc_block_idx, dc_block_type, plane);
+
+                        dc_pred[dc_block_idx].type = dc_block_type;
+                        dc_pred[dc_block_idx].dc   =
+                        last_dc[dc_block_type]     = s->all_fragments[fragment].dc;
+                }
+                vp4_dc_pred_after(s, dc_pred, sb_x);
+            }
+        }
+    }
+
+    vp4_set_tokens_base(s);
+
+    return 0;
+}
+
 /*
  * This function reverses the DC prediction for each coded fragment in
  * the frame. Much of this function is adapted directly from the original
@@ -1500,6 +1942,98 @@  static void await_reference_row(Vp3DecodeContext *s, Vp3Fragment *fragment,
     ff_thread_await_progress(ref_frame, ref_row, 0);
 }
 
+/**
+ * @return non-zero if temp (edge_emu_buffer) was populated
+ */
+static int vp4_mc_loop_filter(Vp3DecodeContext *s, int plane, int motion_x, int motion_y, int bx, int by,
+       uint8_t * motion_source, int stride, int src_x, int src_y, uint8_t *temp)
+{
+    static const int motion_shift[2] = { 1, 2 };
+    static const int subpel_mask[2]  = { 1, 3 };
+    int *bounding_values = s->bounding_values_array + 127;
+
+    int i;
+    int x, y;
+    int x2, y2;
+    int x_subpel, y_subpel;
+    int x_offset, y_offset;
+
+    int block_width = plane ? 8 : 16;
+    int plane_width  = s->width  >> (plane && s->chroma_x_shift);
+    int plane_height = s->height >> (plane && s->chroma_y_shift);
+
+#define loop_stride 12
+    uint8_t loop[12 * loop_stride];
+
+#define SHIFT(v, shift) ((v) >> (shift))
+#define ABS_SHIFT(v, shift) ((v) > 0 ? SHIFT(v, shift) : -SHIFT(-v, shift))
+    x = 8 * bx + ABS_SHIFT(motion_x, motion_shift[!!plane]);
+    y = 8 * by + ABS_SHIFT(motion_y, motion_shift[!!plane]);
+
+    x_subpel = motion_x & subpel_mask[!!plane];
+    y_subpel = motion_y & subpel_mask[!!plane];
+
+    if (x_subpel || y_subpel) {
+        x--;
+        y--;
+
+        if (x_subpel)
+            x = FFMIN(x, x + FFSIGN(motion_x));
+
+        if (y_subpel)
+            y = FFMIN(y, y + FFSIGN(motion_y));
+
+        x2 = x + block_width;
+        y2 = y + block_width;
+
+        if (x2 < 0 || x2 >= plane_width || y2 < 0 || y2 >= plane_height)
+            return 0;
+
+        x_offset = (-(x + 2) & 7) + 2;
+        y_offset = (-(y + 2) & 7) + 2;
+
+        if (x_offset > 8 + x_subpel && y_offset > 8 + y_subpel)
+            return 0;
+
+        s->vdsp.emulated_edge_mc(loop, motion_source - stride - 1,
+             loop_stride, stride,
+             12, 12, src_x - 1, src_y - 1,
+             plane_width,
+             plane_height);
+
+        if (x_offset <= 8 + x_subpel)
+            ff_vp3dsp_h_loop_filter_12(loop + x_offset, loop_stride, bounding_values);
+
+        if (y_offset <= 8 + y_subpel)
+            ff_vp3dsp_v_loop_filter_12(loop + y_offset*loop_stride, loop_stride, bounding_values);
+
+    } else {
+
+        x_offset = -x & 7;
+        y_offset = -y & 7;
+
+        if (!x_offset && !y_offset)
+            return 0;
+
+        s->vdsp.emulated_edge_mc(loop, motion_source - stride - 1,
+             loop_stride, stride,
+             12, 12, src_x - 1, src_y - 1,
+             plane_width,
+             plane_height);
+
+        if (x_offset)
+            s->vp3dsp.h_loop_filter(loop + loop_stride + x_offset + 1, loop_stride, bounding_values);
+
+        if (y_offset)
+            s->vp3dsp.v_loop_filter(loop + (y_offset + 1)*loop_stride + 1, loop_stride, bounding_values);
+    }
+
+    for (i = 0; i < 9; i++)
+        memcpy(temp + i*stride, loop + (i + 1) * loop_stride + 1, 9);
+
+    return 1;
+}
+
 /*
  * Perform the final rendering for a particular slice of data.
  * The slice number ranges from 0..(c_superblock_height - 1).
@@ -1585,8 +2119,13 @@  static void render_slice(Vp3DecodeContext *s, int slice)
                         if ((s->all_fragments[i].coding_method > MODE_INTRA) &&
                             (s->all_fragments[i].coding_method != MODE_USING_GOLDEN)) {
                             int src_x, src_y;
+                            int standard_mc = 1;
                             motion_x = motion_val[fragment][0];
                             motion_y = motion_val[fragment][1];
+                            if (plane && s->version >= 2) {
+                                motion_x = (motion_x >> 1) | (motion_x & 1);
+                                motion_y = (motion_y >> 1) | (motion_y & 1);
+                            }
 
                             src_x = (motion_x >> 1) + 8 * x;
                             src_y = (motion_y >> 1) + 8 * y;
@@ -1597,9 +2136,20 @@  static void render_slice(Vp3DecodeContext *s, int slice)
                             motion_halfpel_index |= (motion_y & 0x01) << 1;
                             motion_source        += ((motion_y >> 1) * stride);
 
-                            if (src_x < 0 || src_y < 0 ||
+                            if (s->version >= 2) {
+                                uint8_t *temp = s->edge_emu_buffer;
+                                if (stride < 0)
+                                    temp -= 8 * stride;
+                                if (vp4_mc_loop_filter(s, plane, motion_val[fragment][0], motion_val[fragment][1], x, y, motion_source, stride, src_x, src_y, temp)) {
+                                    motion_source = temp;
+                                    standard_mc = 0;
+                                }
+                            }
+
+                            if (standard_mc && (
+                                src_x < 0 || src_y < 0 ||
                                 src_x + 9 >= plane_width ||
-                                src_y + 9 >= plane_height) {
+                                src_y + 9 >= plane_height)) {
                                 uint8_t *temp = s->edge_emu_buffer;
                                 if (stride < 0)
                                     temp -= 8 * stride;
@@ -1665,7 +2215,7 @@  static void render_slice(Vp3DecodeContext *s, int slice)
             }
 
             // Filter up to the last row in the superblock row
-            if (!s->skip_loop_filter)
+            if (s->version < 2 && !s->skip_loop_filter)
                 apply_loop_filter(s, plane, 4 * sb_y - !!sb_y,
                                   FFMIN(4 * sb_y + 3, fragment_height - 1));
         }
@@ -1694,7 +2244,8 @@  static av_cold int allocate_tables(AVCodecContext *avctx)
     y_fragment_count = s->fragment_width[0] * s->fragment_height[0];
     c_fragment_count = s->fragment_width[1] * s->fragment_height[1];
 
-    s->superblock_coding = av_mallocz(s->superblock_count);
+    /* superblock_coding is used by unpack_superblocks (VP3/Theora) and vp4_unpack_macroblocks (VP4) */
+    s->superblock_coding = av_mallocz(FFMAX(s->superblock_count, s->yuv_macroblock_count));
     s->all_fragments     = av_mallocz_array(s->fragment_count, sizeof(Vp3Fragment));
 
     s-> kf_coded_fragment_list = av_mallocz_array(s->fragment_count, sizeof(int));
@@ -1710,10 +2261,13 @@  static av_cold int allocate_tables(AVCodecContext *avctx)
     s->superblock_fragments = av_mallocz_array(s->superblock_count, 16 * sizeof(int));
     s->macroblock_coding    = av_mallocz(s->macroblock_count + 1);
 
+    s->dc_pred_row = av_malloc_array(s->y_superblock_width * 4, sizeof(*s->dc_pred_row));
+
     if (!s->superblock_coding    || !s->all_fragments          ||
         !s->dct_tokens_base      || !s->kf_coded_fragment_list ||
         !s->nkf_coded_fragment_list ||
         !s->superblock_fragments || !s->macroblock_coding      ||
+        !s->dc_pred_row ||
         !s->motion_val[0]        || !s->motion_val[1]) {
         vp3_decode_end(avctx);
         return -1;
@@ -1743,7 +2297,7 @@  static av_cold int init_frames(Vp3DecodeContext *s)
 static av_cold int vp3_decode_init(AVCodecContext *avctx)
 {
     Vp3DecodeContext *s = avctx->priv_data;
-    int i, inter, plane, ret;
+    int i, j, inter, plane, ret;
     int c_width;
     int c_height;
     int y_fragment_count, c_fragment_count;
@@ -1754,7 +2308,9 @@  static av_cold int vp3_decode_init(AVCodecContext *avctx)
 
     avctx->internal->allocate_progress = 1;
 
-    if (avctx->codec_tag == MKTAG('V', 'P', '3', '0'))
+    if (avctx->codec_tag == MKTAG('V', 'P', '4', '0'))
+        s->version = 3;
+    else if (avctx->codec_tag == MKTAG('V', 'P', '3', '0'))
         s->version = 0;
     else
         s->version = 1;
@@ -1803,6 +2359,10 @@  static av_cold int vp3_decode_init(AVCodecContext *avctx)
     s->macroblock_width  = (s->width  + 15) / 16;
     s->macroblock_height = (s->height + 15) / 16;
     s->macroblock_count  = s->macroblock_width * s->macroblock_height;
+    s->c_macroblock_width  = (c_width  + 15) / 16;
+    s->c_macroblock_height = (c_height + 15) / 16;
+    s->c_macroblock_count  = s->c_macroblock_width * s->c_macroblock_height;
+    s->yuv_macroblock_count = s->macroblock_count + 2 * s->c_macroblock_count;
 
     s->fragment_width[0]  = s->width / FRAGMENT_PIXELS;
     s->fragment_height[0] = s->height / FRAGMENT_PIXELS;
@@ -1818,12 +2378,13 @@  static av_cold int vp3_decode_init(AVCodecContext *avctx)
 
     if (!s->theora_tables) {
         for (i = 0; i < 64; i++) {
-            s->coded_dc_scale_factor[i] = vp31_dc_scale_factor[i];
-            s->coded_ac_scale_factor[i] = vp31_ac_scale_factor[i];
-            s->base_matrix[0][i]        = vp31_intra_y_dequant[i];
-            s->base_matrix[1][i]        = vp31_intra_c_dequant[i];
-            s->base_matrix[2][i]        = vp31_inter_dequant[i];
-            s->filter_limit_values[i]   = vp31_filter_limit_values[i];
+            s->coded_dc_scale_factor[0][i] = s->version < 2 ? vp31_dc_scale_factor[i] : vp4_y_dc_scale_factor[i];
+            s->coded_dc_scale_factor[1][i] = s->version < 2 ? vp31_dc_scale_factor[i] : vp4_uv_dc_scale_factor[i];
+            s->coded_ac_scale_factor[i] = s->version < 2 ? vp31_ac_scale_factor[i] : vp4_ac_scale_factor[i];
+            s->base_matrix[0][i]        = s->version < 2 ? vp31_intra_y_dequant[i] : vp4_generic_dequant[i];
+            s->base_matrix[1][i]        = s->version < 2 ? vp31_intra_c_dequant[i] : vp4_generic_dequant[i];
+            s->base_matrix[2][i]        = s->version < 2 ? vp31_inter_dequant[i]   : vp4_generic_dequant[i];
+            s->filter_limit_values[i]   = s->version < 2 ? vp31_filter_limit_values[i] : vp4_filter_limit_values[i];
         }
 
         for (inter = 0; inter < 2; inter++) {
@@ -1836,6 +2397,7 @@  static av_cold int vp3_decode_init(AVCodecContext *avctx)
         }
 
         /* init VLC tables */
+        if (s->version < 2) {
         for (i = 0; i < 16; i++) {
             /* DC histograms */
             init_vlc(&s->dc_vlc[i], 11, 32,
@@ -1862,6 +2424,34 @@  static av_cold int vp3_decode_init(AVCodecContext *avctx)
                      &ac_bias_3[i][0][1], 4, 2,
                      &ac_bias_3[i][0][0], 4, 2, 0);
         }
+        } else { /* version >= 2 */
+            for (i = 0; i < 16; i++) {
+                /* DC histograms */
+                init_vlc(&s->dc_vlc[i], 11, 32,
+                         &vp4_dc_bias[i][0][1], 4, 2,
+                         &vp4_dc_bias[i][0][0], 4, 2, 0);
+
+                /* group 1 AC histograms */
+                init_vlc(&s->ac_vlc_1[i], 11, 32,
+                         &vp4_ac_bias_0[i][0][1], 4, 2,
+                         &vp4_ac_bias_0[i][0][0], 4, 2, 0);
+
+                /* group 2 AC histograms */
+                init_vlc(&s->ac_vlc_2[i], 11, 32,
+                         &vp4_ac_bias_1[i][0][1], 4, 2,
+                         &vp4_ac_bias_1[i][0][0], 4, 2, 0);
+
+                /* group 3 AC histograms */
+                init_vlc(&s->ac_vlc_3[i], 11, 32,
+                         &vp4_ac_bias_2[i][0][1], 4, 2,
+                         &vp4_ac_bias_2[i][0][0], 4, 2, 0);
+
+                /* group 4 AC histograms */
+                init_vlc(&s->ac_vlc_4[i], 11, 32,
+                         &vp4_ac_bias_3[i][0][1], 4, 2,
+                         &vp4_ac_bias_3[i][0][0], 4, 2, 0);
+            }
+        }
     } else {
         for (i = 0; i < 16; i++) {
             /* DC histograms */
@@ -1912,6 +2502,19 @@  static av_cold int vp3_decode_init(AVCodecContext *avctx)
              &motion_vector_vlc_table[0][1], 2, 1,
              &motion_vector_vlc_table[0][0], 2, 1, 0);
 
+    for (j = 0; j < 2; j++)
+        for (i = 0; i < 7; i++)
+            init_vlc(&s->vp4_mv_vlc[j][i], 6, 63,
+                 &vp4_mv_vlc[j][i][0][1], 4, 2,
+                 &vp4_mv_vlc[j][i][0][0], 4, 2, 0);
+
+    /* version >= 2 */
+    for (i = 0; i < 2; i++)
+        init_vlc(&s->block_pattern_vlc[i], 3, 14,
+             &vp4_block_pattern_vlc[i][0][1], 2, 1,
+             &vp4_block_pattern_vlc[i][0][0], 2, 1, 0);
+
+
     return allocate_tables(avctx);
 
 vlc_fail:
@@ -2135,6 +2738,27 @@  static int vp3_decode_frame(AVCodecContext *avctx,
                 av_log(s->avctx, AV_LOG_ERROR,
                        "Warning, unsupported keyframe coding type?!\n");
             skip_bits(&gb, 2); /* reserved? */
+
+            if (s->version >= 2) {
+                int mb_height, mb_width;
+                int mb_width_mul, mb_width_div, mb_height_mul, mb_height_div;
+
+                mb_height = get_bits(&gb, 8);
+                mb_width  = get_bits(&gb, 8);
+                if (mb_height != s->macroblock_height ||
+                    mb_width != s->macroblock_width)
+                    av_log(s->avctx, AV_LOG_WARNING, "VP4 header: Warning, macroblock dimension mismatch");
+
+                mb_width_mul = get_bits(&gb, 5);
+                mb_width_div = get_bits(&gb, 3);
+                mb_height_mul = get_bits(&gb, 5);
+                mb_height_div = get_bits(&gb, 3);
+                if (mb_width_mul != 1 || mb_width_div != 1 || mb_height_mul != 1 || mb_height_div != 1)
+                      av_log(s->avctx, AV_LOG_WARNING, "VP4 header: Warning, unexpected macroblock dimension multipler/divider");
+
+                if (get_bits(&gb, 2))
+                    av_log(s->avctx, AV_LOG_WARNING, "VP4 header: Warning, unknown bits set");
+            }
         }
     } else {
         if (!s->golden_frame.f->data[0]) {
@@ -2156,10 +2780,17 @@  static int vp3_decode_frame(AVCodecContext *avctx,
     memset(s->all_fragments, 0, s->fragment_count * sizeof(Vp3Fragment));
     ff_thread_finish_setup(avctx);
 
+    if (s->version < 2) {
     if (unpack_superblocks(s, &gb)) {
         av_log(s->avctx, AV_LOG_ERROR, "error in unpack_superblocks\n");
         goto error;
     }
+    } else {
+        if (vp4_unpack_macroblocks(s, &gb)) {
+            av_log(s->avctx, AV_LOG_ERROR, "error in vp4_unpack_macroblocks\n");
+            goto error;
+    }
+    }
     if (unpack_modes(s, &gb)) {
         av_log(s->avctx, AV_LOG_ERROR, "error in unpack_modes\n");
         goto error;
@@ -2172,10 +2803,18 @@  static int vp3_decode_frame(AVCodecContext *avctx,
         av_log(s->avctx, AV_LOG_ERROR, "error in unpack_block_qpis\n");
         goto error;
     }
+
+    if (s->version < 2) {
     if (unpack_dct_coeffs(s, &gb)) {
         av_log(s->avctx, AV_LOG_ERROR, "error in unpack_dct_coeffs\n");
         goto error;
     }
+    } else {
+        if (vp4_unpack_dct_coeffs(s, &gb)) {
+            av_log(s->avctx, AV_LOG_ERROR, "error in vp4_unpack_dct_coeffs\n");
+            goto error;
+        }
+    }
 
     for (i = 0; i < 3; i++) {
         int height = s->height >> (i && s->chroma_y_shift);
@@ -2190,6 +2829,7 @@  static int vp3_decode_frame(AVCodecContext *avctx,
         render_slice(s, i);
 
     // filter the last row
+    if (s->version < 2)
     for (i = 0; i < 3; i++) {
         int row = (s->height >> (3 + (i && s->chroma_y_shift))) - 1;
         apply_loop_filter(s, i, row, row + 1);
@@ -2274,6 +2914,7 @@  static int vp3_init_thread_copy(AVCodecContext *avctx)
     s->motion_val[0]          = NULL;
     s->motion_val[1]          = NULL;
     s->edge_emu_buffer        = NULL;
+    s->dc_pred_row            = NULL;
 
     return init_frames(s);
 }
@@ -2422,7 +3063,8 @@  static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb)
         n = 16;
     /* dc scale factor table */
     for (i = 0; i < 64; i++)
-        s->coded_dc_scale_factor[i] = get_bits(gb, n);
+        s->coded_dc_scale_factor[0][i] =
+        s->coded_dc_scale_factor[1][i] = get_bits(gb, n);
 
     if (s->theora >= 0x030200)
         matrices = get_bits(gb, 9) + 1;
@@ -2608,3 +3250,21 @@  AVCodec ff_vp3_decoder = {
     .init_thread_copy      = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy),
     .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context),
 };
+
+#if CONFIG_VP4_DECODER
+AVCodec ff_vp4_decoder = {
+    .name                  = "vp4",
+    .long_name             = NULL_IF_CONFIG_SMALL("On2 VP4"),
+    .type                  = AVMEDIA_TYPE_VIDEO,
+    .id                    = AV_CODEC_ID_VP4,
+    .priv_data_size        = sizeof(Vp3DecodeContext),
+    .init                  = vp3_decode_init,
+    .close                 = vp3_decode_end,
+    .decode                = vp3_decode_frame,
+    .capabilities          = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
+                             AV_CODEC_CAP_FRAME_THREADS,
+    .flush                 = vp3_decode_flush,
+    .init_thread_copy      = ONLY_IF_THREADS_ENABLED(vp3_init_thread_copy),
+    .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context),
+};
+#endif
diff --git a/libavcodec/vp4data.h b/libavcodec/vp4data.h
new file mode 100644
index 0000000000..69a009eff1
--- /dev/null
+++ b/libavcodec/vp4data.h
@@ -0,0 +1,1186 @@ 
+/*
+ * Copyright (C) 2019 Peter Ross
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * VP4 video decoder
+ */
+
+#ifndef AVCODEC_VP4DATA_H
+#define AVCODEC_VP4DATA_H
+
+#include <stdint.h>
+
+static const uint8_t vp4_generic_dequant[64] = {
+    16, 17, 18, 20, 22, 24, 26, 28,
+    17, 18, 20, 22, 24, 26, 28, 32,
+    18, 20, 22, 24, 26, 28, 32, 36,
+    20, 22, 24, 26, 28, 32, 36, 40,
+    22, 24, 26, 28, 32, 36, 40, 44,
+    24, 26, 28, 32, 36, 40, 44, 48,
+    26, 28, 32, 36, 40, 44, 48, 52,
+    28, 32, 36, 40, 44, 48, 52, 56
+};
+
+static const uint8_t vp4_y_dc_scale_factor[64] = {
+    180, 180, 180, 180, 180, 180, 175, 170,
+    165, 160, 157, 155, 152, 150, 147, 145,
+    142, 140, 137, 135, 132, 130, 127, 125,
+    122, 120, 117, 115, 112, 110, 107, 105,
+    102, 100,  97,  95,  92,  90,  87,  85,
+     82,  80,  77,  75,  72,  70,  67,  65,
+     62,  60,  57,  55,  52,  50,  47,  45,
+     42,  40,  37,  35,  32,  30,  27,  25
+};
+
+static const uint8_t vp4_uv_dc_scale_factor[64] = {
+    150, 150, 150, 150, 150, 150, 150, 150,
+    150, 150, 150, 150, 150, 150, 147, 145,
+    142, 140, 137, 135, 132, 130, 127, 125,
+    122, 120, 117, 115, 112, 110, 107, 105,
+    102, 100,  97,  95,  92,  90,  87,  85,
+     82,  80,  77,  75,  72,  70,  67,  65,
+     62,  60,  57,  55,  52,  50,  47,  45,
+     42,  40,  37,  35,  32,  30,  27,  25
+};
+
+static const uint16_t vp4_ac_scale_factor[64] = {
+    500, 475, 450, 430, 410, 390, 370, 350,
+    330, 315, 300, 285, 270, 260, 250, 240,
+    230, 220, 210, 200, 190, 185, 180, 170,
+    160, 150, 143, 135, 128, 120, 113, 106,
+    100,  94,  90,  85,  80,  75,  70,  66,
+     62,  57,  52,  49,  45,  41,  38,  35,
+     33,  30,  27,  24,  22,  20,  18,  16,
+     14,  12,  10,   9,   7,   6,   4,   1
+};
+
+static const uint8_t vp4_filter_limit_values[64] = {
+    30, 25, 20, 20, 15, 15, 14, 14,
+    13, 13, 12, 12, 11, 11, 10, 10,
+     9,  9,  8,  8,  7,  7,  7,  7,
+     6,  6,  6,  6,  5,  5,  5,  5,
+     4,  4,  4,  4,  3,  3,  3,  3,
+     2,  2,  2,  2,  2,  2,  2,  2,
+     2,  2,  2,  2,  2,  2,  2,  2,
+     1,  1,  1,  1,  1,  1,  1,  1
+};
+
+static const uint8_t vp4_block_pattern_table_selector[14] = {
+    0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1
+};
+
+static const uint8_t vp4_block_pattern_vlc[2][14][2] = {
+    {
+        { 0x0, 3 }, { 0xf, 4 }, { 0x9, 4 }, { 0x2, 3 },
+        { 0xd, 4 }, { 0xe, 5 }, { 0xb, 4 }, { 0x1, 3 },
+        { 0xf, 5 }, { 0x8, 4 }, { 0x6, 4 }, { 0xe, 4 },
+        { 0xc, 4 }, { 0xa, 4 }
+    },
+    {
+        { 0x7, 4 }, { 0xa, 4 }, { 0x9, 4 }, { 0xc, 4 },
+        { 0x8, 4 }, { 0xd, 5 }, { 0x0, 3 }, { 0xe, 4 },
+        { 0xc, 5 }, { 0xd, 4 }, { 0x1, 3 }, { 0xb, 4 },
+        { 0xf, 4 }, { 0x2, 3 }
+    }
+};
+
+static const uint8_t vp4_mv_table_selector[32] = {
+    0, 1, 2, 2, 3, 3, 3, 3,
+    4, 4, 4, 4, 4, 4, 4, 4,
+    5, 5, 5, 5, 5, 5, 5, 5,
+    6, 6, 6, 6, 6, 6, 6, 6,
+};
+
+static const uint16_t vp4_mv_vlc[2][7][63][2] = {
+    { /* x-axis tables */
+        {
+            {   0x6A,  7 }, {  0x11A,  9 }, {  0x18E,  9 }, {  0x237, 10 },
+            {   0x4A,  8 }, {  0x236, 10 }, {   0x7A,  8 }, {   0xD6,  9 },
+            {   0x7E,  8 }, {  0x1FD, 10 }, {   0x8C,  8 }, {   0xD7,  9 },
+            {   0x87,  8 }, {  0x183,  9 }, {   0x3C,  7 }, {   0x61,  7 },
+            {   0x47,  7 }, {   0x69,  8 }, {   0x40,  7 }, {   0x48,  8 },
+            {   0x49,  7 }, {   0x86,  8 }, {   0x13,  6 }, {   0xD2,  8 },
+            {   0x1C,  6 }, {   0x42,  7 }, {   0x25,  6 }, {   0x1B,  6 },
+            {   0x13,  5 }, {    0x5,  4 }, {    0x0,  2 }, {    0x7,  3 },
+            {    0x5,  3 }, {   0x1B,  5 }, {   0x19,  5 }, {   0x19,  6 },
+            {    0x8,  5 }, {   0x45,  7 }, {   0x1D,  6 }, {   0xC6,  8 },
+            {   0x68,  7 }, {   0x90,  8 }, {   0x41,  7 }, {   0x4B,  8 },
+            {   0x31,  7 }, {  0x18F,  9 }, {   0x62,  7 }, {   0x3E,  7 },
+            {   0x44,  7 }, {   0x68,  8 }, {   0x30,  7 }, {  0x182,  9 },
+            {   0xC0,  8 }, {  0x1A7,  9 }, {   0x91,  8 }, {   0x92,  9 },
+            {   0x7B,  8 }, {   0xFF,  9 }, {  0x1A6,  9 }, {  0x1FC, 10 },
+            {   0x6A,  8 }, {   0x93,  9 }, {   0x6B,  7 }
+        },
+        {
+            {   0x39,  7 }, {  0x259, 10 }, {   0x1B,  8 }, {  0x1D1, 10 },
+            {  0x137,  9 }, {  0x1D0, 10 }, {   0x1A,  8 }, {  0x1B5, 10 },
+            {   0x1D,  8 }, {  0x4BC, 11 }, {   0x6C,  8 }, {   0x38,  9 },
+            {   0x71,  8 }, {   0x2D,  9 }, {   0x7D,  8 }, {   0x75,  8 },
+            {   0x19,  7 }, {   0xE9,  9 }, {   0x37,  7 }, {   0x15,  8 },
+            {   0x1E,  7 }, {   0xDB,  9 }, {   0x4C,  7 }, {   0x70,  8 },
+            {    0xD,  6 }, {    0xC,  7 }, {   0x27,  6 }, {    0x4,  6 },
+            {    0x2,  4 }, {    0x0,  4 }, {    0x5,  3 }, {    0x7,  3 },
+            {    0x6,  3 }, {    0x2,  3 }, {    0x8,  4 }, {   0x24,  6 },
+            {    0xC,  5 }, {   0x3B,  7 }, {   0x1E,  6 }, {   0x9A,  8 },
+            {    0xE,  6 }, {   0x69,  8 }, {   0x4A,  7 }, {  0x12D,  9 },
+            {   0x35,  7 }, {   0xF9,  9 }, {   0x18,  7 }, {   0x7F,  8 },
+            {    0xF,  7 }, {   0xF8,  9 }, {   0x7E,  8 }, {  0x25F, 10 },
+            {   0x68,  8 }, {   0x2C,  9 }, {   0x14,  8 }, {  0x258, 10 },
+            {  0x136,  9 }, {  0x4BD, 11 }, {  0x12E,  9 }, {  0x1B4, 10 },
+            {   0x17,  8 }, {   0x39,  9 }, {   0x1F,  7 }
+        },
+        {
+            {   0x29,  7 }, {  0x3CB, 10 }, {  0x1F5,  9 }, {  0x263, 10 },
+            {  0x1F4,  9 }, {  0x3DA, 10 }, {   0x50,  8 }, {  0x260, 10 },
+            {  0x1EC,  9 }, {  0x3D3, 10 }, {  0x109,  9 }, {  0x3D2, 10 },
+            {   0x51,  8 }, {  0x792, 11 }, {   0xF3,  8 }, {   0x9A,  8 },
+            {   0xF7,  8 }, {  0x132,  9 }, {   0xC1,  8 }, {  0x1E8,  9 },
+            {   0x2A,  7 }, {   0x85,  8 }, {   0x61,  7 }, {  0x1F7,  9 },
+            {   0x78,  7 }, {   0xC7,  8 }, {   0x23,  6 }, {   0x7C,  7 },
+            {   0x12,  5 }, {    0xB,  5 }, {    0xE,  4 }, {    0xD,  4 },
+            {    0x0,  2 }, {    0x5,  3 }, {    0x3,  3 }, {    0x4,  4 },
+            {   0x19,  5 }, {   0x20,  6 }, {   0x3F,  6 }, {   0x43,  7 },
+            {   0x62,  7 }, {   0x9F,  8 }, {   0x4E,  7 }, {  0x181,  9 },
+            {   0x2B,  7 }, {  0x137,  9 }, {   0xF5,  8 }, {   0x89,  8 },
+            {   0xC6,  8 }, {  0x262, 10 }, {   0x88,  8 }, {  0x3C8, 10 },
+            {  0x1F6,  9 }, {  0x3CA, 10 }, {   0x9E,  8 }, {  0x261, 10 },
+            {  0x136,  9 }, {  0x108,  9 }, {  0x133,  9 }, {  0x793, 11 },
+            {  0x180,  9 }, {  0x3DB, 10 }, {   0x45,  7 }
+        },
+        {
+            {    0x1,  6 }, {  0x1C7,  9 }, {   0x67,  8 }, {   0xB5,  9 },
+            {   0x66,  8 }, {  0x139,  9 }, {   0x99,  8 }, {   0xB4,  9 },
+            {   0xC3,  8 }, {  0x130,  9 }, {    0x0,  7 }, {  0x131,  9 },
+            {   0x9E,  8 }, {   0xB7,  9 }, {   0x2C,  7 }, {    0x1,  7 },
+            {   0x28,  7 }, {  0x138,  9 }, {   0x4B,  7 }, {   0x31,  8 },
+            {   0x60,  7 }, {   0x91,  8 }, {    0x3,  6 }, {   0x9D,  8 },
+            {   0x17,  6 }, {   0x4D,  7 }, {   0x31,  6 }, {   0x70,  7 },
+            {    0x7,  5 }, {   0x3A,  6 }, {    0x7,  4 }, {    0x2,  4 },
+            {    0xB,  4 }, {    0x1,  4 }, {    0xF,  4 }, {    0x8,  4 },
+            {    0xD,  4 }, {    0x4,  4 }, {    0xA,  4 }, {    0xD,  5 },
+            {   0x19,  5 }, {    0x2,  6 }, {   0x3B,  6 }, {   0x4A,  7 },
+            {   0x15,  6 }, {   0xC2,  8 }, {   0x18,  6 }, {   0x32,  7 },
+            {   0x72,  7 }, {  0x1C6,  9 }, {   0x29,  7 }, {  0x1C5,  9 },
+            {   0x49,  7 }, {  0x121,  9 }, {   0x1B,  7 }, {   0x30,  8 },
+            {   0x1A,  7 }, {  0x1C4,  9 }, {   0x9F,  8 }, {   0xB6,  9 },
+            {   0x19,  7 }, {  0x120,  9 }, {   0x73,  7 }
+        },
+        {
+            {   0x23,  6 }, {  0x1C8,  9 }, {   0x43,  8 }, {  0x110,  9 },
+            {    0xC,  7 }, {  0x153,  9 }, {   0x22,  7 }, {  0x111,  9 },
+            {    0xF,  7 }, {   0x42,  8 }, {   0x23,  7 }, {  0x1C9,  9 },
+            {   0x2A,  7 }, {   0x1B,  8 }, {   0x73,  7 }, {   0x45,  7 },
+            {   0x6E,  7 }, {   0x89,  8 }, {   0x6C,  7 }, {   0x1A,  8 },
+            {   0x6F,  7 }, {   0xB6,  8 }, {    0xB,  6 }, {   0xE5,  8 },
+            {   0x25,  6 }, {   0x20,  7 }, {   0x29,  6 }, {   0x4D,  7 },
+            {    0x2,  5 }, {   0x14,  6 }, {   0x1A,  5 }, {   0x17,  5 },
+            {   0x1E,  5 }, {   0x27,  6 }, {   0x18,  5 }, {   0x28,  6 },
+            {   0x1F,  5 }, {    0x0,  5 }, {    0x6,  4 }, {   0x10,  5 },
+            {    0x7,  4 }, {    0xB,  5 }, {    0x3,  4 }, {    0x4,  5 },
+            {   0x1D,  5 }, {   0x2C,  6 }, {   0x19,  5 }, {   0x2B,  6 },
+            {    0x9,  5 }, {   0x55,  7 }, {   0x38,  6 }, {    0xE,  7 },
+            {   0x24,  6 }, {   0xA8,  8 }, {    0xA,  6 }, {   0x99,  8 },
+            {   0x5A,  7 }, {   0x98,  8 }, {   0x6D,  7 }, {  0x152,  9 },
+            {   0x2B,  7 }, {   0xB7,  8 }, {    0x1,  5 }
+        },
+        {
+            {   0x3D,  6 }, {   0xB1,  8 }, {   0xDD,  8 }, {  0x1F6,  9 },
+            {   0xC5,  8 }, {  0x188,  9 }, {   0x37,  7 }, {   0x3F,  8 },
+            {   0x1E,  7 }, {  0x189,  9 }, {    0xF,  7 }, {   0x3E,  8 },
+            {   0x6A,  7 }, {  0x1F7,  9 }, {   0x61,  7 }, {   0x79,  7 },
+            {   0x18,  6 }, {   0xB0,  8 }, {    0xE,  6 }, {   0xB3,  8 },
+            {    0xC,  6 }, {   0xDF,  8 }, {    0x6,  6 }, {   0xDC,  8 },
+            {   0x19,  6 }, {   0xDE,  8 }, {   0x27,  6 }, {    0xE,  7 },
+            {   0x1A,  6 }, {   0x63,  7 }, {    0xF,  5 }, {    0xE,  5 },
+            {   0x14,  5 }, {   0x7C,  7 }, {   0x36,  6 }, {   0x6B,  7 },
+            {   0x3F,  6 }, {   0x60,  7 }, {    0x8,  5 }, {   0x74,  7 },
+            {    0x9,  5 }, {   0x78,  7 }, {   0x12,  5 }, {    0xD,  6 },
+            {   0x15,  5 }, {   0x2D,  6 }, {    0x2,  4 }, {   0x1C,  5 },
+            {    0x5,  4 }, {   0x3B,  6 }, {    0x0,  4 }, {   0x34,  6 },
+            {   0x19,  5 }, {   0x26,  6 }, {   0x10,  5 }, {   0x75,  7 },
+            {    0x2,  5 }, {   0x36,  7 }, {   0x23,  6 }, {   0xB2,  8 },
+            {   0x22,  6 }, {   0xFA,  8 }, {   0x17,  5 }
+        },
+        {
+            {   0x15,  5 }, {   0xDD,  8 }, {   0x3E,  7 }, {  0x16E,  9 },
+            {   0x4C,  7 }, {   0x12,  8 }, {   0x5D,  7 }, {   0xB6,  8 },
+            {   0x6F,  7 }, {  0x1F1,  9 }, {   0x69,  7 }, {  0x1F0,  9 },
+            {   0x1D,  7 }, {  0x16F,  9 }, {    0x2,  6 }, {   0x6B,  7 },
+            {    0xC,  6 }, {   0xDC,  8 }, {   0x68,  7 }, {   0x9B,  8 },
+            {   0x7D,  7 }, {   0x9A,  8 }, {    0xD,  6 }, {   0x13,  8 },
+            {    0x8,  6 }, {   0xF9,  8 }, {   0x2C,  6 }, {   0x12,  7 },
+            {   0x33,  6 }, {   0x4F,  7 }, {    0xD,  5 }, {    0x5,  5 },
+            {   0x12,  5 }, {   0x3F,  7 }, {   0x32,  6 }, {   0x13,  7 },
+            {   0x3B,  6 }, {    0x5,  6 }, {   0x2F,  6 }, {   0x5A,  7 },
+            {   0x3F,  6 }, {   0x1C,  7 }, {   0x3A,  6 }, {    0x8,  7 },
+            {   0x36,  6 }, {   0x5C,  7 }, {   0x10,  5 }, {    0x0,  5 },
+            {    0xC,  5 }, {   0x4E,  7 }, {    0x3,  5 }, {   0x6A,  7 },
+            {    0xE,  5 }, {    0x3,  6 }, {   0x14,  5 }, {   0x1E,  6 },
+            {   0x1C,  5 }, {    0xF,  6 }, {   0x18,  5 }, {   0x23,  6 },
+            {   0x1E,  5 }, {   0x22,  6 }, {    0x2,  3 }
+        }
+    },
+    { /* y-axis tables */
+        {
+            {   0x52,  7 }, {  0x14C,  9 }, {  0x1FA,  9 }, {  0x124,  9 },
+            {   0x82,  8 }, {  0x29E, 10 }, {   0x8E,  8 }, {  0x24B, 10 },
+            {   0x9C,  8 }, {  0x3F7, 10 }, {   0x86,  8 }, {  0x114,  9 },
+            {   0x83,  8 }, {  0x3A5, 10 }, {   0xFA,  8 }, {   0x4F,  7 },
+            {   0xFB,  8 }, {  0x13B,  9 }, {   0xFC,  8 }, {  0x172,  9 },
+            {   0x44,  7 }, {  0x173,  9 }, {   0x51,  7 }, {   0x87,  8 },
+            {   0x5F,  7 }, {   0xBA,  8 }, {   0x26,  6 }, {   0x5E,  7 },
+            {   0x16,  5 }, {   0x15,  5 }, {    0x6,  3 }, {    0x1,  2 },
+            {    0x0,  2 }, {   0x1C,  5 }, {   0x1E,  5 }, {   0x75,  7 },
+            {   0x3B,  6 }, {   0xFF,  8 }, {   0x25,  6 }, {   0xBB,  8 },
+            {   0x7C,  7 }, {   0x8B,  8 }, {   0x48,  7 }, {  0x171,  9 },
+            {   0x42,  7 }, {  0x14E,  9 }, {   0x46,  7 }, {   0xFE,  8 },
+            {   0x40,  7 }, {  0x13A,  9 }, {   0x93,  8 }, {  0x115,  9 },
+            {   0x8F,  8 }, {  0x3F6, 10 }, {  0x170,  9 }, {  0x29F, 10 },
+            {  0x1D1,  9 }, {  0x24A, 10 }, {  0x1D3,  9 }, {  0x3A4, 10 },
+            {  0x1D0,  9 }, {  0x14D,  9 }, {   0x50,  7 }
+        },
+        {
+            {   0xDE,  8 }, {  0x223, 10 }, {  0x136,  9 }, {  0x7C5, 11 },
+            {  0x12F,  9 }, {  0x4A1, 11 }, {  0x3D7, 10 }, {  0x7AC, 11 },
+            {  0x133,  9 }, {  0x7C4, 11 }, {  0x1B8,  9 }, {  0x222, 10 },
+            {   0x96,  8 }, {  0x251, 10 }, {   0x95,  8 }, {  0x1F0,  9 },
+            {   0xDA,  8 }, {  0x110,  9 }, {   0x9A,  8 }, {  0x360, 10 },
+            {   0xDD,  8 }, {  0x12E,  9 }, {   0x48,  7 }, {   0x92,  8 },
+            {   0x78,  7 }, {   0x98,  8 }, {   0x27,  6 }, {   0x45,  7 },
+            {   0x1A,  5 }, {   0x10,  5 }, {    0x5,  3 }, {    0x0,  2 },
+            {    0x1,  2 }, {    0xE,  4 }, {    0xC,  4 }, {   0x23,  6 },
+            {   0x3F,  6 }, {   0xF4,  8 }, {   0x7D,  7 }, {   0x89,  8 },
+            {   0x7B,  7 }, {  0x1BE,  9 }, {   0xF9,  8 }, {  0x3E3, 10 },
+            {   0xF3,  8 }, {  0x127,  9 }, {   0xDB,  8 }, {  0x1EA,  9 },
+            {   0xD9,  8 }, {  0x6E7, 11 }, {  0x1BF,  9 }, {  0x4A0, 11 },
+            {  0x1B1,  9 }, {  0x6E6, 11 }, {  0x137,  9 }, {  0x7AD, 11 },
+            {  0x126,  9 }, {  0x6C2, 11 }, {  0x132,  9 }, {  0x6C3, 11 },
+            {  0x129,  9 }, {  0x372, 10 }, {   0xF2,  8 }
+        },
+        {
+            {   0x16,  7 }, {   0x9C,  9 }, {  0x13C,  9 }, {   0x9E, 10 },
+            {  0x12B,  9 }, {   0xBA, 10 }, {  0x181,  9 }, {  0x317, 10 },
+            {   0x84,  8 }, {   0x4E,  9 }, {   0x26,  8 }, {  0x316, 10 },
+            {  0x180,  9 }, {   0x5C,  9 }, {   0xC1,  8 }, {   0x2F,  8 },
+            {   0x10,  7 }, {   0x45,  9 }, {   0x12,  7 }, {  0x189,  9 },
+            {   0x24,  7 }, {  0x13D,  9 }, {   0x66,  7 }, {   0x23,  8 },
+            {   0x67,  7 }, {   0xC6,  8 }, {   0x24,  6 }, {   0x4B,  7 },
+            {   0x11,  5 }, {   0x32,  6 }, {    0xD,  4 }, {    0x0,  3 },
+            {    0x7,  3 }, {    0x5,  3 }, {    0x3,  3 }, {    0x3,  4 },
+            {    0x5,  4 }, {   0x20,  6 }, {    0x8,  5 }, {   0x25,  7 },
+            {   0x26,  6 }, {   0x4F,  8 }, {   0x61,  7 }, {   0x2B,  8 },
+            {   0x4E,  7 }, {  0x18A,  9 }, {   0x43,  7 }, {   0x9F,  8 },
+            {   0x14,  7 }, {  0x254, 10 }, {   0x94,  8 }, {  0x310, 10 },
+            {   0x85,  8 }, {  0x311, 10 }, {   0x2A,  8 }, {   0xBB, 10 },
+            {  0x18F,  9 }, {  0x255, 10 }, {   0x9D,  9 }, {   0x9F, 10 },
+            {  0x18E,  9 }, {   0x44,  9 }, {   0x26,  7 }
+        },
+        {
+            {   0x61,  7 }, {  0x12A,  9 }, {    0xD,  8 }, {  0x3BD, 10 },
+            {   0x89,  8 }, {  0x109,  9 }, {  0x18E,  9 }, {  0x210, 10 },
+            {  0x1D3,  9 }, {  0x211, 10 }, {   0x88,  8 }, {   0x19,  9 },
+            {   0x85,  8 }, {   0x18,  9 }, {   0xE8,  8 }, {   0xCE,  8 },
+            {   0x40,  7 }, {  0x119,  9 }, {   0x45,  7 }, {  0x1D2,  9 },
+            {   0x4B,  7 }, {  0x1DD,  9 }, {   0x62,  7 }, {   0x94,  8 },
+            {   0x75,  7 }, {    0xC,  7 }, {   0x27,  6 }, {    0xD,  7 },
+            {    0x2,  5 }, {   0x26,  6 }, {    0x6,  4 }, {   0x1E,  5 },
+            {    0xD,  4 }, {   0x1F,  5 }, {    0x1,  3 }, {    0xA,  4 },
+            {    0x2,  3 }, {    0x7,  4 }, {    0xB,  4 }, {    0x0,  5 },
+            {   0x1C,  5 }, {   0x76,  7 }, {   0x32,  6 }, {    0x7,  7 },
+            {   0x24,  6 }, {   0xC0,  8 }, {    0x7,  6 }, {   0x41,  7 },
+            {    0x2,  6 }, {  0x18F,  9 }, {   0x47,  7 }, {  0x1DC,  9 },
+            {   0x43,  7 }, {  0x12B,  9 }, {   0xCF,  8 }, {  0x118,  9 },
+            {   0xC6,  8 }, {  0x3BC, 10 }, {   0x8D,  8 }, {  0x3BF, 10 },
+            {   0xC1,  8 }, {  0x3BE, 10 }, {   0x66,  7 }
+        },
+        {
+            {    0x7,  6 }, {  0x14D,  9 }, {   0xA0,  8 }, {   0x9E,  9 },
+            {   0xCF,  8 }, {  0x39C, 10 }, {   0xA1,  8 }, {  0x39D, 10 },
+            {   0xAB,  8 }, {  0x1C5,  9 }, {   0x26,  7 }, {  0x14C,  9 },
+            {   0x25,  7 }, {  0x19C,  9 }, {   0x3F,  7 }, {   0xE1,  8 },
+            {   0x66,  7 }, {  0x1CF,  9 }, {   0x3E,  7 }, {  0x1C4,  9 },
+            {   0x72,  7 }, {   0x4E,  8 }, {    0x6,  6 }, {   0xAA,  8 },
+            {   0x1C,  6 }, {   0xE6,  8 }, {   0x32,  6 }, {   0x51,  7 },
+            {   0x3B,  6 }, {    0x5,  6 }, {   0x1F,  5 }, {   0x18,  5 },
+            {    0x2,  4 }, {   0x3A,  6 }, {    0x0,  4 }, {   0x36,  6 },
+            {    0x5,  4 }, {    0x8,  5 }, {    0x8,  4 }, {   0x16,  5 },
+            {    0x9,  4 }, {    0xD,  5 }, {    0x3,  4 }, {   0x2F,  6 },
+            {   0x1E,  5 }, {   0x2E,  6 }, {   0x1A,  5 }, {   0x2B,  6 },
+            {    0xC,  5 }, {   0x24,  7 }, {   0x1E,  6 }, {   0xE0,  8 },
+            {    0x4,  6 }, {   0xA7,  8 }, {   0x54,  7 }, {  0x1C7,  9 },
+            {   0x52,  7 }, {  0x19D,  9 }, {   0x3A,  7 }, {   0x9F,  9 },
+            {   0x3B,  7 }, {  0x1C6,  9 }, {   0x37,  6 }
+        },
+        {
+            {   0x2A,  6 }, {   0x39,  8 }, {   0x25,  7 }, {  0x115,  9 },
+            {   0x24,  7 }, {  0x1FA,  9 }, {   0x2F,  7 }, {  0x114,  9 },
+            {   0x75,  7 }, {   0x38,  8 }, {   0xFC,  8 }, {   0x36,  8 },
+            {   0x1E,  7 }, {  0x1FB,  9 }, {   0x7F,  7 }, {   0x68,  7 },
+            {   0x16,  6 }, {   0x37,  8 }, {   0x1F,  7 }, {   0x5C,  8 },
+            {   0x13,  6 }, {   0x8B,  8 }, {    0x1,  6 }, {   0xFB,  8 },
+            {   0x21,  6 }, {   0x44,  7 }, {   0x2B,  6 }, {   0x6B,  7 },
+            {   0x3B,  6 }, {    0xC,  6 }, {   0x1C,  5 }, {   0x19,  5 },
+            {    0x1,  4 }, {   0x20,  6 }, {   0x16,  5 }, {   0x7C,  7 },
+            {    0xC,  5 }, {   0x74,  7 }, {    0xA,  5 }, {   0x1C,  6 },
+            {   0x12,  5 }, {   0x69,  7 }, {    0xF,  5 }, {   0x6A,  7 },
+            {   0x14,  5 }, {   0x11,  6 }, {   0x1E,  5 }, {   0x17,  5 },
+            {    0x2,  4 }, {   0x31,  6 }, {   0x1B,  5 }, {   0x30,  6 },
+            {    0xD,  5 }, {    0x0,  6 }, {    0x1,  5 }, {   0x1D,  7 },
+            {   0x23,  6 }, {   0x1A,  7 }, {   0x1D,  6 }, {   0x5D,  8 },
+            {   0x10,  6 }, {   0xFA,  8 }, {   0x13,  5 }
+        },
+        {
+            {   0x12,  5 }, {   0x26,  7 }, {   0x41,  7 }, {   0x22,  8 },
+            {   0x1A,  7 }, {   0xA9,  8 }, {   0x4C,  7 }, {  0x1B2,  9 },
+            {   0x5C,  7 }, {   0xA8,  8 }, {   0x58,  7 }, {  0x1B3,  9 },
+            {   0x40,  7 }, {   0x79,  8 }, {    0xC,  6 }, {   0x55,  7 },
+            {   0x1F,  6 }, {   0xD8,  8 }, {   0x76,  7 }, {   0x23,  8 },
+            {   0x5F,  7 }, {   0x78,  8 }, {    0xB,  6 }, {   0x1B,  7 },
+            {   0x2D,  6 }, {   0x10,  7 }, {   0x37,  6 }, {   0x6D,  7 },
+            {   0x32,  6 }, {    0xA,  6 }, {   0x1A,  5 }, {   0x1E,  5 },
+            {   0x1F,  5 }, {   0x2B,  6 }, {    0xD,  5 }, {   0x77,  7 },
+            {   0x31,  6 }, {   0x5D,  7 }, {   0x38,  6 }, {   0x27,  7 },
+            {    0xC,  5 }, {   0xE9,  8 }, {   0x33,  6 }, {   0x5E,  7 },
+            {   0x30,  6 }, {   0x4D,  7 }, {    0xA,  5 }, {   0x21,  6 },
+            {    0x7,  5 }, {   0x3D,  7 }, {   0x39,  6 }, {   0xE8,  8 },
+            {    0xB,  5 }, {   0x59,  7 }, {   0x14,  5 }, {   0x27,  6 },
+            {   0x11,  5 }, {   0x75,  7 }, {    0xE,  5 }, {    0x9,  6 },
+            {    0x8,  5 }, {   0x12,  6 }, {    0x0,  3 }
+        }
+    }
+};
+
+static const uint16_t vp4_dc_bias[16][32][2] = {
+    { /* DC bias table 0 */
+        {    0xC,  5 }, {   0x70,  7 }, {  0x1CA,  9 }, {  0x1CB,  9 },
+        {  0x391, 10 }, { 0x1C9B, 13 }, { 0x3935, 14 }, {   0x71,  7 },
+        { 0x3934, 14 }, {    0xB,  4 }, {    0xF,  4 }, {   0x19,  5 },
+        {    0x2,  4 }, {    0x9,  4 }, {    0x3,  4 }, {   0x1D,  5 },
+        {   0x18,  5 }, {    0x7,  4 }, {    0xD,  4 }, {    0x2,  3 },
+        {    0x0,  3 }, {    0xA,  4 }, {    0x8,  4 }, {   0x1A,  6 },
+        {   0x73,  7 }, {   0x6F,  8 }, {  0xE4C, 12 }, {  0x727, 11 },
+        {  0x392, 10 }, {  0x390, 10 }, {   0x36,  7 }, {   0x6E,  8 }
+    },
+    { /* DC bias table 1 */
+        {   0x11,  5 }, {   0x7A,  7 }, {   0x83,  8 }, {   0x40,  7 },
+        {  0x105,  9 }, {  0x413, 11 }, {  0x410, 11 }, {   0x7B,  7 },
+        {  0x822, 12 }, {    0xE,  4 }, {    0x2,  3 }, {    0x2,  4 },
+        {    0x6,  4 }, {    0xA,  4 }, {    0x7,  4 }, {   0x1F,  5 },
+        {   0x17,  5 }, {    0x9,  4 }, {    0xD,  4 }, {    0x0,  3 },
+        {    0xC,  4 }, {    0x3,  4 }, {   0x3C,  6 }, {   0x2C,  6 },
+        {   0x21,  6 }, {  0x169,  9 }, {  0x412, 11 }, {  0x2D0, 10 },
+        {  0x2D1, 10 }, {  0x823, 12 }, {   0x5B,  7 }, {   0xB5,  8 }
+    },
+    { /* DC bias table 2 */
+        {   0x17,  5 }, {   0x10,  6 }, {   0xB6,  8 }, {   0x22,  7 },
+        {  0x16A,  9 }, {  0x2D0, 10 }, {  0xB48, 12 }, {   0x77,  7 },
+        { 0x1692, 13 }, {    0x0,  3 }, {    0x3,  3 }, {    0x3,  4 },
+        {    0x9,  4 }, {    0xC,  4 }, {    0x5,  4 }, {    0x2,  4 },
+        {   0x1C,  5 }, {    0x8,  4 }, {    0xD,  4 }, {    0xF,  4 },
+        {    0xA,  4 }, {    0x9,  5 }, {   0x23,  7 }, {   0x3A,  6 },
+        {   0x2C,  6 }, {  0x16B,  9 }, {  0x5A5, 11 }, {  0x2D3, 10 },
+        {  0x2D1, 10 }, { 0x1693, 13 }, {   0x76,  7 }, {   0xB7,  8 }
+    },
+    { /* DC bias table 3 */
+        {   0x1E,  5 }, {   0x13,  6 }, {   0xFB,  8 }, {   0x7C,  7 },
+        {   0x46,  8 }, {  0x7D6, 11 }, {  0xFA9, 12 }, {   0x12,  6 },
+        { 0x1F50, 13 }, {    0x1,  3 }, {    0x4,  3 }, {    0x5,  4 },
+        {    0xA,  4 }, {    0xE,  4 }, {    0x7,  4 }, {    0x0,  4 },
+        {   0x17,  5 }, {    0x6,  4 }, {    0xD,  4 }, {    0xC,  4 },
+        {    0x1,  4 }, {   0x2C,  6 }, {   0x8F,  9 }, {   0x3F,  6 },
+        {   0x2D,  6 }, {  0x1F4,  9 }, {  0x7D5, 11 }, {   0x8E,  9 },
+        {  0x7D7, 11 }, { 0x1F51, 13 }, {   0x10,  6 }, {   0x22,  7 }
+    },
+    { /* DC bias table 4 */
+        {    0x1,  4 }, {   0x2B,  6 }, {   0x12,  7 }, {   0x55,  7 },
+        {   0x27,  8 }, {  0x3B0, 10 }, {  0x762, 11 }, {   0x77,  7 },
+        {  0x261, 12 }, {    0x2,  3 }, {    0x6,  3 }, {    0x7,  4 },
+        {    0xB,  4 }, {    0xF,  4 }, {    0x8,  4 }, {    0x0,  4 },
+        {   0x1C,  5 }, {    0x3,  4 }, {    0x9,  4 }, {    0x6,  4 },
+        {   0x14,  5 }, {   0x54,  7 }, {  0x131, 11 }, {    0x5,  5 },
+        {   0x3A,  6 }, {  0x1D9,  9 }, {   0x99, 10 }, {   0x4D,  9 },
+        {  0x763, 11 }, {  0x260, 12 }, {    0x8,  6 }, {   0xED,  8 }
+    },
+    { /* DC bias table 5 */
+        {    0x4,  4 }, {   0x33,  6 }, {   0x60,  7 }, {   0x65,  7 },
+        {   0xC2,  8 }, {  0x30D, 10 }, {  0x619, 11 }, {   0x64,  7 },
+        { 0x1862, 13 }, {    0x4,  3 }, {    0x7,  3 }, {    0xA,  4 },
+        {    0xB,  4 }, {    0xD,  4 }, {    0x6,  4 }, {    0x0,  4 },
+        {    0xF,  5 }, {    0x3,  4 }, {    0x5,  4 }, {    0x2,  4 },
+        {    0x2,  5 }, {   0x77,  8 }, {  0xC30, 12 }, {    0x3,  5 },
+        {   0x31,  6 }, {  0x187,  9 }, {  0x1D9, 10 }, {   0xED,  9 },
+        {  0x1D8, 10 }, { 0x1863, 13 }, {   0x1C,  6 }, {   0x3A,  7 }
+    },
+    { /* DC bias table 6 */
+        {    0x8,  4 }, {    0xA,  5 }, {   0x6A,  7 }, {   0x16,  6 },
+        {   0x1E,  7 }, {  0x34E, 10 }, {  0x69F, 11 }, {   0x68,  7 },
+        {  0xD28, 12 }, {    0x5,  3 }, {    0x7,  3 }, {    0x7,  4 },
+        {    0xC,  4 }, {    0x0,  3 }, {    0x6,  4 }, {   0x1B,  5 },
+        {   0x12,  5 }, {    0x2,  4 }, {    0x4,  4 }, {   0x13,  5 },
+        {    0xE,  6 }, {  0x34B, 10 }, { 0x1A53, 13 }, {    0x6,  5 },
+        {   0x17,  6 }, {  0x1A6,  9 }, {  0x69E, 11 }, {  0x1A4,  9 },
+        {  0x695, 11 }, { 0x1A52, 13 }, {   0x6B,  7 }, {   0x1F,  7 }
+    },
+    { /* DC bias table 7 */
+        {    0xE,  4 }, {    0xF,  5 }, {   0x17,  6 }, {   0x25,  6 },
+        {   0x9F,  8 }, {  0x138,  9 }, {  0x24B, 10 }, {   0x93,  8 },
+        {  0x92A, 12 }, {    0x5,  3 }, {    0x0,  2 }, {    0x8,  4 },
+        {    0xD,  4 }, {    0xF,  4 }, {    0x6,  4 }, {    0x4,  4 },
+        {    0xE,  5 }, {   0x19,  5 }, {   0x18,  5 }, {    0xA,  5 },
+        {   0x9E,  8 }, {  0x494, 11 }, { 0x1256, 13 }, {   0x26,  6 },
+        {   0x16,  6 }, {  0x124,  9 }, {  0x4E5, 11 }, {  0x273, 10 },
+        {  0x4E4, 11 }, { 0x1257, 13 }, {   0x48,  7 }, {   0x9D,  8 }
+    },
+    { /* DC bias table 8 */
+        {    0x4,  4 }, {   0x2C,  6 }, {   0x50,  7 }, {   0x1E,  7 },
+        {   0x71,  9 }, {   0xE1, 10 }, {   0xE0, 10 }, {   0x1D,  7 },
+        {    0x6,  6 }, {    0x7,  3 }, {    0x6,  3 }, {    0x7,  4 },
+        {    0x5,  4 }, {    0x6,  4 }, {   0x15,  5 }, {    0x0,  5 },
+        {   0x29,  6 }, {    0x2,  5 }, {    0x6,  5 }, {    0x1,  5 },
+        {   0x23,  6 }, {   0x1F,  7 }, {   0x39,  8 }, {    0x9,  4 },
+        {    0x2,  4 }, {   0x10,  5 }, {    0x7,  6 }, {   0x2D,  6 },
+        {   0x2F,  6 }, {   0x2E,  6 }, {   0x22,  6 }, {   0x51,  7 }
+    },
+    { /* DC bias table 9 */
+        {    0x8,  4 }, {   0x2F,  6 }, {   0x51,  7 }, {   0x50,  7 },
+        {  0x2ED, 10 }, {  0x5D9, 11 }, {  0x5D8, 11 }, {   0xBA,  8 },
+        {   0x5C,  7 }, {    0x7,  3 }, {    0x6,  3 }, {    0x9,  4 },
+        {    0x6,  4 }, {    0x7,  4 }, {   0x16,  5 }, {    0x5,  5 },
+        {   0x2B,  6 }, {    0x6,  5 }, {    0xA,  5 }, {    0x1,  5 },
+        {    0xF,  6 }, {   0x1D,  7 }, {  0x177,  9 }, {    0x4,  4 },
+        {    0x1,  4 }, {    0x4,  5 }, {    0x1,  6 }, {   0x2A,  6 },
+        {    0xB,  5 }, {   0x29,  6 }, {    0x0,  6 }, {   0x1C,  7 }
+    },
+    { /* DC bias table 10 */
+        {    0xA,  4 }, {   0x3C,  6 }, {   0x74,  7 }, {   0x4E,  7 },
+        {  0x26D, 10 }, {  0x4D9, 11 }, {  0x4D8, 11 }, {   0x9A,  8 },
+        {   0x4C,  7 }, {    0x0,  2 }, {    0x6,  3 }, {    0x8,  4 },
+        {    0x7,  4 }, {    0x6,  4 }, {   0x16,  5 }, {    0x8,  5 },
+        {   0x2E,  6 }, {    0xA,  5 }, {    0xB,  5 }, {   0x3D,  6 },
+        {   0x24,  6 }, {   0xEB,  8 }, {  0x137,  9 }, {   0x1F,  5 },
+        {   0x1C,  5 }, {   0x3B,  6 }, {   0x12,  6 }, {   0x25,  6 },
+        {   0x2F,  6 }, {   0x13,  6 }, {   0x4F,  7 }, {   0xEA,  8 }
+    },
+    { /* DC bias table 11 */
+        {    0xA,  4 }, {    0xA,  5 }, {    0x3,  6 }, {   0x16,  6 },
+        {    0x9,  8 }, {   0x21, 10 }, {   0x20, 10 }, {   0xB3,  8 },
+        {   0x58,  7 }, {    0x7,  3 }, {    0x6,  3 }, {    0x7,  4 },
+        {    0x6,  4 }, {    0x4,  4 }, {   0x13,  5 }, {    0x2,  5 },
+        {   0x25,  6 }, {    0x0,  5 }, {    0x3,  5 }, {   0x2D,  6 },
+        {   0x5D,  7 }, {   0xB2,  8 }, {   0x11,  9 }, {    0x8,  4 },
+        {    0x2,  4 }, {    0x6,  5 }, {   0x17,  6 }, {   0x2F,  6 },
+        {    0x7,  5 }, {   0x24,  6 }, {   0x5C,  7 }, {    0x5,  7 }
+    },
+    { /* DC bias table 12 */
+        {    0xB,  4 }, {   0x13,  5 }, {   0x1F,  6 }, {   0x31,  6 },
+        {   0x21,  7 }, {  0x295, 10 }, {  0x528, 11 }, {   0xA4,  8 },
+        {   0x3C,  7 }, {    0x0,  2 }, {    0x7,  3 }, {    0x6,  4 },
+        {    0x5,  4 }, {   0x1B,  5 }, {   0x12,  5 }, {   0x32,  6 },
+        {   0x1D,  6 }, {   0x2B,  6 }, {   0x30,  6 }, {   0x1C,  6 },
+        {   0x3D,  7 }, {  0x14B,  9 }, {  0x529, 11 }, {    0x8,  4 },
+        {   0x1A,  5 }, {   0x33,  6 }, {   0x11,  6 }, {   0x2A,  6 },
+        {    0x9,  5 }, {   0x28,  6 }, {   0x53,  7 }, {   0x20,  7 }
+    },
+    { /* DC bias table 13 */
+        {    0xE,  4 }, {   0x15,  5 }, {   0x29,  6 }, {   0x3F,  6 },
+        {   0x4D,  7 }, {  0x2F1, 10 }, {  0x5E0, 11 }, {   0x92,  8 },
+        {   0x48,  7 }, {    0x0,  2 }, {    0x6,  3 }, {    0x6,  4 },
+        {    0x5,  4 }, {    0x4,  4 }, {    0xF,  5 }, {   0x2E,  6 },
+        {   0x1D,  6 }, {   0x28,  6 }, {   0x27,  6 }, {   0x5F,  7 },
+        {   0xBD,  8 }, {  0x179,  9 }, {  0x5E1, 11 }, {    0x8,  4 },
+        {   0x1E,  5 }, {   0x2D,  6 }, {   0x1C,  6 }, {   0x2C,  6 },
+        {   0x3E,  6 }, {   0x25,  6 }, {   0x4C,  7 }, {   0x93,  8 }
+    },
+    { /* DC bias table 14 */
+        {    0xC,  4 }, {   0x17,  5 }, {   0x35,  6 }, {   0x13,  5 },
+        {   0x21,  6 }, {   0xAD,  8 }, {  0x6F1, 11 }, {  0x1BD,  9 },
+        {   0xD9,  8 }, {    0x0,  2 }, {    0x7,  3 }, {    0x7,  4 },
+        {    0x6,  4 }, {    0x4,  4 }, {   0x11,  5 }, {   0x2A,  6 },
+        {   0x6E,  7 }, {   0x25,  6 }, {   0x24,  6 }, {   0x57,  7 },
+        {   0xD8,  8 }, {  0x379, 10 }, {  0x6F0, 11 }, {    0x5,  4 },
+        {   0x16,  5 }, {   0x29,  6 }, {   0x6D,  7 }, {   0x28,  6 },
+        {   0x34,  6 }, {   0x20,  6 }, {   0xDF,  8 }, {   0xAC,  8 }
+    },
+    { /* DC bias table 15 */
+        {    0x0,  3 }, {   0x1A,  5 }, {    0x6,  5 }, {   0x19,  5 },
+        {   0x30,  6 }, {   0x5A,  7 }, {  0x18A,  9 }, {  0x2DD, 10 },
+        {  0x18B,  9 }, {    0x1,  2 }, {    0x7,  3 }, {    0xA,  4 },
+        {    0x9,  4 }, {    0x2,  4 }, {   0x10,  5 }, {   0x2E,  6 },
+        {   0x6E,  7 }, {   0x2C,  6 }, {    0xE,  6 }, {   0x5E,  7 },
+        {   0xC4,  8 }, {  0x5B9, 11 }, {  0x5B8, 11 }, {   0x11,  5 },
+        {   0x36,  6 }, {   0x5F,  7 }, {   0x1E,  7 }, {   0x63,  7 },
+        {   0x6F,  7 }, {   0x1F,  7 }, {   0xB6,  8 }, {  0x16F,  9 }
+    }
+};
+
+static const uint16_t vp4_ac_bias_0[16][32][2] = {
+    { /* AC bias group 1, table 0 */
+        {    0x6,  5 }, {   0x1E,  7 }, {  0x1CC,  9 }, {  0x1CE,  9 },
+        {  0x734, 11 }, { 0x1CD5, 13 }, { 0x1CD4, 13 }, {   0x18,  5 },
+        {  0xE6B, 12 }, {    0x0,  3 }, {    0xF,  4 }, {    0x6,  4 },
+        {    0x7,  4 }, {    0xD,  4 }, {    0x8,  4 }, {    0x2,  4 },
+        {   0x19,  5 }, {    0x5,  4 }, {    0xB,  4 }, {    0xA,  4 },
+        {   0x1D,  5 }, {   0x27,  6 }, {  0x1CF,  9 }, {    0x4,  4 },
+        {   0x38,  6 }, {    0xE,  6 }, {   0x4C,  7 }, {   0x1F,  7 },
+        {   0x4D,  7 }, {  0x39B, 10 }, {   0x12,  5 }, {   0x72,  7 }
+    },
+    { /* AC bias group 1, table 1 */
+        {    0x9,  5 }, {   0x4B,  7 }, {   0x90,  8 }, {   0x91,  8 },
+        {  0x745, 11 }, { 0x1D11, 13 }, { 0x1D10, 13 }, {   0x19,  5 },
+        {  0xE89, 12 }, {    0x0,  3 }, {    0xF,  4 }, {    0x8,  4 },
+        {    0x7,  4 }, {    0xD,  4 }, {    0xB,  4 }, {    0x2,  4 },
+        {   0x1C,  5 }, {    0x3,  4 }, {    0xA,  4 }, {    0x5,  4 },
+        {   0x18,  5 }, {   0x10,  6 }, {  0x1D0,  9 }, {    0x6,  4 },
+        {   0x3B,  6 }, {   0x11,  6 }, {   0x4A,  7 }, {   0x49,  7 },
+        {   0xE9,  8 }, {  0x3A3, 10 }, {   0x13,  5 }, {   0x75,  7 }
+    },
+    { /* AC bias group 1, table 2 */
+        {   0x19,  5 }, {   0x74,  7 }, {   0x1D,  8 }, {   0xEA,  8 },
+        {   0x73, 10 }, {  0x1CA, 12 }, {  0x396, 13 }, {   0x1C,  5 },
+        {   0xE4, 11 }, {    0x2,  3 }, {    0x1,  3 }, {    0x7,  4 },
+        {    0x8,  4 }, {    0xD,  4 }, {    0x9,  4 }, {   0x1F,  5 },
+        {   0x18,  5 }, {    0x0,  4 }, {    0x6,  4 }, {   0x1E,  5 },
+        {   0x3B,  6 }, {   0xEB,  8 }, {  0x397, 13 }, {    0xA,  4 },
+        {    0x2,  5 }, {   0x2C,  6 }, {   0x5B,  7 }, {   0x5A,  7 },
+        {    0xF,  7 }, {   0x38,  9 }, {   0x17,  5 }, {    0x6,  6 }
+    },
+    { /* AC bias group 1, table 3 */
+        {   0x1E,  5 }, {   0x6F,  7 }, {   0xAE,  8 }, {   0xAF,  8 },
+        {  0x187, 10 }, {  0x61B, 12 }, {  0xC35, 13 }, {   0x1A,  5 },
+        {  0x30C, 11 }, {    0x2,  3 }, {    0x1,  3 }, {    0x7,  4 },
+        {    0x8,  4 }, {    0xE,  4 }, {    0x9,  4 }, {   0x1F,  5 },
+        {   0x14,  5 }, {    0x0,  4 }, {    0x1,  4 }, {   0x19,  5 },
+        {   0x2A,  6 }, {   0x60,  8 }, {  0xC34, 13 }, {    0xB,  4 },
+        {    0xD,  5 }, {   0x36,  6 }, {   0x6E,  7 }, {   0x56,  7 },
+        {   0x31,  7 }, {   0xC2,  9 }, {   0x18,  5 }, {   0x19,  6 }
+    },
+    { /* AC bias group 1, table 4 */
+        {    0x1,  4 }, {   0x2C,  6 }, {    0x5,  7 }, {   0x15,  7 },
+        {    0x8,  8 }, {   0x97, 12 }, {  0x12D, 13 }, {   0x17,  5 },
+        {   0x4A, 11 }, {    0x3,  3 }, {    0x2,  3 }, {    0x9,  4 },
+        {    0xA,  4 }, {    0xE,  4 }, {    0x8,  4 }, {   0x1F,  5 },
+        {    0x7,  5 }, {   0x1E,  5 }, {   0x1B,  5 }, {    0x4,  5 },
+        {   0x5A,  7 }, {   0x24, 10 }, {  0x12C, 13 }, {    0xC,  4 },
+        {    0x6,  5 }, {    0x0,  5 }, {    0x3,  6 }, {   0x5B,  7 },
+        {   0x14,  7 }, {   0x13,  9 }, {   0x1A,  5 }, {    0xB,  6 }
+    },
+    { /* AC bias group 1, table 5 */
+        {    0x4,  4 }, {    0x0,  5 }, {   0x17,  7 }, {   0x63,  7 },
+        {  0x18B,  9 }, {  0x310, 10 }, {  0xC44, 12 }, {   0x19,  5 },
+        {  0x623, 11 }, {    0x4,  3 }, {    0x3,  3 }, {    0xA,  4 },
+        {    0xB,  4 }, {    0xD,  4 }, {    0x3,  4 }, {   0x1C,  5 },
+        {    0x3,  5 }, {    0xA,  5 }, {    0x4,  5 }, {    0x3,  6 },
+        {  0x18A,  9 }, { 0x188B, 13 }, { 0x188A, 13 }, {    0xF,  4 },
+        {    0xB,  5 }, {    0x2,  5 }, {    0xA,  6 }, {    0x2,  6 },
+        {   0x16,  7 }, {  0x189,  9 }, {   0x1D,  5 }, {   0x30,  6 }
+    },
+    { /* AC bias group 1, table 6 */
+        {    0xD,  4 }, {    0x3,  5 }, {   0x77,  7 }, {    0xD,  6 },
+        {   0x82,  8 }, {  0x20D, 10 }, {  0x830, 12 }, {   0x19,  5 },
+        {  0x419, 11 }, {    0x3,  3 }, {    0x2,  3 }, {    0xA,  4 },
+        {    0x9,  4 }, {    0xB,  4 }, {    0x2,  4 }, {   0x11,  5 },
+        {   0x39,  6 }, {    0x2,  5 }, {   0x21,  6 }, {   0x40,  7 },
+        { 0x1063, 13 }, { 0x20C5, 14 }, { 0x20C4, 14 }, {    0xF,  4 },
+        {   0x18,  5 }, {    0x7,  5 }, {   0x38,  6 }, {    0xC,  6 },
+        {   0x76,  7 }, {  0x107,  9 }, {    0x0,  4 }, {   0x3A,  6 }
+    },
+    { /* AC bias group 1, table 7 */
+        {    0xF,  4 }, {   0x1C,  5 }, {   0x36,  6 }, {    0x8,  5 },
+        {   0x61,  7 }, {   0x91,  8 }, {  0x243, 10 }, {    0x9,  5 },
+        {  0x120,  9 }, {    0x5,  3 }, {    0x3,  3 }, {    0x8,  4 },
+        {    0x5,  4 }, {    0x1,  4 }, {   0x13,  5 }, {   0x31,  6 },
+        {   0x76,  7 }, {   0x60,  7 }, {   0x93,  8 }, {  0x909, 12 },
+        {  0x908, 12 }, {  0x90B, 12 }, {  0x90A, 12 }, {    0x1,  3 },
+        {   0x1A,  5 }, {   0x19,  5 }, {   0x3A,  6 }, {   0x25,  6 },
+        {   0x77,  7 }, {   0x92,  8 }, {    0x0,  4 }, {   0x37,  6 }
+    },
+    { /* AC bias group 1, table 8 */
+        {   0x1F,  5 }, {   0x79,  7 }, {   0xF1,  8 }, {   0xF0,  8 },
+        {  0x11B, 10 }, {  0x469, 12 }, {  0x468, 12 }, {   0x3B,  6 },
+        {   0x22,  7 }, {    0x5,  3 }, {    0x4,  3 }, {    0x7,  4 },
+        {    0x5,  4 }, {    0x6,  4 }, {   0x1C,  5 }, {    0x1,  5 },
+        {   0x35,  6 }, {   0x3D,  6 }, {   0x3A,  6 }, {   0x10,  6 },
+        {   0x47,  8 }, {   0x8C,  9 }, {  0x235, 11 }, {    0x1,  3 },
+        {    0x1,  4 }, {   0x19,  5 }, {    0x0,  5 }, {   0x30,  6 },
+        {    0x9,  5 }, {   0x31,  6 }, {   0x1B,  5 }, {   0x34,  6 }
+    },
+    { /* AC bias group 1, table 9 */
+        {    0x3,  4 }, {   0x1B,  6 }, {   0xF3,  8 }, {   0xFD,  8 },
+        {  0x3C9, 10 }, {  0xF20, 12 }, { 0x1E42, 13 }, {   0x3D,  6 },
+        {   0xFC,  8 }, {    0x6,  3 }, {    0x4,  3 }, {    0x2,  4 },
+        {    0x0,  4 }, {    0x1,  4 }, {   0x17,  5 }, {   0x3E,  6 },
+        {   0x1A,  6 }, {   0x39,  6 }, {   0x2B,  6 }, {   0x78,  7 },
+        {  0x1E5,  9 }, {  0x791, 11 }, { 0x1E43, 13 }, {    0x2,  3 },
+        {    0x7,  4 }, {   0x1D,  5 }, {    0xC,  5 }, {   0x38,  6 },
+        {   0x14,  5 }, {   0x7F,  7 }, {   0x16,  5 }, {   0x2A,  6 }
+    },
+    { /* AC bias group 1, table 10 */
+        {    0x7,  4 }, {   0x39,  6 }, {   0x51,  7 }, {   0x78,  7 },
+        {  0x3CB, 10 }, {  0xF29, 12 }, { 0x1E51, 13 }, {   0x3D,  6 },
+        {   0xF3,  8 }, {    0x6,  3 }, {    0x4,  3 }, {    0x2,  4 },
+        {    0x0,  4 }, {    0x1,  4 }, {   0x17,  5 }, {   0x3E,  6 },
+        {   0x7F,  7 }, {   0x2B,  6 }, {   0x7E,  7 }, {   0x50,  7 },
+        {  0x1E4,  9 }, {  0x795, 11 }, { 0x1E50, 13 }, {    0x2,  3 },
+        {    0x6,  4 }, {   0x1D,  5 }, {    0x6,  5 }, {   0x38,  6 },
+        {    0x7,  5 }, {   0x29,  6 }, {   0x16,  5 }, {   0x2A,  6 }
+    },
+    { /* AC bias group 1, table 11 */
+        {    0x8,  4 }, {   0x3B,  6 }, {   0x1D,  7 }, {   0x72,  7 },
+        {  0x1CC,  9 }, {  0x734, 11 }, { 0x1CD5, 13 }, {   0x3A,  6 },
+        {   0x1C,  7 }, {    0x6,  3 }, {    0x5,  3 }, {    0x2,  4 },
+        {    0x1,  4 }, {    0x0,  4 }, {   0x12,  5 }, {   0x3E,  6 },
+        {   0x7F,  7 }, {   0x1E,  6 }, {   0x7E,  7 }, {   0xE7,  8 },
+        {  0x39B, 10 }, {  0xE6B, 12 }, { 0x1CD4, 13 }, {    0x2,  3 },
+        {    0x6,  4 }, {   0x1E,  5 }, {    0xE,  5 }, {   0x38,  6 },
+        {    0x6,  5 }, {    0xF,  6 }, {   0x13,  5 }, {   0x1F,  6 }
+    },
+    { /* AC bias group 1, table 12 */
+        {    0xD,  4 }, {   0x3F,  6 }, {   0x73,  7 }, {    0xC,  6 },
+        {   0xE4,  8 }, {  0x72B, 11 }, {  0xE54, 12 }, {   0x3A,  6 },
+        {   0x1A,  7 }, {    0x5,  3 }, {    0x4,  3 }, {    0x2,  4 },
+        {    0x1,  4 }, {    0x0,  4 }, {    0x7,  5 }, {   0x38,  6 },
+        {   0x76,  7 }, {   0x77,  7 }, {   0x1B,  7 }, {  0x1CB,  9 },
+        {  0x394, 10 }, { 0x1CAB, 13 }, { 0x1CAA, 13 }, {    0x2,  3 },
+        {    0x6,  4 }, {   0x1E,  5 }, {    0xE,  5 }, {   0x3E,  6 },
+        {   0x19,  5 }, {   0x1F,  6 }, {   0x18,  5 }, {   0x1E,  6 }
+    },
+    { /* AC bias group 1, table 13 */
+        {    0xE,  4 }, {    0x7,  5 }, {    0xC,  6 }, {   0x1C,  6 },
+        {   0xBD,  8 }, {  0x2F3, 10 }, {  0xBC9, 12 }, {   0x1F,  6 },
+        {   0xBF,  8 }, {    0x6,  3 }, {    0x4,  3 }, {    0x2,  4 },
+        {    0x1,  4 }, {   0x1E,  5 }, {    0x1,  5 }, {    0xD,  6 },
+        {   0x3A,  7 }, {   0x3B,  7 }, {   0xBE,  8 }, {  0x178,  9 },
+        {  0x5E5, 11 }, { 0x1791, 13 }, { 0x1790, 13 }, {    0x2,  3 },
+        {    0x6,  4 }, {   0x1F,  5 }, {   0x16,  5 }, {    0x0,  5 },
+        {   0x15,  5 }, {   0x2E,  6 }, {   0x14,  5 }, {   0x1E,  6 }
+    },
+    { /* AC bias group 1, table 14 */
+        {    0x0,  3 }, {   0x1B,  5 }, {   0x31,  6 }, {   0x3A,  6 },
+        {   0x60,  7 }, {   0x6F,  9 }, {  0x1B9, 11 }, {    0xE,  6 },
+        {   0x1A,  7 }, {    0x5,  3 }, {    0x3,  3 }, {    0x2,  4 },
+        {   0x1F,  5 }, {   0x1A,  5 }, {   0x39,  6 }, {    0xC,  6 },
+        {   0xC3,  8 }, {   0xC2,  8 }, {   0x36,  8 }, {   0xDD, 10 },
+        {  0x370, 12 }, {  0x6E3, 13 }, {  0x6E2, 13 }, {    0x2,  3 },
+        {    0x8,  4 }, {   0x1E,  5 }, {   0x19,  5 }, {   0x3B,  6 },
+        {   0x12,  5 }, {    0xF,  6 }, {   0x13,  5 }, {   0x38,  6 }
+    },
+    { /* AC bias group 1, table 15 */
+        {    0x2,  3 }, {    0x0,  4 }, {    0x3,  5 }, {   0x1C,  5 },
+        {   0x32,  6 }, {   0x1C,  7 }, {  0x199,  9 }, {    0x4,  6 },
+        {   0xCD,  8 }, {    0x4,  3 }, {    0x3,  3 }, {   0x1B,  5 },
+        {   0x1A,  5 }, {   0x3D,  6 }, {   0x67,  7 }, {   0x3B,  8 },
+        {  0x198,  9 }, {   0x75,  9 }, {   0xE9, 10 }, {  0x3A1, 12 },
+        {  0x3A0, 12 }, {  0x3A3, 12 }, {  0x3A2, 12 }, {    0x5,  3 },
+        {    0x2,  4 }, {   0x1F,  5 }, {   0x1D,  5 }, {   0x3C,  6 },
+        {   0x18,  5 }, {    0xF,  6 }, {    0x6,  5 }, {    0x5,  6 }
+    }
+};
+
+static const uint16_t vp4_ac_bias_1[16][32][2] = {
+    { /* AC bias group 2, table 0 */
+        {    0x4,  5 }, {   0xF5,  8 }, {  0x182,  9 }, {  0x60F, 11 },
+        { 0x1839, 13 }, { 0x1838, 13 }, { 0x183B, 13 }, {   0x13,  5 },
+        {   0xC0,  8 }, {    0x3,  3 }, {    0x2,  3 }, {    0xB,  4 },
+        {    0xA,  4 }, {    0xE,  4 }, {    0x8,  4 }, {    0x1,  4 },
+        {   0x12,  5 }, {   0x1F,  5 }, {    0x0,  4 }, {    0x6,  5 },
+        {   0x7B,  7 }, {  0x306, 10 }, { 0x183A, 13 }, {    0xD,  4 },
+        {    0x7,  5 }, {   0x31,  6 }, {    0xA,  6 }, {   0x61,  7 },
+        {   0x3C,  6 }, {   0xF4,  8 }, {   0x19,  5 }, {    0xB,  6 }
+    },
+    { /* AC bias group 2, table 1 */
+        {    0xA,  5 }, {   0x1A,  7 }, {  0x1D8,  9 }, {  0x3B3, 10 },
+        {  0xECA, 12 }, { 0x1D96, 13 }, { 0x3B2F, 14 }, {   0x14,  5 },
+        {   0x36,  8 }, {    0x4,  3 }, {    0x3,  3 }, {    0xC,  4 },
+        {    0xB,  4 }, {    0x0,  3 }, {    0x4,  4 }, {   0x1C,  5 },
+        {    0x5,  5 }, {   0x15,  5 }, {    0x7,  5 }, {   0x17,  6 },
+        {   0x37,  8 }, {  0x764, 11 }, { 0x3B2E, 14 }, {    0xF,  4 },
+        {   0x1A,  5 }, {   0x3A,  6 }, {    0xC,  6 }, {   0x77,  7 },
+        {    0x4,  5 }, {   0xED,  8 }, {   0x1B,  5 }, {   0x16,  6 }
+    },
+    { /* AC bias group 2, table 2 */
+        {   0x1A,  5 }, {   0x2D,  7 }, {   0x58,  8 }, {  0x1F4,  9 },
+        {  0x7D4, 11 }, { 0x1F55, 13 }, { 0x1F54, 13 }, {   0x14,  5 },
+        {   0x59,  8 }, {    0x4,  3 }, {    0x3,  3 }, {    0xB,  4 },
+        {    0xC,  4 }, {    0xE,  4 }, {    0x4,  4 }, {   0x15,  5 },
+        {    0x5,  5 }, {    0x7,  5 }, {    0x4,  5 }, {   0x7C,  7 },
+        {  0x3EB, 10 }, { 0x1F57, 13 }, { 0x1F56, 13 }, {    0x0,  3 },
+        {   0x1B,  5 }, {   0x3F,  6 }, {    0xD,  6 }, {    0xC,  6 },
+        {    0xA,  5 }, {   0xFB,  8 }, {   0x1E,  5 }, {   0x17,  6 }
+    },
+    { /* AC bias group 2, table 3 */
+        {    0x0,  4 }, {   0x75,  7 }, {   0x4A,  8 }, {   0x97,  9 },
+        {  0x25B, 11 }, {  0x969, 13 }, {  0x968, 13 }, {    0xB,  5 },
+        {   0xE8,  8 }, {    0x5,  3 }, {    0x4,  3 }, {    0x7,  4 },
+        {    0xC,  4 }, {    0xD,  4 }, {    0x1,  4 }, {    0xA,  5 },
+        {   0x39,  6 }, {   0x3B,  6 }, {   0x18,  6 }, {   0xE9,  8 },
+        {  0x12C, 10 }, {  0x96B, 13 }, {  0x96A, 13 }, {    0x1,  3 },
+        {   0x1F,  5 }, {    0x8,  5 }, {   0x19,  6 }, {   0x13,  6 },
+        {    0xD,  5 }, {   0x24,  7 }, {   0x1E,  5 }, {   0x38,  6 }
+    },
+    { /* AC bias group 2, table 4 */
+        {    0x4,  4 }, {   0x14,  6 }, {   0x6E,  8 }, {   0x57,  8 },
+        {  0x159, 10 }, {  0x562, 12 }, {  0xAC7, 13 }, {    0xB,  5 },
+        {   0x6F,  8 }, {    0x6,  3 }, {    0x5,  3 }, {    0x8,  4 },
+        {    0x9,  4 }, {    0x7,  4 }, {   0x1E,  5 }, {    0x2,  5 },
+        {    0x7,  6 }, {    0x6,  6 }, {   0x2A,  7 }, {   0xAD,  9 },
+        {  0xAC6, 13 }, {  0x561, 12 }, {  0x560, 12 }, {    0x1,  3 },
+        {   0x1F,  5 }, {    0xC,  5 }, {   0x39,  6 }, {   0x1A,  6 },
+        {    0x0,  4 }, {   0x36,  7 }, {   0x1D,  5 }, {   0x38,  6 }
+    },
+    { /* AC bias group 2, table 5 */
+        {    0x7,  4 }, {   0x1B,  6 }, {    0xE,  7 }, {    0xD,  7 },
+        {  0x3E1, 10 }, { 0x1F06, 13 }, { 0x3E0F, 14 }, {    0x2,  5 },
+        {   0xF9,  8 }, {    0x5,  3 }, {    0x6,  3 }, {    0x8,  4 },
+        {    0x9,  4 }, {    0x4,  4 }, {    0xC,  5 }, {   0x1A,  6 },
+        {    0xF,  7 }, {    0xC,  7 }, {  0x1F1,  9 }, {  0x7C0, 11 },
+        { 0x3E0E, 14 }, { 0x1F05, 13 }, { 0x1F04, 13 }, {    0x1,  3 },
+        {    0x0,  4 }, {   0x1C,  5 }, {   0x3F,  6 }, {   0x3D,  6 },
+        {    0x5,  4 }, {   0x7D,  7 }, {   0x1D,  5 }, {   0x3C,  6 }
+    },
+    { /* AC bias group 2, table 6 */
+        {    0xF,  4 }, {    0xA,  5 }, {   0x71,  7 }, {    0x6,  6 },
+        {  0x1C2,  9 }, {  0x702, 11 }, { 0x1C0E, 13 }, {    0x2,  5 },
+        {    0xE,  7 }, {    0x5,  3 }, {    0x4,  3 }, {    0x6,  4 },
+        {    0x7,  4 }, {   0x1D,  5 }, {   0x17,  6 }, {    0xF,  7 },
+        {  0x1C3,  9 }, {  0x1C1,  9 }, {  0x380, 10 }, { 0x381F, 14 },
+        { 0x381E, 14 }, { 0x1C0D, 13 }, { 0x1C0C, 13 }, {    0x1,  3 },
+        {    0x4,  4 }, {   0x18,  5 }, {    0x1,  5 }, {    0x0,  5 },
+        {    0xD,  4 }, {   0x16,  6 }, {   0x19,  5 }, {   0x39,  6 }
+    },
+    { /* AC bias group 2, table 7 */
+        {    0x2,  3 }, {   0x1E,  5 }, {   0x3B,  6 }, {    0xD,  5 },
+        {   0x61,  7 }, {  0x1FA,  9 }, { 0x1FB5, 13 }, {   0x31,  6 },
+        {   0xFC,  8 }, {    0x4,  3 }, {    0x5,  3 }, {    0x1,  4 },
+        {    0x7,  4 }, {   0x3A,  6 }, {   0x60,  7 }, {  0x3F7, 10 },
+        {  0x7EC, 11 }, { 0x1FB7, 13 }, { 0x3F6C, 14 }, { 0x7EDB, 15 },
+        { 0x7EDA, 15 }, { 0x3F69, 14 }, { 0x3F68, 14 }, {    0x1,  3 },
+        {    0x0,  4 }, {   0x19,  5 }, {   0x3E,  6 }, {   0x39,  6 },
+        {    0xD,  4 }, {   0x38,  6 }, {    0xC,  5 }, {   0x7F,  7 }
+    },
+    { /* AC bias group 2, table 8 */
+        {   0x1E,  5 }, {   0x70,  7 }, {  0x127,  9 }, {  0x126,  9 },
+        {  0x492, 11 }, { 0x124D, 13 }, { 0x124C, 13 }, {    0x1,  5 },
+        {   0x7F,  7 }, {    0x6,  3 }, {    0x5,  3 }, {    0x5,  4 },
+        {    0x4,  4 }, {    0x1,  4 }, {    0x7,  5 }, {   0x25,  6 },
+        {   0x71,  7 }, {   0x7E,  7 }, {   0x48,  7 }, {  0x125,  9 },
+        {  0x248, 10 }, { 0x124F, 13 }, { 0x124E, 13 }, {    0x3,  3 },
+        {    0x8,  4 }, {   0x1D,  5 }, {    0x6,  5 }, {   0x3E,  6 },
+        {    0x2,  4 }, {    0x0,  5 }, {   0x13,  5 }, {   0x39,  6 }
+    },
+    { /* AC bias group 2, table 9 */
+        {    0x1,  4 }, {    0x1,  6 }, {   0xE7,  8 }, {   0x91,  8 },
+        {  0x240, 10 }, { 0x120D, 13 }, { 0x120C, 13 }, {   0x3C,  6 },
+        {    0x0,  6 }, {    0x6,  3 }, {    0x5,  3 }, {    0x5,  4 },
+        {    0x4,  4 }, {   0x1F,  5 }, {    0x4,  5 }, {   0x25,  6 },
+        {   0x72,  7 }, {   0x49,  7 }, {   0xE6,  8 }, {  0x121,  9 },
+        {  0x482, 11 }, { 0x120F, 13 }, { 0x120E, 13 }, {    0x3,  3 },
+        {    0x8,  4 }, {   0x1D,  5 }, {    0x5,  5 }, {   0x3D,  6 },
+        {    0x3,  4 }, {    0x1,  5 }, {   0x13,  5 }, {   0x38,  6 }
+    },
+    { /* AC bias group 2, table 10 */
+        {    0x4,  4 }, {    0xF,  6 }, {   0xF4,  8 }, {   0x5B,  8 },
+        {  0x2D3, 11 }, {  0xB4A, 13 }, { 0x1697, 14 }, {   0x3C,  6 },
+        {    0xE,  6 }, {    0x6,  3 }, {    0x5,  3 }, {    0x2,  4 },
+        {    0x1,  4 }, {   0x1D,  5 }, {    0x0,  5 }, {   0x7B,  7 },
+        {   0x2C,  7 }, {   0xF5,  8 }, {   0xB5,  9 }, {  0x168, 10 },
+        { 0x1696, 14 }, {  0xB49, 13 }, {  0xB48, 13 }, {    0x3,  3 },
+        {    0x9,  4 }, {   0x1F,  5 }, {    0xA,  5 }, {    0x1,  5 },
+        {    0x8,  4 }, {    0x6,  5 }, {   0x1C,  5 }, {   0x17,  6 }
+    },
+    { /* AC bias group 2, table 11 */
+        {    0x8,  4 }, {   0x39,  6 }, {   0x1A,  7 }, {    0x3,  7 },
+        {   0xDB, 10 }, {  0x6D6, 13 }, {  0xDAF, 14 }, {   0x3C,  6 },
+        {    0xC,  6 }, {    0x6,  3 }, {    0x5,  3 }, {    0x2,  4 },
+        {    0x1,  4 }, {   0x1D,  5 }, {   0x3D,  6 }, {    0x0,  6 },
+        {    0x2,  7 }, {   0x37,  8 }, {   0x6C,  9 }, {  0x1B4, 11 },
+        {  0xDAE, 14 }, {  0x6D5, 13 }, {  0x6D4, 13 }, {    0x2,  3 },
+        {    0x7,  4 }, {   0x1F,  5 }, {    0x7,  5 }, {    0x1,  5 },
+        {    0x9,  4 }, {    0xD,  5 }, {    0xC,  5 }, {   0x38,  6 }
+    },
+    { /* AC bias group 2, table 12 */
+        {    0xF,  4 }, {    0x4,  5 }, {   0x2F,  7 }, {   0x2E,  7 },
+        {   0x54,  9 }, {  0x555, 13 }, {  0x554, 13 }, {   0x16,  6 },
+        {    0xE,  6 }, {    0x6,  3 }, {    0x5,  3 }, {    0x1,  4 },
+        {    0x0,  4 }, {    0x9,  5 }, {    0xB,  6 }, {   0x14,  7 },
+        {   0x57,  9 }, {   0x56,  9 }, {   0xAB, 10 }, {  0x557, 13 },
+        {  0x556, 13 }, {  0x2A9, 12 }, {  0x2A8, 12 }, {    0x3,  3 },
+        {    0x8,  4 }, {   0x13,  5 }, {    0xA,  5 }, {    0x8,  5 },
+        {    0xE,  4 }, {   0x12,  5 }, {    0x6,  5 }, {    0xF,  6 }
+    },
+    { /* AC bias group 2, table 13 */
+        {    0x1,  3 }, {    0xE,  5 }, {    0x6,  6 }, {    0x4,  6 },
+        {   0xDA,  9 }, {  0xDBE, 13 }, { 0x1B7E, 14 }, {    0x7,  6 },
+        {   0x1A,  6 }, {    0x5,  3 }, {    0x4,  3 }, {   0x1C,  5 },
+        {   0x1B,  5 }, {   0x3A,  6 }, {   0x37,  7 }, {   0x6C,  8 },
+        {  0x1B6, 10 }, {  0x36E, 11 }, {  0xDBD, 13 }, { 0x36FF, 15 },
+        { 0x36FE, 15 }, { 0x1B79, 14 }, { 0x1B78, 14 }, {    0x2,  3 },
+        {    0xC,  4 }, {    0x0,  4 }, {    0xF,  5 }, {    0xC,  5 },
+        {    0xF,  4 }, {   0x1A,  5 }, {   0x3B,  6 }, {    0x5,  6 }
+    },
+    { /* AC bias group 2, table 14 */
+        {    0x5,  3 }, {   0x1E,  5 }, {   0x3A,  6 }, {   0x3E,  6 },
+        {   0xFC,  8 }, {  0xFD7, 12 }, { 0x3F55, 14 }, {   0x77,  7 },
+        {   0x30,  6 }, {    0x3,  3 }, {    0x4,  3 }, {   0x1A,  5 },
+        {   0x19,  5 }, {   0x7F,  7 }, {  0x1FB,  9 }, {  0x3F4, 10 },
+        {  0xFD6, 12 }, { 0x1FA9, 13 }, { 0x3F54, 14 }, { 0x3F57, 14 },
+        { 0x3F56, 14 }, { 0x3F51, 14 }, { 0x3F50, 14 }, {    0x1,  3 },
+        {    0x4,  4 }, {   0x1C,  5 }, {    0xB,  5 }, {    0xA,  5 },
+        {    0x0,  3 }, {   0x1B,  5 }, {   0x31,  6 }, {   0x76,  7 }
+    },
+    { /* AC bias group 2, table 15 */
+        {    0x5,  3 }, {    0xC,  4 }, {   0x1B,  5 }, {    0x8,  4 },
+        {   0x38,  6 }, {   0x15,  8 }, {   0xA3, 11 }, {   0xE6,  8 },
+        {    0x4,  6 }, {    0x1,  3 }, {    0x2,  3 }, {   0x12,  5 },
+        {    0x3,  5 }, {    0xB,  7 }, {   0x29,  9 }, {   0xA0, 11 },
+        {  0x142, 12 }, {  0x287, 13 }, {  0x286, 13 }, {  0x289, 13 },
+        {  0x288, 13 }, {  0x28B, 13 }, {  0x28A, 13 }, {    0xF,  4 },
+        {   0x1D,  5 }, {   0x13,  5 }, {    0x1,  5 }, {    0x0,  5 },
+        {    0x3,  3 }, {   0x1A,  5 }, {   0x72,  7 }, {   0xE7,  8 }
+    }
+};
+
+static const uint16_t vp4_ac_bias_2[16][32][2] = {
+    { /* AC bias group 3, table 0 */
+        {    0x9,  5 }, {   0x15,  7 }, {   0x28,  8 }, {   0x52,  9 },
+        {  0x29A, 12 }, {  0x537, 13 }, {  0x536, 13 }, {    0xA,  5 },
+        {   0x54,  7 }, {    0x4,  3 }, {    0x3,  3 }, {    0xC,  4 },
+        {    0xB,  4 }, {    0xD,  4 }, {    0x3,  4 }, {   0x14,  5 },
+        {   0x3A,  6 }, {    0x4,  5 }, {   0x38,  6 }, {   0x55,  7 },
+        {   0xA7, 10 }, {  0x299, 12 }, {  0x298, 12 }, {    0x0,  3 },
+        {   0x1E,  5 }, {    0x8,  5 }, {   0x2B,  6 }, {    0xB,  6 },
+        {    0xB,  5 }, {   0x3B,  6 }, {   0x1F,  5 }, {   0x39,  6 }
+    },
+    { /* AC bias group 3, table 1 */
+        {   0x1D,  5 }, {   0x2F,  7 }, {    0x2,  8 }, {    0x7,  9 },
+        {   0x19, 11 }, {   0x35, 12 }, {   0x34, 12 }, {    0x9,  5 },
+        {   0x2E,  7 }, {    0x6,  3 }, {    0x5,  3 }, {    0x9,  4 },
+        {    0x8,  4 }, {    0x7,  4 }, {   0x1F,  5 }, {    0x8,  5 },
+        {   0x18,  6 }, {   0x19,  6 }, {    0x1,  6 }, {    0x0,  7 },
+        {   0x18, 11 }, {   0x37, 12 }, {   0x36, 12 }, {    0x1,  3 },
+        {    0x1,  4 }, {    0xA,  5 }, {   0x39,  6 }, {   0x16,  6 },
+        {    0xD,  5 }, {    0x1,  5 }, {   0x1E,  5 }, {   0x38,  6 }
+    },
+    { /* AC bias group 3, table 2 */
+        {    0x1,  4 }, {   0x71,  7 }, {   0xE0,  8 }, {  0x1C3,  9 },
+        {  0x708, 11 }, { 0x1C26, 13 }, { 0x384F, 14 }, {    0x1,  5 },
+        {   0x31,  7 }, {    0x6,  3 }, {    0x5,  3 }, {    0x9,  4 },
+        {    0x8,  4 }, {    0x5,  4 }, {    0xF,  5 }, {   0x39,  6 },
+        {   0x77,  7 }, {   0x76,  7 }, {   0x30,  7 }, {  0x385, 10 },
+        { 0x384E, 14 }, { 0x1C25, 13 }, { 0x1C24, 13 }, {    0x1,  3 },
+        {    0x4,  4 }, {    0xD,  5 }, {    0x0,  5 }, {   0x19,  6 },
+        {   0x1F,  5 }, {    0xE,  5 }, {   0x1E,  5 }, {   0x3A,  6 }
+    },
+    { /* AC bias group 3, table 3 */
+        {    0x6,  4 }, {    0xC,  6 }, {   0xD6,  8 }, {   0x7B,  8 },
+        {  0x1E8, 10 }, {  0x7A4, 12 }, {  0xF4B, 13 }, {   0x36,  6 },
+        {   0x6A,  7 }, {    0x7,  3 }, {    0x5,  3 }, {    0x8,  4 },
+        {    0x9,  4 }, {    0x1,  4 }, {    0x7,  5 }, {    0xD,  6 },
+        {   0x3C,  7 }, {   0xD7,  8 }, {   0xF5,  9 }, {  0x7A7, 12 },
+        {  0xF4A, 13 }, {  0xF4D, 13 }, {  0xF4C, 13 }, {    0x2,  3 },
+        {    0x2,  4 }, {    0xE,  5 }, {   0x37,  6 }, {   0x34,  6 },
+        {    0x0,  4 }, {   0x19,  5 }, {   0x18,  5 }, {   0x1F,  6 }
+    },
+    { /* AC bias group 3, table 4 */
+        {    0xA,  4 }, {   0x27,  6 }, {   0xBF,  8 }, {   0xBE,  8 },
+        {  0x224, 10 }, { 0x225D, 14 }, { 0x225C, 14 }, {   0x26,  6 },
+        {   0x5E,  7 }, {    0x7,  3 }, {    0x6,  3 }, {    0x6,  4 },
+        {    0x7,  4 }, {   0x16,  5 }, {   0x2E,  6 }, {   0x45,  7 },
+        {   0x88,  8 }, {  0x113,  9 }, {  0x44A, 11 }, { 0x225F, 14 },
+        { 0x225E, 14 }, { 0x112D, 13 }, { 0x112C, 13 }, {    0x2,  3 },
+        {    0x2,  4 }, {   0x12,  5 }, {    0x3,  5 }, {    0x2,  5 },
+        {    0x3,  4 }, {    0x0,  4 }, {   0x10,  5 }, {   0x23,  6 }
+    },
+    { /* AC bias group 3, table 5 */
+        {    0xF,  4 }, {    0x6,  5 }, {   0x75,  7 }, {   0x74,  7 },
+        {    0xA,  9 }, {   0xBF, 13 }, {   0xB9, 13 }, {   0x22,  6 },
+        {    0x3,  7 }, {    0x5,  3 }, {    0x6,  3 }, {    0x1,  4 },
+        {    0x2,  4 }, {    0x7,  5 }, {    0x0,  6 }, {    0x4,  8 },
+        {   0x16, 10 }, {   0x5E, 12 }, {   0xB8, 13 }, {   0xBB, 13 },
+        {   0xBA, 13 }, {  0x17D, 14 }, {  0x17C, 14 }, {    0x2,  3 },
+        {    0x6,  4 }, {   0x1C,  5 }, {   0x10,  5 }, {   0x3B,  6 },
+        {    0x9,  4 }, {    0x7,  4 }, {    0x1,  5 }, {   0x23,  6 }
+    },
+    { /* AC bias group 3, table 6 */
+        {    0x1,  3 }, {   0x1C,  5 }, {   0x36,  6 }, {   0x3B,  6 },
+        {   0xEA,  8 }, {  0x75B, 11 }, { 0x1D65, 13 }, {   0x19,  6 },
+        {   0x74,  7 }, {    0x4,  3 }, {    0x5,  3 }, {    0x0,  4 },
+        {    0x1,  4 }, {   0x37,  6 }, {  0x1D7,  9 }, {  0x75A, 11 },
+        { 0x1D64, 13 }, { 0x1D67, 13 }, { 0x1D66, 13 }, { 0x1D61, 13 },
+        { 0x1D60, 13 }, { 0x1D63, 13 }, { 0x1D62, 13 }, {    0x2,  3 },
+        {   0x1F,  5 }, {   0x1A,  5 }, {    0xD,  5 }, {   0x3D,  6 },
+        {    0xC,  4 }, {    0x7,  4 }, {   0x3C,  6 }, {   0x18,  6 }
+    },
+    { /* AC bias group 3, table 7 */
+        {    0x2,  3 }, {    0x1,  4 }, {   0x14,  5 }, {    0x0,  4 },
+        {   0x2F,  6 }, {   0xBB,  8 }, {  0x2E4, 10 }, {   0x7D,  7 },
+        {   0xBA,  8 }, {    0x3,  3 }, {    0x4,  3 }, {   0x16,  5 },
+        {   0x1A,  5 }, {   0xB8,  8 }, { 0x172E, 13 }, { 0x2E5F, 14 },
+        { 0x2E5E, 14 }, { 0x1729, 13 }, { 0x1728, 13 }, { 0x172B, 13 },
+        { 0x172A, 13 }, { 0x172D, 13 }, { 0x172C, 13 }, {    0x1,  3 },
+        {   0x1E,  5 }, {   0x15,  5 }, {   0x1B,  5 }, {   0x3F,  6 },
+        {    0xC,  4 }, {    0xE,  4 }, {   0x7C,  7 }, {  0x173,  9 }
+    },
+    { /* AC bias group 3, table 8 */
+        {    0x3,  4 }, {   0x7B,  7 }, {   0x58,  8 }, {  0x1EA,  9 },
+        { 0x1EB1, 13 }, { 0x1EB0, 13 }, { 0x1EB3, 13 }, {   0x13,  6 },
+        {   0x12,  6 }, {    0x5,  3 }, {    0x6,  3 }, {    0x2,  4 },
+        {    0x1,  4 }, {   0x13,  5 }, {   0x3C,  6 }, {   0x2D,  7 },
+        {   0xF4,  8 }, {   0x59,  8 }, {  0x3D7, 10 }, {  0xF5B, 12 },
+        { 0x1EB2, 13 }, { 0x1EB5, 13 }, { 0x1EB4, 13 }, {    0x3,  3 },
+        {    0xE,  4 }, {   0x1F,  5 }, {   0x12,  5 }, {    0x8,  5 },
+        {    0x8,  4 }, {    0x0,  4 }, {    0xA,  5 }, {   0x17,  6 }
+    },
+    { /* AC bias group 3, table 9 */
+        {    0x8,  4 }, {   0x3C,  6 }, {   0xF5,  8 }, {   0xF4,  8 },
+        { 0x1EF7, 13 }, { 0x3DE9, 14 }, { 0x3DE8, 14 }, {   0x1C,  6 },
+        {    0xD,  6 }, {    0x5,  3 }, {    0x6,  3 }, {    0x1,  4 },
+        {    0x0,  4 }, {    0x7,  5 }, {    0xC,  6 }, {   0xF6,  8 },
+        {  0x1EE,  9 }, {  0x3DF, 10 }, {  0x7BC, 11 }, { 0x3DEB, 14 },
+        { 0x3DEA, 14 }, { 0x3DED, 14 }, { 0x3DEC, 14 }, {    0x2,  3 },
+        {    0x9,  4 }, {   0x1F,  5 }, {    0xF,  5 }, {    0x5,  5 },
+        {    0xE,  4 }, {    0x6,  4 }, {    0x4,  5 }, {   0x1D,  6 }
+    },
+    { /* AC bias group 3, table 10 */
+        {    0x9,  4 }, {   0x39,  6 }, {   0x19,  7 }, {   0x18,  7 },
+        {  0x706, 11 }, { 0x383D, 14 }, { 0x383C, 14 }, {    0xD,  6 },
+        {    0xF,  6 }, {    0x5,  3 }, {    0x6,  3 }, {    0x0,  4 },
+        {   0x1D,  5 }, {    0x3,  5 }, {   0x71,  7 }, {   0xE1,  8 },
+        {  0x1C0,  9 }, {  0x382, 10 }, { 0x1C1D, 13 }, { 0x383F, 14 },
+        { 0x383E, 14 }, { 0x3839, 14 }, { 0x3838, 14 }, {    0x2,  3 },
+        {    0x8,  4 }, {    0x2,  4 }, {    0xD,  5 }, {    0xC,  5 },
+        {    0xF,  4 }, {    0x7,  4 }, {    0x2,  5 }, {    0xE,  6 }
+    },
+    { /* AC bias group 3, table 11 */
+        {    0x0,  3 }, {    0x6,  5 }, {   0x35,  7 }, {   0x34,  7 },
+        {  0x777, 11 }, { 0x1DD4, 13 }, { 0x3BAB, 14 }, {    0xE,  6 },
+        {    0xF,  6 }, {    0x5,  3 }, {    0x4,  3 }, {   0x1C,  5 },
+        {   0x19,  5 }, {   0x3A,  6 }, {   0xEF,  8 }, {  0x1DC,  9 },
+        {  0x776, 11 }, {  0x774, 11 }, { 0x3BAA, 14 }, { 0x3BAD, 14 },
+        { 0x3BAC, 14 }, { 0x3BAF, 14 }, { 0x3BAE, 14 }, {    0x2,  3 },
+        {    0x7,  4 }, {    0x2,  4 }, {   0x18,  5 }, {    0xC,  5 },
+        {    0xF,  4 }, {    0xD,  4 }, {   0x1B,  6 }, {   0x76,  7 }
+    },
+    { /* AC bias group 3, table 12 */
+        {    0x2,  3 }, {   0x11,  5 }, {    0x6,  6 }, {   0x4F,  7 },
+        {  0x130,  9 }, { 0x1319, 13 }, { 0x1318, 13 }, {   0x4E,  7 },
+        {    0x7,  6 }, {    0x6,  3 }, {    0x5,  3 }, {   0x10,  5 },
+        {    0xD,  5 }, {    0x5,  6 }, {   0x99,  8 }, {  0x262, 10 },
+        {  0x98E, 12 }, { 0x131B, 13 }, { 0x131A, 13 }, { 0x263D, 14 },
+        { 0x263C, 14 }, { 0x263F, 14 }, { 0x263E, 14 }, {    0x1,  3 },
+        {    0x7,  4 }, {    0x0,  4 }, {   0x12,  5 }, {    0xC,  5 },
+        {    0xE,  4 }, {    0xF,  4 }, {    0x4,  6 }, {   0x4D,  7 }
+    },
+    { /* AC bias group 3, table 13 */
+        {    0x3,  3 }, {    0x0,  4 }, {    0x2,  5 }, {   0x37,  6 },
+        {  0x1B7,  9 }, {  0xDB5, 12 }, { 0x36DD, 14 }, {   0x6C,  7 },
+        {   0x16,  6 }, {    0x5,  3 }, {    0x4,  3 }, {    0x3,  5 },
+        {    0xA,  5 }, {   0x2E,  7 }, {  0x36C, 10 }, {  0xDB4, 12 },
+        { 0x36DC, 14 }, { 0x36DF, 14 }, { 0x36DE, 14 }, { 0x36D9, 14 },
+        { 0x36D8, 14 }, { 0x36DB, 14 }, { 0x36DA, 14 }, {    0xE,  4 },
+        {    0x4,  4 }, {   0x1A,  5 }, {   0x19,  5 }, {   0x18,  5 },
+        {    0xF,  4 }, {    0x1,  3 }, {   0x2F,  7 }, {   0xDA,  8 }
+    },
+    { /* AC bias group 3, table 14 */
+        {    0x6,  3 }, {    0x6,  4 }, {    0xF,  5 }, {    0x0,  4 },
+        {   0x75,  7 }, {  0x3B8, 10 }, { 0x1DCA, 13 }, {   0x74,  7 },
+        {   0x76,  7 }, {    0x4,  3 }, {    0x5,  3 }, {    0x3,  5 },
+        {    0x2,  5 }, {  0x1DE,  9 }, {  0xEE6, 12 }, { 0x3B97, 14 },
+        { 0x3B96, 14 }, { 0x3B9D, 14 }, { 0x3B9C, 14 }, { 0x3B9F, 14 },
+        { 0x3B9E, 14 }, { 0x1DC9, 13 }, { 0x1DC8, 13 }, {    0x5,  4 },
+        {   0x1C,  5 }, {    0x9,  5 }, {    0xE,  5 }, {    0x8,  5 },
+        {    0xF,  4 }, {    0x1,  3 }, {  0x1DF,  9 }, {  0x1DD,  9 }
+    },
+    { /* AC bias group 3, table 15 */
+        {    0x4,  3 }, {    0xB,  4 }, {   0x1D,  5 }, {    0xC,  4 },
+        {   0x14,  5 }, {   0xE0,  8 }, { 0x3875, 14 }, {  0x386, 10 },
+        {  0x1C2,  9 }, {    0x0,  2 }, {    0x1,  2 }, {   0x71,  7 },
+        {   0x72,  7 }, { 0x1C3F, 13 }, { 0x3874, 14 }, { 0x3877, 14 },
+        { 0x3876, 14 }, { 0x3871, 14 }, { 0x3870, 14 }, { 0x3873, 14 },
+        { 0x3872, 14 }, { 0x3879, 14 }, { 0x3878, 14 }, {   0x3C,  6 },
+        {   0x73,  7 }, {   0x2A,  6 }, {   0x3D,  6 }, {   0x2B,  6 },
+        {   0x1F,  5 }, {    0xD,  4 }, { 0x1C3E, 13 }, { 0x1C3D, 13 }
+    }
+};
+
+static const uint16_t vp4_ac_bias_3[16][32][2] = {
+    { /* AC bias group 4, table 0 */
+        {    0x7,  4 }, {    0xF,  6 }, {   0xBB,  8 }, {   0xBA,  8 },
+        {  0x5CF, 11 }, { 0x173A, 13 }, { 0x2E77, 14 }, {   0x29,  6 },
+        {  0x172,  9 }, {    0x7,  3 }, {    0x6,  3 }, {    0x9,  4 },
+        {    0x8,  4 }, {    0x1,  4 }, {    0x5,  5 }, {    0xD,  6 },
+        {   0x1D,  7 }, {   0x1C,  7 }, {   0xB8,  8 }, {  0x2E6, 10 },
+        { 0x2E76, 14 }, { 0x1739, 13 }, { 0x1738, 13 }, {    0x2,  3 },
+        {    0x6,  4 }, {   0x16,  5 }, {    0x4,  5 }, {   0x28,  6 },
+        {   0x15,  5 }, {    0xC,  6 }, {    0x0,  4 }, {   0x2F,  6 }
+    },
+    { /* AC bias group 4, table 1 */
+        {    0xB,  4 }, {    0x2,  5 }, {   0x54,  7 }, {   0x2F,  7 },
+        {  0x2AC, 10 }, { 0x156B, 13 }, { 0x1568, 13 }, {   0x16,  6 },
+        {  0x154,  9 }, {    0x7,  3 }, {    0x6,  3 }, {    0x4,  4 },
+        {    0x3,  4 }, {   0x13,  5 }, {   0x28,  6 }, {   0x2E,  7 },
+        {  0x157,  9 }, {  0x155,  9 }, {  0x55B, 11 }, { 0x2AD3, 14 },
+        { 0x2AD2, 14 }, { 0x2AD5, 14 }, { 0x2AD4, 14 }, {    0x3,  3 },
+        {    0x8,  4 }, {    0x0,  4 }, {    0xA,  5 }, {    0x3,  5 },
+        {    0x2,  4 }, {   0x2B,  6 }, {   0x12,  5 }, {   0x29,  6 }
+    },
+    { /* AC bias group 4, table 2 */
+        {    0xF,  4 }, {    0x7,  5 }, {    0x1,  6 }, {    0x0,  6 },
+        {  0x1C4,  9 }, {  0x703, 11 }, {  0xE02, 12 }, {   0x11,  6 },
+        {   0xE1,  8 }, {    0x5,  3 }, {    0x6,  3 }, {    0x2,  4 },
+        {    0x1,  4 }, {    0x9,  5 }, {   0x10,  6 }, {   0xE3,  8 },
+        {  0x1C5,  9 }, {  0x1C1,  9 }, {  0x702, 11 }, { 0x1C07, 13 },
+        { 0x1C06, 13 }, {  0xE01, 12 }, {  0xE00, 12 }, {    0x4,  3 },
+        {    0x7,  4 }, {   0x1D,  5 }, {    0xD,  5 }, {    0x1,  5 },
+        {    0x5,  4 }, {    0x6,  5 }, {    0xC,  5 }, {   0x39,  6 }
+    },
+    { /* AC bias group 4, table 3 */
+        {    0x1,  3 }, {   0x1C,  5 }, {   0x11,  6 }, {   0x13,  6 },
+        {   0x42,  8 }, {  0x207, 11 }, {  0x815, 13 }, {   0x75,  7 },
+        {   0x41,  8 }, {    0x5,  3 }, {    0x6,  3 }, {    0x0,  4 },
+        {   0x1F,  5 }, {   0x3B,  6 }, {   0x74,  7 }, {   0x43,  8 },
+        {   0x80,  9 }, {  0x206, 11 }, {  0x814, 13 }, {  0x817, 13 },
+        {  0x816, 13 }, {  0x409, 12 }, {  0x408, 12 }, {    0x3,  3 },
+        {    0x9,  4 }, {   0x1E,  5 }, {   0x11,  5 }, {    0x3,  5 },
+        {    0x5,  4 }, {   0x10,  5 }, {    0x2,  5 }, {   0x12,  6 }
+    },
+    { /* AC bias group 4, table 4 */
+        {    0x1,  3 }, {   0x1F,  5 }, {   0x27,  6 }, {    0x1,  5 },
+        {   0x4B,  8 }, {  0x123, 10 }, {  0x915, 13 }, {    0x0,  6 },
+        {   0x49,  8 }, {    0x5,  3 }, {    0x6,  3 }, {   0x1D,  5 },
+        {   0x1C,  5 }, {   0x13,  6 }, {   0x4A,  8 }, {   0x90,  9 },
+        {  0x914, 13 }, {  0x917, 13 }, {  0x916, 13 }, {  0x911, 13 },
+        {  0x910, 13 }, {  0x913, 13 }, {  0x912, 13 }, {    0x3,  3 },
+        {    0x5,  4 }, {    0x1,  4 }, {   0x12,  5 }, {    0x8,  5 },
+        {    0x8,  4 }, {   0x1E,  5 }, {   0x26,  6 }, {    0x1,  6 }
+    },
+    { /* AC bias group 4, table 5 */
+        {    0x3,  3 }, {    0x1,  4 }, {   0x3F,  6 }, {    0xB,  5 },
+        {   0x4E,  7 }, {  0x132,  9 }, {  0x99A, 12 }, {   0x4F,  7 },
+        {   0x98,  8 }, {    0x6,  3 }, {    0x5,  3 }, {   0x1D,  5 },
+        {   0x1C,  5 }, {   0x7C,  7 }, {  0x267, 10 }, { 0x1331, 13 },
+        { 0x1330, 13 }, { 0x1333, 13 }, { 0x1332, 13 }, { 0x266D, 14 },
+        { 0x266C, 14 }, { 0x266F, 14 }, { 0x266E, 14 }, {    0x1,  3 },
+        {    0x4,  4 }, {   0x1E,  5 }, {   0x12,  5 }, {    0xA,  5 },
+        {    0x8,  4 }, {    0x0,  4 }, {   0x7D,  7 }, {   0x4D,  7 }
+    },
+    { /* AC bias group 4, table 6 */
+        {    0x2,  3 }, {    0x7,  4 }, {   0x15,  5 }, {    0x3,  4 },
+        {    0x4,  5 }, {   0xA7,  8 }, {  0x536, 11 }, {   0x28,  6 },
+        {  0x29A, 10 }, {    0x6,  3 }, {    0x4,  3 }, {   0x1C,  5 },
+        {   0x17,  5 }, {   0xA4,  8 }, { 0x29BE, 14 }, { 0x537F, 15 },
+        { 0x537E, 15 }, { 0x29B9, 14 }, { 0x29B8, 14 }, { 0x29BB, 14 },
+        { 0x29BA, 14 }, { 0x29BD, 14 }, { 0x29BC, 14 }, {    0xF,  4 },
+        {    0x0,  4 }, {    0x5,  5 }, {   0x16,  5 }, {   0x1D,  5 },
+        {    0x6,  4 }, {    0x1,  4 }, {   0xA5,  8 }, {  0x14C,  9 }
+    },
+    { /* AC bias group 4, table 7 */
+        {    0x4,  3 }, {    0x7,  4 }, {   0x1A,  5 }, {    0xC,  4 },
+        {    0x6,  4 }, {   0x29,  6 }, {  0x1BD,  9 }, { 0x1BE3, 13 },
+        { 0x1BE0, 13 }, {    0x0,  2 }, {    0x7,  3 }, {   0x6E,  7 },
+        {  0x1BC,  9 }, { 0x37C3, 14 }, { 0x37C2, 14 }, { 0x37CD, 14 },
+        { 0x37CC, 14 }, { 0x37CF, 14 }, { 0x37CE, 14 }, { 0x37C9, 14 },
+        { 0x37C8, 14 }, { 0x37CB, 14 }, { 0x37CA, 14 }, {   0x15,  5 },
+        {  0x1BF,  9 }, {  0x37D, 10 }, {   0x36,  6 }, {    0x2,  3 },
+        {    0xB,  4 }, {   0x28,  6 }, { 0x37C5, 14 }, { 0x37C4, 14 }
+    },
+    { /* AC bias group 4, table 8 */
+        {    0x1,  3 }, {    0x9,  5 }, {    0x3,  6 }, {    0x2,  6 },
+        {  0x11F, 10 }, {  0x8E9, 13 }, {  0x8E8, 13 }, {   0x2D,  7 },
+        {   0x22,  7 }, {    0x6,  3 }, {    0x7,  3 }, {   0x10,  5 },
+        {   0x11,  5 }, {   0x17,  6 }, {   0x2C,  7 }, {   0x46,  8 },
+        {  0x11E, 10 }, {  0x11C, 10 }, {  0x477, 12 }, {  0x8EB, 13 },
+        {  0x8EA, 13 }, {  0x8ED, 13 }, {  0x8EC, 13 }, {    0x3,  3 },
+        {    0xB,  4 }, {    0x1,  4 }, {   0x14,  5 }, {    0xA,  5 },
+        {    0x9,  4 }, {   0x15,  5 }, {    0x0,  5 }, {   0x10,  6 }
+    },
+    { /* AC bias group 4, table 9 */
+        {    0x1,  3 }, {   0x1D,  5 }, {   0x22,  6 }, {   0x13,  6 },
+        {  0x11E,  9 }, {  0x8FC, 12 }, { 0x23F5, 14 }, {   0x23,  7 },
+        {   0x22,  7 }, {    0x5,  3 }, {    0x6,  3 }, {   0x10,  5 },
+        {    0xB,  5 }, {   0x10,  6 }, {   0x8E,  8 }, {  0x23E, 10 },
+        {  0x8FF, 12 }, { 0x11FD, 13 }, { 0x23F4, 14 }, { 0x23F7, 14 },
+        { 0x23F6, 14 }, { 0x23F9, 14 }, { 0x23F8, 14 }, {    0x3,  3 },
+        {    0x9,  4 }, {    0x0,  4 }, {   0x1C,  5 }, {    0xA,  5 },
+        {    0xF,  4 }, {    0x1,  4 }, {   0x12,  6 }, {   0x46,  7 }
+    },
+    { /* AC bias group 4, table 10 */
+        {    0x3,  3 }, {   0x1F,  5 }, {   0x3C,  6 }, {   0x3D,  6 },
+        {   0x86,  8 }, {  0x877, 12 }, { 0x10E8, 13 }, {   0x41,  7 },
+        {   0x40,  7 }, {    0x5,  3 }, {    0x6,  3 }, {    0x7,  5 },
+        {    0x6,  5 }, {    0x4,  6 }, {  0x10F,  9 }, {  0x21C, 10 },
+        {  0x875, 12 }, { 0x21D3, 14 }, { 0x21D2, 14 }, { 0x21D9, 14 },
+        { 0x21D8, 14 }, { 0x21DB, 14 }, { 0x21DA, 14 }, {    0x2,  3 },
+        {    0x9,  4 }, {    0x0,  4 }, {   0x11,  5 }, {    0x3,  5 },
+        {    0xE,  4 }, {    0x2,  4 }, {    0x5,  6 }, {   0x42,  7 }
+    },
+    { /* AC bias group 4, table 11 */
+        {    0x4,  3 }, {    0x1,  4 }, {   0x3D,  6 }, {    0x9,  5 },
+        {   0xF3,  8 }, {  0x793, 11 }, { 0x1E45, 13 }, {    0x0,  7 },
+        {    0x2,  7 }, {    0x5,  3 }, {    0x6,  3 }, {    0x8,  5 },
+        {    0x1,  5 }, {    0x3,  7 }, {  0x1E5,  9 }, {  0x792, 11 },
+        { 0x1E44, 13 }, { 0x1E47, 13 }, { 0x1E46, 13 }, { 0x1E41, 13 },
+        { 0x1E40, 13 }, { 0x1E43, 13 }, { 0x1E42, 13 }, {    0x1,  3 },
+        {    0x6,  4 }, {   0x1F,  5 }, {    0xF,  5 }, {    0xE,  5 },
+        {    0xE,  4 }, {    0x5,  4 }, {   0x78,  7 }, {    0x1,  7 }
+    },
+    { /* AC bias group 4, table 12 */
+        {    0x4,  3 }, {    0x5,  4 }, {    0xE,  5 }, {   0x17,  5 },
+        {   0x3E,  7 }, {   0xF0,  9 }, {  0xF1E, 13 }, {   0x7A,  8 },
+        {   0x7F,  8 }, {    0x6,  3 }, {    0x7,  3 }, {    0x5,  5 },
+        {    0x4,  5 }, {   0x7B,  8 }, {  0x1E2, 10 }, { 0x1E3F, 14 },
+        { 0x1E3E, 14 }, {  0xF19, 13 }, {  0xF18, 13 }, {  0xF1B, 13 },
+        {  0xF1A, 13 }, {  0xF1D, 13 }, {  0xF1C, 13 }, {    0x0,  3 },
+        {    0x3,  4 }, {   0x16,  5 }, {    0x9,  5 }, {    0x8,  5 },
+        {    0xA,  4 }, {    0x6,  4 }, {   0x7E,  8 }, {   0x79,  8 }
+    },
+    { /* AC bias group 4, table 13 */
+        {    0x5,  3 }, {    0xC,  4 }, {   0x1A,  5 }, {    0x4,  4 },
+        {   0x1A,  6 }, {   0xDE,  9 }, {  0xDF4, 13 }, {   0xDD,  9 },
+        {   0x6D,  8 }, {    0x0,  2 }, {    0x7,  3 }, {   0x25,  6 },
+        {   0x24,  6 }, {   0xDC,  9 }, {  0xDF7, 13 }, { 0x1BEB, 14 },
+        { 0x1BEA, 14 }, {  0xDF1, 13 }, {  0xDF0, 13 }, {  0xDF3, 13 },
+        {  0xDF2, 13 }, { 0x1BED, 14 }, { 0x1BEC, 14 }, {    0x8,  4 },
+        {   0x13,  5 }, {    0xC,  5 }, {   0x37,  6 }, {   0x36,  6 },
+        {    0x5,  4 }, {    0x7,  4 }, {   0x6C,  8 }, {  0x1BF, 10 }
+    },
+    { /* AC bias group 4, table 14 */
+        {    0x5,  3 }, {    0xD,  4 }, {   0x1F,  5 }, {    0xC,  4 },
+        {   0x3B,  6 }, {   0x40,  7 }, {  0x41A, 11 }, {  0x104,  9 },
+        {  0x107,  9 }, {    0x1,  2 }, {    0x0,  2 }, {   0x24,  6 },
+        {   0x21,  6 }, {  0x20B, 10 }, { 0x106E, 13 }, { 0x20DF, 14 },
+        { 0x20DE, 14 }, { 0x1055, 13 }, { 0x1054, 13 }, { 0x1057, 13 },
+        { 0x1056, 13 }, { 0x106D, 13 }, { 0x106C, 13 }, {   0x11,  5 },
+        {   0x3A,  6 }, {   0x25,  6 }, {   0x38,  6 }, {   0x39,  6 },
+        {   0x13,  5 }, {   0x1E,  5 }, {  0x20C, 10 }, {  0x414, 11 }
+    },
+    { /* AC bias group 4, table 15 */
+        {    0x0,  2 }, {    0x7,  4 }, {    0xD,  5 }, {    0x5,  4 },
+        {    0x9,  5 }, {   0x22,  7 }, {  0xCD1, 13 }, {  0xCD0, 13 },
+        {  0xCD3, 13 }, {    0x3,  2 }, {    0x2,  2 }, {   0x8D,  9 },
+        {   0xCC,  9 }, {  0x66B, 12 }, {  0xCD2, 13 }, { 0x19B5, 14 },
+        { 0x19B4, 14 }, { 0x19B7, 14 }, { 0x19B6, 14 }, { 0x19B1, 14 },
+        { 0x19B0, 14 }, { 0x19B3, 14 }, { 0x19B2, 14 }, {   0x47,  8 },
+        {   0x8C,  9 }, {  0x337, 11 }, {   0x67,  8 }, {   0x18,  6 },
+        {   0x10,  6 }, {   0x32,  7 }, {  0xCD5, 13 }, {  0xCD4, 13 }
+    }
+};
+
+#endif /* AVCODEC_VP4DATA_H */