[FFmpeg-devel] avcodec/scpr: add version 3 support

Submitted by Paul B Mahol on Sept. 4, 2018, 5:53 p.m.

Details

Message ID 20180904175359.22152-1-onemda@gmail.com
State New
Headers show

Commit Message

Paul B Mahol Sept. 4, 2018, 5:53 p.m.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 libavcodec/scpr.c | 1842 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 1558 insertions(+), 284 deletions(-)

Comments

Rostislav Pehlivanov Sept. 5, 2018, 7:58 p.m.
On 4 September 2018 at 18:53, Paul B Mahol <onemda@gmail.com> wrote:

> Signed-off-by: Paul B Mahol <onemda@gmail.com>
> ---
>  libavcodec/scpr.c | 1842 ++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 1558 insertions(+), 284 deletions(-)
>
> diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c
> index ee6bf21b71..4cd9e33d71 100644
> --- a/libavcodec/scpr.c
> +++ b/libavcodec/scpr.c
> @@ -24,47 +24,1538 @@
>  #include <stdlib.h>
>  #include <string.h>
>
> +#include "libavutil/qsort.h"
> +
>  #include "avcodec.h"
>  #include "bytestream.h"
>  #include "internal.h"
>
> -#define TOP  0x01000000
> -#define BOT    0x010000
> +#define TOP  0x01000000
> +#define BOT    0x010000
>
+
>

I think the range coder is too big so you should put it in another file.


+typedef struct RangeCoder {
> +    unsigned   code;
> +    unsigned   range;
> +    unsigned   code1;
> +} RangeCoder;
> +
> +typedef struct PixelModel {
> +    unsigned    freq[256];
> +    unsigned    lookup[16];
> +    unsigned    total_freq;
> +} PixelModel;
>

You should really specify how many bits the models need rather than leaving
them as random unsigned.



> +
> +typedef struct PixelModel3 {
> +    uint8_t    type;
> +    uint8_t    length;
> +    uint8_t    maxpos;
> +    uint8_t    fshift;
> +    uint16_t   size;
> +    uint32_t   cntsum;
> +    uint8_t    symbols[256];
> +    uint16_t   freqs[256];
> +    uint16_t   freqs1[256];
> +    uint16_t   cnts[256];
> +    uint8_t    dectab[32];
> +} PixelModel3;
> +
> +typedef struct FillModel3 {
> +    uint32_t   cntsum;
> +    uint16_t   freqs[2][5];
> +    uint16_t   cnts[5];
> +    uint8_t    dectab[32];
> +} FillModel3;
> +
> +typedef struct OpModel3 {
> +    uint32_t   cntsum;
> +    uint16_t   freqs[2][6];
> +    uint16_t   cnts[6];
> +    uint8_t    dectab[32];
> +} OpModel3;
> +
> +typedef struct RunModel3 {
> +    uint32_t   cntsum;
> +    uint16_t   freqs[2][256];
> +    uint16_t   cnts[256];
> +    uint8_t    dectab[32];
> +} RunModel3;
> +
> +typedef struct SxyModel3 {
> +    uint32_t   cntsum;
> +    uint16_t   freqs[2][16];
> +    uint16_t   cnts[16];
> +    uint8_t    dectab[32];
> +} SxyModel3;
> +
> +typedef struct MVModel3 {
> +    uint32_t   cntsum;
> +    uint16_t   freqs[2][512];
> +    uint16_t   cnts[512];
> +    uint8_t    dectab[32];
> +} MVModel3;
> +
> +typedef struct SCPRContext {
> +    int             version;
> +    AVFrame        *last_frame;
> +    AVFrame        *current_frame;
> +    GetByteContext  gb;
> +    RangeCoder      rc;
> +    PixelModel      pixel_model[3][4096];
> +    unsigned        op_model[6][7];
> +    unsigned        run_model[6][257];
> +    unsigned        range_model[257];
> +    unsigned        count_model[257];
> +    unsigned        fill_model[6];
> +    unsigned        sxy_model[4][17];
> +    unsigned        mv_model[2][513];
> +    unsigned        nbx, nby;
> +    unsigned        nbcount;
> +    unsigned       *blocks;
> +    unsigned        cbits;
> +    int             cxshift;
> +
> +    PixelModel3     pixel_model3[3][4096];
> +    RunModel3       run_model3[6];
> +    RunModel3       range_model3;
> +    RunModel3       count_model3;
> +    FillModel3      fill_model3;
> +    SxyModel3       sxy_model3[4];
> +    MVModel3        mv_model3[2];
> +    OpModel3        op_model3[6];
> +
> +    int           (*get_freq)(RangeCoder *rc, unsigned total_freq,
> unsigned *freq);
> +    int           (*decode)(GetByteContext *gb, RangeCoder *rc, unsigned
> cumFreq, unsigned freq, unsigned total_freq);
> +} SCPRContext;
> +
> +static void renew_table3(unsigned nsym, uint32_t *cntsum,
> +                         uint16_t *freqs, uint16_t *freqs1,
> +                         uint16_t *cnts, uint8_t *dectab)
> +{
> +    unsigned a = 0, b = 4096 / nsym, c = b - (b >> 1);
> +
> +    *cntsum = c * nsym;
> +
> +    for (int d = 0; d < nsym; d++) {
> +        freqs[d] = b;
> +        freqs1[d] = a;
> +        cnts[d] = c;
> +        for (int q = a + 128 - 1 >> 7, f = (a + b - 1 >> 7) + 1; q < f;
> q++) {
> +            dectab[q] = d;
> +        }
>

That's a weird loop, but you don't need brackets here.


+
> +        a += b;
> +    }
> +}
> +
> +static void reinit_tables3(SCPRContext * s)
> +{
> +    for (int i = 0; i < 3; i++) {
> +        for (int j = 0; j < 4096; j++) {
> +            PixelModel3 *m = &s->pixel_model3[i][j];
> +            m->type = 0;
> +        }
> +    }
> +
> +    for (int i = 0; i < 6; i++) {
> +        renew_table3(256, &s->run_model3[i].cntsum,
> +                     s->run_model3[i].freqs[0], s->run_model3[i].freqs[1],
> +                     s->run_model3[i].cnts, s->run_model3[i].dectab);
> +    }
> +
> +    renew_table3(256, &s->range_model3.cntsum,
> +                 s->range_model3.freqs[0], s->range_model3.freqs[1],
> +                 s->range_model3.cnts, s->range_model3.dectab);
> +
> +    renew_table3(5, &s->fill_model3.cntsum,
> +                 s->fill_model3.freqs[0], s->fill_model3.freqs[1],
> +                 s->fill_model3.cnts, s->fill_model3.dectab);
> +
> +    renew_table3(256, &s->count_model3.cntsum,
> +                 s->count_model3.freqs[0], s->count_model3.freqs[1],
> +                 s->count_model3.cnts, s->count_model3.dectab);
> +
> +    for (int i = 0; i < 4; i++) {
> +        renew_table3(16, &s->sxy_model3[i].cntsum,
> +                     s->sxy_model3[i].freqs[0], s->sxy_model3[i].freqs[1],
> +                     s->sxy_model3[i].cnts, s->sxy_model3[i].dectab);
> +    }
> +
> +    for (int i = 0; i < 2; i++) {
> +        renew_table3(512, &s->mv_model3[i].cntsum,
> +                     s->mv_model3[i].freqs[0], s->mv_model3[i].freqs[1],
> +                     s->mv_model3[i].cnts, s->mv_model3[i].dectab);
> +    }
> +
> +    for (int i = 0; i < 6; i++) {
> +        renew_table3(6, &s->op_model3[i].cntsum,
> +                     s->op_model3[i].freqs[0], s->op_model3[i].freqs[1],
> +                     s->op_model3[i].cnts, s->op_model3[i].dectab);
> +    }
> +}
> +
> +static int decode3(GetByteContext *gb, RangeCoder *rc, unsigned a,
> unsigned b)
> +{
> +    unsigned x = a * (rc->code >> 12) + (rc->code & 0xFFF) - b;
> +
> +    while (x < 0x800000 && bytestream2_get_bytes_left(gb) > 0) {
> +        x = bytestream2_get_byte(gb) | (x << 8);
> +    }
>

No brackets needed here either.



> +    rc->code = x;
> +
> +    return 0;
> +}
> +
> +static void rescale(PixelModel3 *m, int *totfr)
> +{
> +    unsigned a, b, c;
>

Use whatever the range coder needs rather than unsigned.



> +
> +    for (a = 256 - m->size, b = 0, c = m->size; b < c; b++) {
> +        m->freqs[b] -= m->freqs[b] >> 1;
> +        a += m->freqs[b];
> +    }
> +
> +    *totfr = a;
> +}
> +
> +static int add_symbol(PixelModel3 *m, int index, unsigned symbol, int
> *totfr, int max)
> +{
> +    if (m->size == max)
> +        return 0;
> +
> +    for (int c = m->size - 1; c >= index; c--) {
> +        m->symbols[c + 1] = m->symbols[c];
> +        m->freqs[c + 1] = m->freqs[c];
> +    }
> +
> +    m->symbols[index] = symbol;
> +    m->freqs[index] = 50;
> +    m->size++;
> +
> +    if (m->maxpos >= index)
> +        m->maxpos++;
> +
> +    *totfr += 50;
> +    if (*totfr + 50 > 4096)
> +        rescale(m, totfr);
> +
> +    return 1;
> +}
> +
> +static int decode_adaptive45(PixelModel3 *m, int rccode, unsigned *value,
> +                             uint16_t *a, uint16_t *b, uint32_t *c, int
> max)
> +{
> +    unsigned q, g, maxpos, d, e = *c, totfr = *c;
> +    int ret;
> +
> +    for (d = 0; e <= 2048; d++)
> +        e <<= 1;
> +    maxpos = m->maxpos;
> +    rccode >>= d;
> +    *c = m->freqs[maxpos];
> +    m->freqs[maxpos] += 4096 - e >> d;
> +
> +    for (q = 0, g = 0, e = 0; q < m->size; q++) {
> +        unsigned f = m->symbols[q];
> +        unsigned p = e + f - g;
> +        unsigned k = m->freqs[q];
> +
> +        if (rccode < p) {
> +            *value = rccode - e + g;
> +            *b = rccode << d;
> +            *a = 1 << d;
> +            m->freqs[maxpos] = *c;
> +            ret = add_symbol(m, q, *value, &totfr, max);
> +            *c = totfr;
> +            return ret;
> +        }
> +
> +        if (p + k > rccode) {
> +            *value = f;
> +            e += *value - g;
> +            *b = e << d;
> +            *a = k << d;
> +            m->freqs[maxpos] = *c;
> +            m->freqs[q] += 50;
> +            totfr += 50;
> +            if ((q != maxpos) && (m->freqs[q] > m->freqs[maxpos]))
> +                m->maxpos = q;
> +            if (totfr + 50 > 4096)
> +                rescale(m, &totfr);
> +            *c = totfr;
> +            return 1;
> +        }
> +
> +        e += f - g + k;
> +        g = f + 1;
> +    }
> +
> +    m->freqs[maxpos] = *c;
> +    *value = g + rccode - e;
> +    *b = rccode << d;
> +    *a = 1 << d;
> +    ret = add_symbol(m, q, *value, &totfr, max);
> +    *c = totfr;
> +    return ret;
> +}
> +
> +static int update_model6_to_7(PixelModel3 *n, PixelModel3 *m)
> +{
> +    int c, d, e, f, k, p, length, i, j, index;
> +    uint16_t *freqs, *freqs1, *cnts;
> +
> +    n->type = 7;
> +
> +    length = m->length;
> +    freqs = n->freqs;
> +    freqs1 = n->freqs1;
> +    cnts = n->cnts;
> +    n->cntsum = m->cnts[length];
> +    for (i = 0; i < length; i++) {
> +        if (!m->cnts[i])
> +            continue;
> +        index = m->symbols[i];
> +        freqs[index] = m->freqs[2 * i];
> +        freqs1[index] = m->freqs[2 * i + 1];
> +        cnts[index] = m->cnts[i];
> +    }
> +    c = 1 << m->fshift;
> +    d = c - (c >> 1);
> +    for (j = 0, e = 0; j < 256; j++) {
> +        f = freqs[j];
> +        if (!f) {
> +            f = c;
> +            freqs[j] = c;
> +            freqs1[j] = e;
> +            cnts[j] = d;
> +        }
> +        p = (e + 127) >> 7;
> +        k = ((f + e - 1) >> 7) + 1;
> +        for (i = 0; i < k - p; i++)
> +            n->dectab[p + i] = j;
> +        e += f;
> +    }
> +
> +    memcpy(m, n, sizeof(*n));
> +
> +    return 0;
> +}
> +
> +static void calc_sum(PixelModel3 *m)
> +{
> +    int a, b, c;
> +
> +    b = m->length;
> +    a = 256 - m->size << (0 < m->fshift ? m->fshift - 1 : 0);
> +    for (c = 0; c < b; c++)
> +        a += m->cnts[c];
> +    m->cnts[b] = a;
> +}
> +
> +static void rescale_dec(PixelModel3 *m)
> +{
> +    uint16_t cnts[256] = {0};
> +    uint16_t freqs[512] = {0};
> +    int a, b, c, e, g;
> +
> +    for (a = 1 << (0 < m->fshift ? m->fshift - 1 : 0), b = 0; b < 256;
> b++) {
> +        cnts[b] = a;
> +    }
> +
> +    for (a = 0, b = m->size; a < b; a++) {
> +        cnts[m->symbols[a]] = m->cnts[a];
> +    }
> +
> +    for (b = a = 0; b < 256; b++) {
> +        freqs[2 * b] = cnts[b];
> +        freqs[2 * b + 1] = a;
> +        a += cnts[b];
> +    }
> +
> +    if (m->fshift > 0)
> +        m->fshift--;
> +
> +    a = 256 - m->size << (0 < m->fshift ? m->fshift - 1 : 0);
> +    for (b = 0, c = m->size; b < c; b++) {
> +        m->cnts[b] -= m->cnts[b] >> 1;
> +        a = a + m->cnts[b];
> +        e = m->symbols[b];
> +        g = freqs[2 * e + 1];
> +        m->freqs[2 * b] = freqs[2 * e];
> +        m->freqs[2 * b + 1] = g;
> +    }
> +    m->cnts[m->length] = a;
> +}
> +
> +static int update_model5_to_6(PixelModel3 *n, PixelModel3 *m, uint8_t
> value)
> +{
> +    int c, d, e, f, g, k, q, p;
>

This looks like its directly out of a decompiler. Any chance of having more
descript names (and using for (int) to discern what's a loop counter).


+
> +    n->type = 6;
> +    n->length = 32;
> +
> +    for (c = m->size, d = 256 - c, e = 0; e < c; e++)
> +        d = d + m->freqs[e];
> +
> +    for (e = 0; 2048 >= d; e++)
> +        d <<= 1;
> +
> +    for (q = d = 0, g = q = 0; g < c; g++) {
> +        p = m->symbols[g];
> +        d = d + (p - q);
> +        q = m->freqs[g];
> +        k = q << e;
> +        n->freqs[2 * g] = k;
> +        n->freqs[2 * g + 1] = d << e;
> +        n->cnts[g] = k - (k >> 1);
> +        n->symbols[g] = p;
> +        d += q;
> +        q = p + 1;
> +    }
> +
> +    n->fshift = e;
> +    e = 1 << n->fshift;
> +    d = 0;
> +    if (value > 0) {
> +        d = -1;
> +        for (p = f = g = 0; p < c; p++) {
> +            k = n->symbols[p];
> +            if (k > d && k < value) {
> +                d = k;
> +                g = n->freqs[2 * p];
> +                f = n->freqs[2 * p + 1];
> +            }
> +        }
> +        d = 0 < g ? f + g + (value - d - 1 << n->fshift) : value <<
> n->fshift;
> +    }
> +    n->freqs[2 * c] = e;
> +    n->freqs[2 * c + 1] = d;
> +    n->cnts[c] = e - (e >> 1);
> +    n->symbols[c] = value;
> +    n->size = c + 1;
> +    e = 25 << n->fshift;
> +    n->cnts[c] += e;
> +    n->cnts[32] += e;
> +    if (n->cnts[32] + e > 4096) {
> +        rescale_dec(n);
> +    }
> +    calc_sum(n);
> +    c = 0;
> +    for (e = n->size - 1; c < e;) {
> +        for (d = c++, g = d + 1, f = n->size; g < f;) {
> +            if (p = g++, q = n->freqs[2 * p], k = n->freqs[2 * d], q > k)
> {
> +                int l = n->freqs[2 * d + 1];
> +                int h = n->freqs[2 * p + 1];
> +                n->freqs[2 * d] = q;
> +                n->freqs[2 * d + 1] = h;
> +                n->freqs[2 * p] = k;
> +                n->freqs[2 * p + 1] = l;
> +                FFSWAP(uint16_t, n->cnts[d], n->cnts[p]);
> +                FFSWAP(uint8_t, n->symbols[d], n->symbols[p]);
> +            }
> +        }
> +    }
> +
> +    memcpy(m, n, sizeof(*n));
> +
> +    return 0;
> +}
> +
> +static void grow_dec(PixelModel3 *m)
> +{
> +    int a;
> +
> +    a = 2 * m->length;
> +    m->cnts[2 * m->length] = m->cnts[m->length];
> +    m->length = a;
> +}
> +
> +static int add_dec(PixelModel3 *m, int a, int b, int c)
> +{
> +    int d;
> +
> +    if (m->size >= 40 || m->size >= m->length)
> +        return -1;
> +
> +    d = m->size;
> +    m->symbols[d] = a;
> +    m->freqs[2 * d] = b;
> +    m->freqs[2 * d + 1] = c;
> +    m->cnts[d] = b - (b >> 1);
> +    m->size++;
> +
> +    return d;
> +}
> +
> +static void incr_cntdec(PixelModel3 *m, int a)
> +{
> +    int b, c, d, e, g;
> +
> +    b = 25 << m->fshift;
> +    c = m->length;
> +    m->cnts[a] += b;
> +    m->cnts[c] += b;
> +    if (a > 0 && m->cnts[a] > m->cnts[a - 1]) {
> +        d = m->cnts[a];
> +        m->cnts[a] = m->cnts[a - 1];
> +        m->cnts[a - 1] = d;
> +        d = m->freqs[2 * a];
> +        e = m->freqs[2 * a + 1];
> +        g = m->freqs[2 * (a - 1) + 1];
> +        m->freqs[2 * a] = m->freqs[2 * (a - 1)];
> +        m->freqs[2 * a + 1] = g;
> +        g = a - 1;
> +        m->freqs[2 * g] = d;
> +        m->freqs[2 * g + 1] = e;
> +        d = m->symbols[a];
> +        m->symbols[a] = m->symbols[a - 1];
> +        m->symbols[a - 1] = d;
> +    }
> +    if (m->cnts[c] + b > 4096)
> +        rescale_dec(m);
> +}
> +
> +static int decode_adaptive6(PixelModel3 *m, unsigned code, unsigned
> *value,
> +                            uint16_t *a, uint16_t *b)
> +{
> +    int c, d, e, f, g, q;
> +
> +    for (c = 0, d = 0, e = 0, f = 0, g = 0, q = m->size; g < q; g++) {
> +        unsigned p = m->freqs[2 * g + 1];
> +
> +        if (p <= code) {
> +            unsigned k = m->freqs[2 * g];
> +
> +            if (p + k > code) {
> +                *value = m->symbols[g];
> +                *a = k;
> +                *b = p;
> +                incr_cntdec(m, g);
> +                return 1;
> +            }
> +
> +            if (p >= d) {
> +                c = k;
> +                d = p;
> +                e = m->symbols[g];
> +            }
> +        }
> +    }
> +
> +    g = 1 << m->fshift;
> +    q = f = 0;
> +
> +    if (c > 0) {
> +        f = code - (d + c) >> m->fshift;
> +        q = f + e + 1;
> +        f = d + c + (f << m->fshift);
> +    } else {
> +        q = code >> m->fshift;
> +        f = q << m->fshift;
> +    }
> +
> +    *a = g;
> +    *b = f;
> +    *value = q;
> +
> +    c = add_dec(m, q, g, f);
> +    if (c < 0) {
> +        if (m->length == 64)
> +            return 0;
> +        grow_dec(m);
> +        c = add_dec(m, q, g, f);
> +    }
> +
> +    incr_cntdec(m, c);
> +    return 1;
> +}
> +
> +static int cmpbytes(const void *p1, const void *p2)
> +{
> +    int left  = *(const uint8_t *)p1;
> +    int right = *(const uint8_t *)p2;
> +    return FFDIFFSIGN(left, right);
> +}
>

What is this function doing? I don't think its comparing bytes.


+
> +static int update_model1_to_2(PixelModel3 *m, unsigned val)
> +{
> +    PixelModel3 n = {0};
> +    int i, b;
> +
> +    n.type = 2;
> +    n.size = m->size + 1;
> +    b = m->size;
> +    for (i = 0; i < b; i++)
> +        n.symbols[i] = m->symbols[i];
> +    n.symbols[b] = val;
> +
> +    memcpy(m, &n, sizeof(n));
> +
> +    return 0;
> +}
> +
> +static int update_model1_to_4(PixelModel3 *m, unsigned val)
> +{
> +    PixelModel3 n = {0};
> +    int size, i;
> +
> +    size = m->size;
> +    n.type = 4;
> +    n.size = size;
> +    for (i = 0; i < n.size; i++) {
> +        n.symbols[i] = m->symbols[i];
> +    }
>

No brackets needed.


+    AV_QSORT(n.symbols, size, uint8_t, cmpbytes);
> +    for (i = 0; i < n.size; i++) {
> +        if (val == n.symbols[i]) {
> +            n.freqs[i] = 100;
> +            n.maxpos = i;
> +        } else {
> +            n.freqs[i] = 50;
> +        }
> +    }
> +
> +    memcpy(m, &n, sizeof(n));
> +
> +    return 0;
> +}
> +
> +static int update_model1_to_5(PixelModel3 *m, unsigned val)
> +{
> +    PixelModel3 n = {0};
> +    int i, size, freqs;
> +    unsigned a;
> +
> +    size = m->size;
> +    n.size = size;
> +    for (i = 0; i < size; i++) {
> +        n.symbols[i] = m->symbols[i];
> +    }
>

Same.



> +    AV_QSORT(n.symbols, size, uint8_t, cmpbytes);
> +    size = n.size;
> +    for (i = 0; i < size; i++) {
> +        if (val == n.symbols[i]) {
> +            n.freqs[i] = 100;
> +            n.maxpos = i;
> +        } else {
> +            n.freqs[i] = 50;
> +        }
> +    }
> +    a = 256 - size;
> +    for (i = 0; i < size; i++, a += freqs)
> +        freqs = n.freqs[i];
> +    n.type = 5;
> +    n.cntsum = a;
> +
> +    memcpy(m, &n, sizeof(n));
> +
> +    return 0;
> +}
> +
> +static int decode_static1(PixelModel3 *m, unsigned val)
> +{
> +    unsigned size;
> +
> +    size = m->size;
> +    for (int i = 0; i < size; i++) {
> +        if (val == m->symbols[i]) {
> +            if (size <= 4)
> +                return update_model1_to_4(m, val);
> +            else
> +                return update_model1_to_5(m, val);
> +        }
> +    }
> +
> +    if (size >= 14)
> +        return update_model1_to_2(m, val);
> +
> +    m->symbols[size] = val;
> +    m->size++;
> +    return 0;
> +}
> +
> +static int update_model2_to_6(PixelModel3 *m, uint8_t value, int a4)
> +{
> +    PixelModel3 n = {0};
> +    int c, d, e, f, g, q;
> +
> +    n.type = 6;
> +    n.length = a4;
> +
> +    memset(n.symbols, 1u, a4);
> +
> +    c = m->size;
> +    d = 256 - c + (64 * c + 64);
> +    for (e = 0; d <= 2048; e++) {
> +        d <<= 1;
> +    }
>

Same.



> +
> +    g = q = 0;
> +    AV_QSORT(m->symbols, c, uint8_t, cmpbytes);
> +    for (f = d = 0; f < c; f++) {
> +        int p = f;
> +        int k = m->symbols[p];
> +        int l;
> +        g = g + (k - q);
> +
> +        if (k == value) {
> +            d = p;
> +            q = 128;
> +        } else {
> +            q = 64;
> +        }
> +        l = q << e;
> +        n.freqs[2 * p] = l;
> +        n.freqs[2 * p + 1] = g << e;
> +        n.symbols[p] = k;
> +        n.cnts[p] = l - (l >> 1);
> +        g += q;
> +        q = k + 1;
> +    }
> +    n.size = c;
> +    n.fshift = e;
> +    calc_sum(&n);
> +
> +    if (d > 0) {
> +        c = n.freqs[0];
> +        e = n.freqs[1];
> +        g = n.freqs[2 * d + 1];
> +        n.freqs[0] = n.freqs[2 * d];
> +        n.freqs[1] = g;
> +        n.freqs[2 * d] = c;
> +        n.freqs[2 * d + 1] = e;
> +        FFSWAP(uint16_t, n.cnts[0], n.cnts[d]);
> +        FFSWAP(uint8_t, n.symbols[0], n.symbols[d]);
> +    }
> +
> +    memcpy(m, &n, sizeof(n));
> +
> +    return 0;
> +}
> +
> +static int update_model2_to_3(PixelModel3 *m, unsigned val)
> +{
> +    PixelModel3 n = {0};
> +    unsigned size;
> +
> +    n.type = 3;
> +    n.size = m->size + 1;
> +
> +    size = m->size;
> +    for (int i = 0; i < size; i++)
> +        n.symbols[i] = m->symbols[i];
> +    n.symbols[size] = val;
> +
> +    memcpy(m, &n, sizeof(n));
> +
> +    return 0;
> +}
> +
> +static int decode_static2(PixelModel3 *m, unsigned val)
> +{
> +    unsigned size;
> +
> +    size = m->size;
> +    for (int i = 0; i < size; i++) {
> +        if (val == m->symbols[i]) {
> +            int a;
> +
> +            if (m->size <= 32)
> +                a = 32;
> +            else
> +                a = 64;
> +            return update_model2_to_6(m, val, a);
> +        }
> +    }
> +
> +    if (size >= 64)
> +        return update_model2_to_3(m, val);
> +
> +    m->symbols[size] = val;
> +    m->size++;
> +
> +    return 0;
> +}
> +
> +static int update_model3_to_7(PixelModel3 *m, uint8_t value)
> +{
> +    PixelModel3 n = {0};
> +    int c, d, e, f, g, q;
> +
> +    n.type = 7;
> +
> +    for (c = 0; c < 256; c++) {
> +        d = c;
> +        n.freqs[d] = 1;
> +        n.cnts[d] = 1;
> +    }
> +
> +    for (c = m->size, d = (4096 - (256 - c)) / (c + 1) | 0, e = d - (d >>
> 1), g = 0; g < c;) {
> +        q = g++;
> +        q = m->symbols[q];
> +        n.freqs[q] = d;
> +        n.cnts[q] = e;
> +    }
> +    n.freqs[value] += d;
> +    n.cnts[value] += 16;
> +    for (d = c = n.cntsum = 0; 256 > d; d++) {
> +        e = d;
> +        n.cntsum += n.cnts[e];
> +        n.freqs1[e] = c;
> +        for (g = n.freqs[e], q = c + 128 - 1 >> 7, f = (c + g - 1 >> 7) +
> 1; q < f; q++) {
> +            n.dectab[q] = e;
> +        }
> +        c += g;
> +    }
> +
> +    memcpy(m, &n, sizeof(n));
> +
> +    return 0;
> +}
> +
> +static int decode_static3(PixelModel3 *m, unsigned val)
> +{
> +    unsigned size = m->size;
> +
> +    for (int i = 0; i < size; i++) {
> +        if (val == m->symbols[i])
> +            return update_model3_to_7(m, val);
> +    }
> +
> +    if (size >= 256)
> +        return 0;
> +
> +    m->symbols[size] = val;
> +    m->size++;
> +    return 0;
> +}
> +
> +static void sync_code3(GetByteContext *gb, RangeCoder *rc)
> +{
> +    rc->code1++;
> +    if (rc->code1 == 0x20000) {
> +        rc->code = bytestream2_get_le32(gb);
> +        rc->code1 = 0;
> +    }
> +}
> +
> +static int decode_value3(SCPRContext *s, unsigned max, uint32_t *cntsum,
> +                         uint16_t *freqs1, uint16_t *freqs2,
> +                         uint16_t *cnts, uint8_t *dectable,
> +                         unsigned *value)
> +{
> +    GetByteContext *gb = &s->gb;
> +    RangeCoder *rc = &s->rc;
> +    unsigned r, y, a, b, e, g, q;
> +
> +    r = dectable[(rc->code & 0xFFFu) >> 7];
> +    if (r < max) {
> +        while (freqs2[r + 1] <= (rc->code & 0xFFF)) {
> +            if (++r >= max)
> +                break;
> +        }
> +    }
> +
> +    cnts[r] += 16;
> +    a = freqs1[r];
> +    b = freqs2[r];
> +    *cntsum += 16;
> +    if (*cntsum + 16 > 4096) {
> +        *cntsum = 0;
> +        for (int c = 0, i = 0; i < max + 1; i++) {
> +            e = cnts[i];
> +            freqs2[i] = c;
> +            freqs1[i] = e;
> +            g = (c + 127) >> 7;
> +            c += e;
> +            q = ((c - 1) >> 7) + 1;
> +            if (q > g) {
> +                for (int j = 0; j < q - g; j++)
> +                    dectable[j + g] = i;
> +            }
> +            y = e - (e >> 1);
> +            cnts[i] = y;
> +            *cntsum += y;
> +        }
> +    }
> +
> +    decode3(gb, rc, a, b);
> +    sync_code3(gb, rc);
> +
> +    *value = r;
> +
> +    return 0;
> +}
> +
> +static void calc_sum5(PixelModel3 *m)
> +{
> +    int a, b, c;
> +
> +    for (a = 256 - m->size, b = 0, c = m->size; b < c; b++) {
> +        a += m->freqs[b];
> +    }
>

Same.


+    m->cntsum = a;
> +}
> +
> +static int update_model4_to_5(PixelModel3 *m, unsigned value)
> +{
> +    PixelModel3 n = {0};
> +    int c, d, e, g, totfr;
> +
> +    n.type = 5;
> +
> +    for (c = 0, d = m->size, e = 0; c < d && m->symbols[c] < value; c++) {
> +        n.symbols[c] = m->symbols[c];
> +        e += n.freqs[c] = m->freqs[c];
> +    }
> +
> +    g = c;
> +    n.symbols[g] = value;
> +    e += n.freqs[g] = 50;
> +    for (++g; c < d;) {
> +        n.symbols[g] = m->symbols[c];
> +        e += n.freqs[g] = m->freqs[c];
> +        ++c;
> +        ++g;
> +    }
>

This is a really weird loop. Any chance of simplifying it?


+    n.size = d + 1;
> +    if (e > 4096)
> +        rescale(&n, &totfr);
> +
> +    calc_sum5(&n);
> +
> +    memcpy(m, &n, sizeof(n));
> +
> +    return 0;
> +}
> +
> +static signed int decode_unit3(SCPRContext *s, PixelModel3 *m, unsigned
> code, unsigned *value)
> +{
> +    PixelModel3 n = {0};
> +    GetByteContext *gb = &s->gb;
> +    RangeCoder *rc = &s->rc;
> +    uint16_t a = 0, b = 0;
> +    uint32_t param;
> +    int type;
> +
> +    type = m->type;
> +    switch (type) {
> +    case 0:
> +        *value = bytestream2_get_byte(&s->gb);
> +        m->type = 1;
> +        m->size = 1;
> +        m->symbols[0] = *value;
> +        sync_code3(gb, rc);
> +        break;
> +    case 1:
> +        *value = bytestream2_get_byte(&s->gb);
> +        decode_static1(m, *value);
> +        sync_code3(gb, rc);
> +        break;
> +    case 2:
> +        *value = bytestream2_get_byte(&s->gb);
> +        decode_static2(m, *value);
> +        sync_code3(gb, rc);
> +        break;
> +    case 3:
> +        *value = bytestream2_get_byte(&s->gb);
> +        decode_static3(m, *value);
> +        sync_code3(gb, rc);
> +        break;
> +    case 4:
> +        param = m->freqs[0] + m->freqs[1] + m->freqs[2] + m->freqs[3] +
> 256 - m->size;
> +        if (!decode_adaptive45(m, code, value, &a, &b, &param, 4)) {
> +            update_model4_to_5(m, *value);
> +        }
> +        decode3(gb, rc, a, b);
> +        sync_code3(gb, rc);
> +        break;
> +    case 5:
> +        if (!decode_adaptive45(m, code, value, &a, &b, &m->cntsum, 16)) {
> +            update_model5_to_6(&n, m, *value);
> +        }
> +        decode3(gb, rc, a, b);
> +        sync_code3(gb, rc);
> +        break;
> +    case 6:
> +        if (!decode_adaptive6(m, code, value, &a, &b)) {
> +            update_model6_to_7(&n, m);
> +        }
> +        decode3(gb, rc, a, b);
> +        sync_code3(gb, rc);
> +        break;
> +    case 7:
> +        return decode_value3(s, 255, &m->cntsum,
> +                            m->freqs, m->freqs1,
> +                            m->cnts, m->dectab, value);
> +    }
> +    return 0;
> +}
> +
> +static int decode_units3(SCPRContext * s, unsigned *red,
> +                         unsigned *green, unsigned *blue,
> +                         int *cx, int *cx1)
> +{
> +    RangeCoder *rc = &s->rc;
> +
> +    decode_unit3(s, &s->pixel_model3[0][*cx + *cx1], rc->code & 0xFFF,
> red);
> +
> +    *cx1 = (*cx << 6) & 0xFC0;
> +    *cx = *red >> 2;
> +
> +    decode_unit3(s, &s->pixel_model3[1][*cx + *cx1], rc->code & 0xFFF,
> green);
> +
> +    *cx1 = (*cx << 6) & 0xFC0;
> +    *cx = *green >> 2;
> +
> +    decode_unit3(s, &s->pixel_model3[2][*cx + *cx1], rc->code & 0xFFF,
> blue);
> +
> +    *cx1 = (*cx << 6) & 0xFC0;
> +    *cx = *blue >> 2;
> +
> +    return 0;
> +}
> +
> +static void init_rangecoder3(RangeCoder *rc, GetByteContext *gb)
> +{
> +    rc->code  = bytestream2_get_le32(gb);
> +    rc->code1 = 0;
> +}
> +
> +static int decode_run_i(AVCodecContext *avctx, unsigned ptype, int run,
> +                        int *x, int *y, unsigned clr, uint32_t *dst,
> +                        int linesize, unsigned *lx, unsigned *ly,
> +                        unsigned backstep, int off, int *cx, int *cx1)
> +{
> +    unsigned r, g, b;
> +    int z;
> +
> +    switch (ptype) {
> +    case 0:
> +        while (run-- > 0) {
> +            if (*y >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            dst[*y * linesize + *x] = clr;
> +            *lx = *x;
> +            *ly = *y;
> +            (*x)++;
> +            if (*x >= avctx->width) {
> +                *x = 0;
> +                (*y)++;
> +            }
> +        }
> +        break;
> +    case 1:
> +        while (run-- > 0) {
> +            if (*y >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            dst[*y * linesize + *x] = dst[*ly * linesize + *lx];
> +            *lx = *x;
> +            *ly = *y;
> +            (*x)++;
> +            if (*x >= avctx->width) {
> +                *x = 0;
> +                (*y)++;
> +            }
> +        }
> +        clr = dst[*ly * linesize + *lx];
> +        break;
> +    case 2:
> +        while (run-- > 0) {
> +            if (*y < 1 || *y >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            clr = dst[*y * linesize + *x + off + 1];
> +            dst[*y * linesize + *x] = clr;
> +            *lx = *x;
> +            *ly = *y;
> +            (*x)++;
> +            if (*x >= avctx->width) {
> +                *x = 0;
> +                (*y)++;
> +            }
> +        }
> +        break;
> +    case 4:
> +        while (run-- > 0) {
> +            uint8_t *odst = (uint8_t *)dst;
> +
> +            if (*y < 1 || *y >= avctx->height ||
> +                (*y == 1 && *x == 0))
> +                return AVERROR_INVALIDDATA;
> +
> +            if (*x == 0) {
> +                z = backstep;
> +            } else {
> +                z = 0;
> +            }
> +
> +            r = odst[(*ly * linesize + *lx) * 4] +
> +                odst[((*y * linesize + *x) + off) * 4 + 4] -
> +                odst[((*y * linesize + *x) + off - z) * 4];
> +            g = odst[(*ly * linesize + *lx) * 4 + 1] +
> +                odst[((*y * linesize + *x) + off) * 4 + 5] -
> +                odst[((*y * linesize + *x) + off - z) * 4 + 1];
> +            b = odst[(*ly * linesize + *lx) * 4 + 2] +
> +                odst[((*y * linesize + *x) + off) * 4 + 6] -
> +                odst[((*y * linesize + *x) + off - z) * 4 + 2];
> +            clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
> +            dst[*y * linesize + *x] = clr;
> +            *lx = *x;
> +            *ly = *y;
> +            (*x)++;
> +            if (*x >= avctx->width) {
> +                *x = 0;
> +                (*y)++;
> +            }
> +        }
> +        break;
> +    case 5:
> +        while (run-- > 0) {
> +            if (*y < 1 || *y >= avctx->height ||
> +                (*y == 1 && *x == 0))
> +                return AVERROR_INVALIDDATA;
> +
> +            if (*x == 0) {
> +                z = backstep;
> +            } else {
> +                z = 0;
> +            }
> +
> +            clr = dst[*y * linesize + *x + off - z];
> +            dst[*y * linesize + *x] = clr;
> +            *lx = *x;
> +            *ly = *y;
> +            (*x)++;
> +            if (*x >= avctx->width) {
> +                *x = 0;
> +                (*y)++;
> +            }
> +        }
> +        break;
> +    }
> +
> +    if (avctx->bits_per_coded_sample == 16) {
> +        *cx1 = (clr & 0x3F00) >> 2;
> +        *cx = (clr & 0x3FFFFF) >> 16;
> +    } else {
> +        *cx1 = (clr & 0xFC00) >> 4;
> +        *cx = (clr & 0xFFFFFF) >> 18;
> +    }
> +
> +    return 0;
> +}
> +
> +static int decompress_i3(AVCodecContext *avctx, uint32_t *dst, int
> linesize)
> +{
> +    SCPRContext *s = avctx->priv_data;
> +    GetByteContext *gb = &s->gb;
> +    RangeCoder *rc = &s->rc;
> +    int cx = 0, cx1 = 0, k = 0;
> +    int run, off, y = 0, x = 0, ret;
> +    unsigned backstep = linesize - avctx->width;
> +    unsigned clr = 0, lx, ly, ptype, r, g, b;
> +
> +    bytestream2_skip(gb, 1);
> +    init_rangecoder3(rc, gb);
> +    reinit_tables3(s);
>
> -typedef struct RangeCoder {
> -    unsigned   code;
> -    unsigned   range;
> -    unsigned   code1;
> -} RangeCoder;
> +    while (k < avctx->width + 1) {
> +        decode_units3(s, &r, &g, &b, &cx, &cx1);
> +        ret = decode_value3(s, 255, &s->run_model3[0].cntsum,
> +                            s->run_model3[0].freqs[0],
> +                            s->run_model3[0].freqs[1],
> +                            s->run_model3[0].cnts,
> +                            s->run_model3[0].dectab, &run);
> +        if (ret < 0)
> +            return ret;
> +        if (run <= 0)
> +            return AVERROR_INVALIDDATA;
>
> -typedef struct PixelModel {
> -    unsigned    freq[256];
> -    unsigned    lookup[16];
> -    unsigned    total_freq;
> -} PixelModel;
> +        clr = (b << 16) + (g << 8) + r;
> +        k += run;
> +        while (run-- > 0) {
> +            if (y >= avctx->height)
> +                return AVERROR_INVALIDDATA;
>
> -typedef struct SCPRContext {
> -    AVFrame        *last_frame;
> -    AVFrame        *current_frame;
> -    GetByteContext  gb;
> -    RangeCoder      rc;
> -    PixelModel      pixel_model[3][4096];
> -    unsigned        op_model[6][7];
> -    unsigned        run_model[6][257];
> -    unsigned        range_model[257];
> -    unsigned        count_model[257];
> -    unsigned        fill_model[6];
> -    unsigned        sxy_model[4][17];
> -    unsigned        mv_model[2][513];
> -    unsigned        nbx, nby;
> -    unsigned        nbcount;
> -    unsigned       *blocks;
> -    unsigned        cbits;
> -    int             cxshift;
> +            dst[y * linesize + x] = clr;
> +            lx = x;
> +            ly = y;
> +            x++;
> +            if (x >= avctx->width) {
> +                x = 0;
> +                y++;
> +            }
> +        }
> +    }
> +    off = -linesize - 1;
> +    ptype = 0;
>
> -    int           (*get_freq)(RangeCoder *rc, unsigned total_freq,
> unsigned *freq);
> -    int           (*decode)(GetByteContext *gb, RangeCoder *rc, unsigned
> cumFreq, unsigned freq, unsigned total_freq);
> -} SCPRContext;
> +    while (x < avctx->width && y < avctx->height) {
> +        ret = decode_value3(s, 5, &s->op_model3[ptype].cntsum,
> +                            s->op_model3[ptype].freqs[0],
> +                            s->op_model3[ptype].freqs[1],
> +                            s->op_model3[ptype].cnts,
> +                            s->op_model3[ptype].dectab, &ptype);
> +        if (ret < 0)
> +            return ret;
> +        if (ptype == 0) {
> +            decode_units3(s, &r, &g, &b, &cx, &cx1);
> +            clr = (b << 16) + (g << 8) + r;
> +        }
> +        if (ptype > 5)
> +            return AVERROR_INVALIDDATA;
> +        ret = decode_value3(s, 255, &s->run_model3[ptype].cntsum,
> +                            s->run_model3[ptype].freqs[0],
> +                            s->run_model3[ptype].freqs[1],
> +                            s->run_model3[ptype].cnts,
> +                            s->run_model3[ptype].dectab, &run);
> +        if (ret < 0)
> +            return ret;
> +        if (run <= 0)
> +            return AVERROR_INVALIDDATA;
> +
> +        ret = decode_run_i(avctx, ptype, run, &x, &y, clr,
> +                           dst, linesize, &lx, &ly,
> +                           backstep, off, &cx, &cx1);
> +        if (run < 0)
> +            return ret;
> +    }
> +
> +    return 0;
> +}
> +
> +static int decode_run_p(AVCodecContext *avctx, unsigned ptype, int run,
> +                        int x, int y, unsigned clr,
> +                        uint32_t *dst, uint32_t *prev,
> +                        int linesize, int plinesize,
> +                        unsigned *bx, unsigned *by,
> +                        unsigned backstep, int sx1, int sx2,
> +                        int *cx, int *cx1)
> +{
> +    unsigned r, g, b;
> +    int z;
> +
> +    switch (ptype) {
> +    case 0:
> +        while (run-- > 0) {
> +            if (*by >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            dst[*by * linesize + *bx] = clr;
> +            (*bx)++;
> +            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
> +                *bx = x * 16 + sx1;
> +                (*by)++;
> +            }
> +        }
> +        break;
> +    case 1:
> +        while (run-- > 0) {
> +            if (*bx == 0) {
> +                if (*by < 1)
> +                    return AVERROR_INVALIDDATA;
> +                z = backstep;
> +            } else {
> +                z = 0;
> +            }
> +
> +            if (*by >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            clr = dst[*by * linesize + *bx - 1 - z];
> +            dst[*by * linesize + *bx] = clr;
> +            (*bx)++;
> +            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
> +                *bx = x * 16 + sx1;
> +                (*by)++;
> +            }
> +        }
> +        break;
> +    case 2:
> +        while (run-- > 0) {
> +            if (*by < 1 || *by >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            clr = dst[(*by - 1) * linesize + *bx];
> +            dst[*by * linesize + *bx] = clr;
> +            (*bx)++;
> +            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
> +                *bx = x * 16 + sx1;
> +                (*by)++;
> +            }
> +        }
> +        break;
> +    case 3:
> +        while (run-- > 0) {
> +            if (*by >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            clr = prev[*by * plinesize + *bx];
> +            dst[*by * linesize + *bx] = clr;
> +            (*bx)++;
> +            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
> +                *bx = x * 16 + sx1;
> +                (*by)++;
> +            }
> +        }
> +        break;
> +    case 4:
> +        while (run-- > 0) {
> +            uint8_t *odst = (uint8_t *)dst;
> +
> +            if (*by < 1 || *by >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            if (*bx == 0) {
> +                if (*by < 2)
> +                    return AVERROR_INVALIDDATA;
> +                z = backstep;
> +            } else {
> +                z = 0;
> +            }
> +
> +            r = odst[((*by - 1) * linesize + *bx) * 4] +
> +                odst[(*by * linesize + *bx - 1 - z) * 4] -
> +                odst[((*by - 1) * linesize + *bx - 1 - z) * 4];
> +            g = odst[((*by - 1) * linesize + *bx) * 4 + 1] +
> +                odst[(*by * linesize + *bx - 1 - z) * 4 + 1] -
> +                odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 1];
> +            b = odst[((*by - 1) * linesize + *bx) * 4 + 2] +
> +                odst[(*by * linesize + *bx - 1 - z) * 4 + 2] -
> +                odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 2];
> +            clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
> +            dst[*by * linesize + *bx] = clr;
> +            (*bx)++;
> +            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
> +                *bx = x * 16 + sx1;
> +                (*by)++;
> +            }
> +        }
> +        break;
> +    case 5:
> +        while (run-- > 0) {
> +            if (*by < 1 || *by >= avctx->height)
> +                return AVERROR_INVALIDDATA;
> +
> +            if (*bx == 0) {
> +                if (*by < 2)
> +                    return AVERROR_INVALIDDATA;
> +                z = backstep;
> +            } else {
> +                z = 0;
> +            }
> +
> +            clr = dst[(*by - 1) * linesize + *bx - 1 - z];
> +            dst[*by * linesize + *bx] = clr;
> +            (*bx)++;
> +            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
> +                *bx = x * 16 + sx1;
> +                (*by)++;
> +            }
> +        }
> +        break;
> +    }
> +
> +    if (avctx->bits_per_coded_sample == 16) {
> +        *cx1 = (clr & 0x3F00) >> 2;
> +        *cx = (clr & 0x3FFFFF) >> 16;
> +    } else {
> +        *cx1 = (clr & 0xFC00) >> 4;
> +        *cx = (clr & 0xFFFFFF) >> 18;
> +    }
> +
> +    return 0;
> +}
> +
> +static int decompress_p3(AVCodecContext *avctx,
> +                         uint32_t *dst, int linesize,
> +                         uint32_t *prev, int plinesize)
> +{
> +    SCPRContext *s = avctx->priv_data;
> +    GetByteContext *gb = &s->gb;
> +    int ret, temp, min, max, x, y, cx = 0, cx1 = 0;
> +    int backstep = linesize - avctx->width;
> +    int mvx = 0, mvy = 0;
> +
> +    if (bytestream2_get_byte(gb) == 0)
> +        return 0;
> +    init_rangecoder3(&s->rc, gb);
> +
> +    ret  = decode_value3(s, 255, &s->range_model3.cntsum,
> +                         s->range_model3.freqs[0],
> +                         s->range_model3.freqs[1],
> +                         s->range_model3.cnts,
> +                         s->range_model3.dectab, &min);
> +    ret |= decode_value3(s, 255, &s->range_model3.cntsum,
> +                         s->range_model3.freqs[0],
> +                         s->range_model3.freqs[1],
> +                         s->range_model3.cnts,
> +                         s->range_model3.dectab, &temp);
> +    min += temp << 8;
> +    ret |= decode_value3(s, 255, &s->range_model3.cntsum,
> +                         s->range_model3.freqs[0],
> +                         s->range_model3.freqs[1],
> +                         s->range_model3.cnts,
> +                         s->range_model3.dectab, &max);
> +    ret |= decode_value3(s, 255, &s->range_model3.cntsum,
> +                         s->range_model3.freqs[0],
> +                         s->range_model3.freqs[1],
> +                         s->range_model3.cnts,
> +                         s->range_model3.dectab, &temp);
> +    if (ret < 0)
> +        return ret;
> +
> +    max += temp << 8;
> +    memset(s->blocks, 0, sizeof(*s->blocks) * s->nbcount);
> +
> +    while (min <= max) {
> +        int fill, count;
> +
> +        ret  = decode_value3(s, 4, &s->fill_model3.cntsum,
> +                             s->fill_model3.freqs[0],
> +                             s->fill_model3.freqs[1],
> +                             s->fill_model3.cnts,
> +                             s->fill_model3.dectab, &fill);
> +        ret |= decode_value3(s, 255, &s->count_model3.cntsum,
> +                             s->count_model3.freqs[0],
> +                             s->count_model3.freqs[1],
> +                             s->count_model3.cnts,
> +                             s->count_model3.dectab, &count);
> +        if (ret < 0)
> +            return ret;
> +
> +        while (min < s->nbcount && count-- > 0) {
> +            s->blocks[min++] = fill;
> +        }
> +    }
> +
> +    for (y = 0; y < s->nby; y++) {
> +        for (x = 0; x < s->nbx; x++) {
> +            int sy1 = 0, sy2 = 16, sx1 = 0, sx2 = 16;
> +
> +            if (s->blocks[y * s->nbx + x] == 0)
> +                continue;
> +
> +            if (((s->blocks[y * s->nbx + x] + 1) & 1) > 0) {
> +                ret  = decode_value3(s, 15, &s->sxy_model3[0].cntsum,
> +                                     s->sxy_model3[0].freqs[0],
> +                                     s->sxy_model3[0].freqs[1],
> +                                     s->sxy_model3[0].cnts,
> +                                     s->sxy_model3[0].dectab, &sx1);
> +                ret |= decode_value3(s, 15, &s->sxy_model3[1].cntsum,
> +                                     s->sxy_model3[1].freqs[0],
> +                                     s->sxy_model3[1].freqs[1],
> +                                     s->sxy_model3[1].cnts,
> +                                     s->sxy_model3[1].dectab, &sy1);
> +                ret |= decode_value3(s, 15, &s->sxy_model3[2].cntsum,
> +                                     s->sxy_model3[2].freqs[0],
> +                                     s->sxy_model3[2].freqs[1],
> +                                     s->sxy_model3[2].cnts,
> +                                     s->sxy_model3[2].dectab, &sx2);
> +                ret |= decode_value3(s, 15, &s->sxy_model3[3].cntsum,
> +                                     s->sxy_model3[3].freqs[0],
> +                                     s->sxy_model3[3].freqs[1],
> +                                     s->sxy_model3[3].cnts,
> +                                     s->sxy_model3[3].dectab, &sy2);
> +                if (ret < 0)
> +                    return ret;
> +
> +                sx2++;
> +                sy2++;
> +            }
> +            if (((s->blocks[y * s->nbx + x] + 3) & 2) > 0) {
> +                int i, a, b, c, j, by = y * 16, bx = x * 16;
> +                unsigned X;
> +
> +                a = s->rc.code & 0xFFF;
> +                c = 1;
> +
> +                if (a < 0x800)
> +                    c = 0;
> +                b = 2048;
> +                if (!c)
> +                    b = 0;
> +
> +                X = a + ((s->rc.code >> 1) & 0xFFFFF800) - b;
> +                while (X < 0x800000 && bytestream2_get_bytes_left(gb) >
> 0) {
> +                    X = bytestream2_get_byte(gb) | (X << 8);
> +                }
> +                s->rc.code = X;
> +
> +                sync_code3(gb, &s->rc);
> +
> +                if (!c) {
> +                    ret  = decode_value3(s, 511, &s->mv_model3[0].cntsum,
> +                                         s->mv_model3[0].freqs[0],
> +                                         s->mv_model3[0].freqs[1],
> +                                         s->mv_model3[0].cnts,
> +                                         s->mv_model3[0].dectab, &mvx);
> +                    ret |= decode_value3(s, 511, &s->mv_model3[1].cntsum,
> +                                         s->mv_model3[1].freqs[0],
> +                                         s->mv_model3[1].freqs[1],
> +                                         s->mv_model3[1].cnts,
> +                                         s->mv_model3[1].dectab, &mvy);
> +                    if (ret < 0)
> +                        return ret;
> +
> +                    mvx -= 256;
> +                    mvy -= 256;
> +                }
> +
> +                if (by + mvy + sy1 < 0 || bx + mvx + sx1 < 0 ||
> +                    by + mvy + sy1 >= avctx->height || bx + mvx + sx1 >=
> avctx->width)
> +                    return AVERROR_INVALIDDATA;
> +
> +                for (i = 0; i < sy2 - sy1 && (by + sy1 + i) <
> avctx->height && (by + mvy + sy1 + i) < avctx->height; i++) {
> +                    for (j = 0; j < sx2 - sx1 && (bx + sx1 + j) <
> avctx->width && (bx + mvx + sx1 + j) < avctx->width; j++) {
> +                        dst[(by + i + sy1) * linesize + bx + sx1 + j] =
> prev[(by + mvy + sy1 + i) * plinesize + bx + sx1 + mvx + j];
> +                    }
> +                }
> +            } else {
> +                int run, bx = x * 16 + sx1, by = y * 16 + sy1;
> +                unsigned clr, ptype = 0, r, g, b;
> +
> +                for (; by < y * 16 + sy2 && by < avctx->height;) {
> +                    ret = decode_value3(s, 5, &s->op_model3[ptype].cntsum,
> +                                        s->op_model3[ptype].freqs[0],
> +                                        s->op_model3[ptype].freqs[1],
> +                                        s->op_model3[ptype].cnts,
> +                                        s->op_model3[ptype].dectab,
> &ptype);
> +                    if (ret < 0)
> +                        return ret;
> +                    if (ptype == 0) {
> +                        ret = decode_units3(s, &r, &g, &b, &cx, &cx1);
> +                        if (ret < 0)
> +                            return ret;
> +
> +                        clr = (b << 16) + (g << 8) + r;
> +                    }
> +                    if (ptype > 5)
> +                        return AVERROR_INVALIDDATA;
> +                    ret = decode_value3(s, 255,
> &s->run_model3[ptype].cntsum,
> +                                        s->run_model3[ptype].freqs[0],
> +                                        s->run_model3[ptype].freqs[1],
> +                                        s->run_model3[ptype].cnts,
> +                                        s->run_model3[ptype].dectab,
> &run);
> +                    if (ret < 0)
> +                        return ret;
> +                    if (run <= 0)
> +                        return AVERROR_INVALIDDATA;
> +
> +                    ret = decode_run_p(avctx, ptype, run, x, y, clr,
> +                                       dst, prev, linesize, plinesize,
> &bx, &by,
> +                                       backstep, sx1, sx2, &cx, &cx1);
> +                    if (ret < 0)
> +                        return ret;
> +                }
> +            }
> +        }
> +    }
> +
> +    return 0;
> +}
>
>  static void init_rangecoder(RangeCoder *rc, GetByteContext *gb)
>  {
> @@ -329,9 +1820,9 @@ static int decompress_i(AVCodecContext *avctx,
> uint32_t *dst, int linesize)
>  {
>      SCPRContext *s = avctx->priv_data;
>      GetByteContext *gb = &s->gb;
> -    int cx = 0, cx1 = 0, k = 0, clr = 0;
> -    int run, off, y = 0, x = 0, z, ret;
> -    unsigned r, g, b, backstep = linesize - avctx->width;
> +    int cx = 0, cx1 = 0, k = 0;
> +    int run, off, y = 0, x = 0, ret;
> +    unsigned clr = 0, r, g, b, backstep = linesize - avctx->width;
>      unsigned lx, ly, ptype;
>
>      reinit_tables(s);
> @@ -387,120 +1878,11 @@ static int decompress_i(AVCodecContext *avctx,
> uint32_t *dst, int linesize)
>          if (run <= 0)
>              return AVERROR_INVALIDDATA;
>
> -        switch (ptype) {
> -        case 0:
> -            while (run-- > 0) {
> -                if (y >= avctx->height)
> -                    return AVERROR_INVALIDDATA;
> -
> -                dst[y * linesize + x] = clr;
> -                lx = x;
> -                ly = y;
> -                x++;
> -                if (x >= avctx->width) {
> -                    x = 0;
> -                    y++;
> -                }
> -            }
> -            break;
> -        case 1:
> -            while (run-- > 0) {
> -                if (y >= avctx->height)
> -                    return AVERROR_INVALIDDATA;
> -
> -                dst[y * linesize + x] = dst[ly * linesize + lx];
> -                lx = x;
> -                ly = y;
> -                x++;
> -                if (x >= avctx->width) {
> -                    x = 0;
> -                    y++;
> -                }
> -            }
> -            clr = dst[ly * linesize + lx];
> -            break;
> -        case 2:
> -            while (run-- > 0) {
> -                if (y < 1 || y >= avctx->height)
> -                    return AVERROR_INVALIDDATA;
> -
> -                clr = dst[y * linesize + x + off + 1];
> -                dst[y * linesize + x] = clr;
> -                lx = x;
> -                ly = y;
> -                x++;
> -                if (x >= avctx->width) {
> -                    x = 0;
> -                    y++;
> -                }
> -            }
> -            break;
> -        case 4:
> -            while (run-- > 0) {
> -                uint8_t *odst = (uint8_t *)dst;
> -
> -                if (y < 1 || y >= avctx->height ||
> -                    (y == 1 && x == 0))
> -                    return AVERROR_INVALIDDATA;
> -
> -                if (x == 0) {
> -                    z = backstep;
> -                } else {
> -                    z = 0;
> -                }
> -
> -                r = odst[(ly * linesize + lx) * 4] +
> -                    odst[((y * linesize + x) + off) * 4 + 4] -
> -                    odst[((y * linesize + x) + off - z) * 4];
> -                g = odst[(ly * linesize + lx) * 4 + 1] +
> -                    odst[((y * linesize + x) + off) * 4 + 5] -
> -                    odst[((y * linesize + x) + off - z) * 4 + 1];
> -                b = odst[(ly * linesize + lx) * 4 + 2] +
> -                    odst[((y * linesize + x) + off) * 4 + 6] -
> -                    odst[((y * linesize + x) + off - z) * 4 + 2];
> -                clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
> -                dst[y * linesize + x] = clr;
> -                lx = x;
> -                ly = y;
> -                x++;
> -                if (x >= avctx->width) {
> -                    x = 0;
> -                    y++;
> -                }
> -            }
> -            break;
> -        case 5:
> -            while (run-- > 0) {
> -                if (y < 1 || y >= avctx->height ||
> -                    (y == 1 && x == 0))
> -                    return AVERROR_INVALIDDATA;
> -
> -                if (x == 0) {
> -                    z = backstep;
> -                } else {
> -                    z = 0;
> -                }
> -
> -                clr = dst[y * linesize + x + off - z];
> -                dst[y * linesize + x] = clr;
> -                lx = x;
> -                ly = y;
> -                x++;
> -                if (x >= avctx->width) {
> -                    x = 0;
> -                    y++;
> -                }
> -            }
> -            break;
> -        }
> -
> -        if (avctx->bits_per_coded_sample == 16) {
> -            cx1 = (clr & 0x3F00) >> 2;
> -            cx = (clr & 0x3FFFFF) >> 16;
> -        } else {
> -            cx1 = (clr & 0xFC00) >> 4;
> -            cx = (clr & 0xFFFFFF) >> 18;
> -        }
> +        ret = decode_run_i(avctx, ptype, run, &x, &y, clr,
> +                           dst, linesize, &lx, &ly,
> +                           backstep, off, &cx, &cx1);
> +        if (run < 0)
> +            return ret;
>      }
>
>      return 0;
> @@ -587,7 +1969,7 @@ static int decompress_p(AVCodecContext *avctx,
>                      }
>                  }
>              } else {
> -                int run, z, bx = x * 16 + sx1, by = y * 16 + sy1;
> +                int run, bx = x * 16 + sx1, by = y * 16 + sy1;
>                  unsigned r, g, b, clr, ptype = 0;
>
>                  for (; by < y * 16 + sy2 && by < avctx->height;) {
> @@ -609,134 +1991,11 @@ static int decompress_p(AVCodecContext *avctx,
>                      if (run <= 0)
>                          return AVERROR_INVALIDDATA;
>
> -                    switch (ptype) {
> -                    case 0:
> -                        while (run-- > 0) {
> -                            if (by >= avctx->height)
> -                                return AVERROR_INVALIDDATA;
> -
> -                            dst[by * linesize + bx] = clr;
> -                            bx++;
> -                            if (bx >= x * 16 + sx2 || bx >= avctx->width)
> {
> -                                bx = x * 16 + sx1;
> -                                by++;
> -                            }
> -                        }
> -                        break;
> -                    case 1:
> -                        while (run-- > 0) {
> -                            if (bx == 0) {
> -                                if (by < 1)
> -                                    return AVERROR_INVALIDDATA;
> -                                z = backstep;
> -                            } else {
> -                                z = 0;
> -                            }
> -
> -                            if (by >= avctx->height)
> -                                return AVERROR_INVALIDDATA;
> -
> -                            clr = dst[by * linesize + bx - 1 - z];
> -                            dst[by * linesize + bx] = clr;
> -                            bx++;
> -                            if (bx >= x * 16 + sx2 || bx >= avctx->width)
> {
> -                                bx = x * 16 + sx1;
> -                                by++;
> -                            }
> -                        }
> -                        break;
> -                    case 2:
> -                        while (run-- > 0) {
> -                            if (by < 1 || by >= avctx->height)
> -                                return AVERROR_INVALIDDATA;
> -
> -                            clr = dst[(by - 1) * linesize + bx];
> -                            dst[by * linesize + bx] = clr;
> -                            bx++;
> -                            if (bx >= x * 16 + sx2 || bx >= avctx->width)
> {
> -                                bx = x * 16 + sx1;
> -                                by++;
> -                            }
> -                        }
> -                        break;
> -                    case 3:
> -                        while (run-- > 0) {
> -                            if (by >= avctx->height)
> -                                return AVERROR_INVALIDDATA;
> -
> -                            clr = prev[by * plinesize + bx];
> -                            dst[by * linesize + bx] = clr;
> -                            bx++;
> -                            if (bx >= x * 16 + sx2 || bx >= avctx->width)
> {
> -                                bx = x * 16 + sx1;
> -                                by++;
> -                            }
> -                        }
> -                        break;
> -                    case 4:
> -                        while (run-- > 0) {
> -                            uint8_t *odst = (uint8_t *)dst;
> -
> -                            if (by < 1 || by >= avctx->height)
> -                                return AVERROR_INVALIDDATA;
> -
> -                            if (bx == 0) {
> -                                if (by < 2)
> -                                    return AVERROR_INVALIDDATA;
> -                                z = backstep;
> -                            } else {
> -                                z = 0;
> -                            }
> -
> -                            r = odst[((by - 1) * linesize + bx) * 4] +
> -                                odst[(by * linesize + bx - 1 - z) * 4] -
> -                                odst[((by - 1) * linesize + bx - 1 - z) *
> 4];
> -                            g = odst[((by - 1) * linesize + bx) * 4 + 1] +
> -                                odst[(by * linesize + bx - 1 - z) * 4 +
> 1] -
> -                                odst[((by - 1) * linesize + bx - 1 - z) *
> 4 + 1];
> -                            b = odst[((by - 1) * linesize + bx) * 4 + 2] +
> -                                odst[(by * linesize + bx - 1 - z) * 4 +
> 2] -
> -                                odst[((by - 1) * linesize + bx - 1 - z) *
> 4 + 2];
> -                            clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8)
> + (r & 0xFF);
> -                            dst[by * linesize + bx] = clr;
> -                            bx++;
> -                            if (bx >= x * 16 + sx2 || bx >= avctx->width)
> {
> -                                bx = x * 16 + sx1;
> -                                by++;
> -                            }
> -                        }
> -                        break;
> -                    case 5:
> -                        while (run-- > 0) {
> -                            if (by < 1 || by >= avctx->height)
> -                                return AVERROR_INVALIDDATA;
> -
> -                            if (bx == 0) {
> -                                if (by < 2)
> -                                    return AVERROR_INVALIDDATA;
> -                                z = backstep;
> -                            } else {
> -                                z = 0;
> -                            }
> -
> -                            clr = dst[(by - 1) * linesize + bx - 1 - z];
> -                            dst[by * linesize + bx] = clr;
> -                            bx++;
> -                            if (bx >= x * 16 + sx2 || bx >= avctx->width)
> {
> -                                bx = x * 16 + sx1;
> -                                by++;
> -                            }
> -                        }
> -                        break;
> -                    }
> -
> -                    if (avctx->bits_per_coded_sample == 16) {
> -                        cx1 = (clr & 0x3F00) >> 2;
> -                        cx = (clr & 0x3FFFFF) >> 16;
> -                    } else {
> -                        cx1 = (clr & 0xFC00) >> 4;
> -                        cx = (clr & 0xFFFFFF) >> 18;
> -                    }
> +                    ret = decode_run_p(avctx, ptype, run, x, y, clr,
> +                                       dst, prev, linesize, plinesize,
> &bx, &by,
> +                                       backstep, sx1, sx2, &cx, &cx1);
> +                    if (ret < 0)
> +                        return ret;
>                  }
>              }
>          }
> @@ -766,18 +2025,26 @@ static int decode_frame(AVCodecContext *avctx, void
> *data, int *got_frame,
>      type = bytestream2_peek_byte(gb);
>
>      if (type == 2) {
> +        s->version = 1;
>          s->get_freq = get_freq0;
>          s->decode = decode0;
>          frame->key_frame = 1;
>          ret = decompress_i(avctx, (uint32_t *)s->current_frame->data[0],
>                             s->current_frame->linesize[0] / 4);
>      } else if (type == 18) {
> +        s->version = 2;
>          s->get_freq = get_freq;
>          s->decode = decode;
>          frame->key_frame = 1;
>          ret = decompress_i(avctx, (uint32_t *)s->current_frame->data[0],
>                             s->current_frame->linesize[0] / 4);
> -    } else if (type == 17) {
> +    } else if (type == 34) {
> +        frame->key_frame = 1;
> +        s->version = 3;
> +        ret = decompress_i3(avctx, (uint32_t *)s->current_frame->data[0],
> +                            s->current_frame->linesize[0] / 4);
> +        ret = 0;
> +    } else if (type == 17 || type == 33) {
>          uint32_t clr, *dst = (uint32_t *)s->current_frame->data[0];
>          int x, y;
>
> @@ -807,10 +2074,16 @@ static int decode_frame(AVCodecContext *avctx, void
> *data, int *got_frame,
>          if (ret < 0)
>              return ret;
>
> -        ret = decompress_p(avctx, (uint32_t *)s->current_frame->data[0],
> -                           s->current_frame->linesize[0] / 4,
> -                           (uint32_t *)s->last_frame->data[0],
> -                           s->last_frame->linesize[0] / 4);
> +        if (s->version == 1 || s->version == 2)
> +            ret = decompress_p(avctx, (uint32_t
> *)s->current_frame->data[0],
> +                               s->current_frame->linesize[0] / 4,
> +                               (uint32_t *)s->last_frame->data[0],
> +                               s->last_frame->linesize[0] / 4);
> +        else
> +            ret = decompress_p3(avctx, (uint32_t
> *)s->current_frame->data[0],
> +                                s->current_frame->linesize[0] / 4,
> +                                (uint32_t *)s->last_frame->data[0],
> +                                s->last_frame->linesize[0] / 4);
>      } else {
>          return AVERROR_PATCHWELCOME;
>      }
> @@ -901,6 +2174,7 @@ static av_cold int decode_close(AVCodecContext *avctx)
>      av_freep(&s->blocks);
>      av_frame_free(&s->last_frame);
>      av_frame_free(&s->current_frame);
> +    reinit_tables3(s);
>
>      return 0;
>  }
> --
> 2.17.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Patch hide | download patch | download mbox

diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c
index ee6bf21b71..4cd9e33d71 100644
--- a/libavcodec/scpr.c
+++ b/libavcodec/scpr.c
@@ -24,47 +24,1538 @@ 
 #include <stdlib.h>
 #include <string.h>
 
+#include "libavutil/qsort.h"
+
 #include "avcodec.h"
 #include "bytestream.h"
 #include "internal.h"
 
-#define TOP  0x01000000
-#define BOT    0x010000
+#define TOP  0x01000000
+#define BOT    0x010000
+
+typedef struct RangeCoder {
+    unsigned   code;
+    unsigned   range;
+    unsigned   code1;
+} RangeCoder;
+
+typedef struct PixelModel {
+    unsigned    freq[256];
+    unsigned    lookup[16];
+    unsigned    total_freq;
+} PixelModel;
+
+typedef struct PixelModel3 {
+    uint8_t    type;
+    uint8_t    length;
+    uint8_t    maxpos;
+    uint8_t    fshift;
+    uint16_t   size;
+    uint32_t   cntsum;
+    uint8_t    symbols[256];
+    uint16_t   freqs[256];
+    uint16_t   freqs1[256];
+    uint16_t   cnts[256];
+    uint8_t    dectab[32];
+} PixelModel3;
+
+typedef struct FillModel3 {
+    uint32_t   cntsum;
+    uint16_t   freqs[2][5];
+    uint16_t   cnts[5];
+    uint8_t    dectab[32];
+} FillModel3;
+
+typedef struct OpModel3 {
+    uint32_t   cntsum;
+    uint16_t   freqs[2][6];
+    uint16_t   cnts[6];
+    uint8_t    dectab[32];
+} OpModel3;
+
+typedef struct RunModel3 {
+    uint32_t   cntsum;
+    uint16_t   freqs[2][256];
+    uint16_t   cnts[256];
+    uint8_t    dectab[32];
+} RunModel3;
+
+typedef struct SxyModel3 {
+    uint32_t   cntsum;
+    uint16_t   freqs[2][16];
+    uint16_t   cnts[16];
+    uint8_t    dectab[32];
+} SxyModel3;
+
+typedef struct MVModel3 {
+    uint32_t   cntsum;
+    uint16_t   freqs[2][512];
+    uint16_t   cnts[512];
+    uint8_t    dectab[32];
+} MVModel3;
+
+typedef struct SCPRContext {
+    int             version;
+    AVFrame        *last_frame;
+    AVFrame        *current_frame;
+    GetByteContext  gb;
+    RangeCoder      rc;
+    PixelModel      pixel_model[3][4096];
+    unsigned        op_model[6][7];
+    unsigned        run_model[6][257];
+    unsigned        range_model[257];
+    unsigned        count_model[257];
+    unsigned        fill_model[6];
+    unsigned        sxy_model[4][17];
+    unsigned        mv_model[2][513];
+    unsigned        nbx, nby;
+    unsigned        nbcount;
+    unsigned       *blocks;
+    unsigned        cbits;
+    int             cxshift;
+
+    PixelModel3     pixel_model3[3][4096];
+    RunModel3       run_model3[6];
+    RunModel3       range_model3;
+    RunModel3       count_model3;
+    FillModel3      fill_model3;
+    SxyModel3       sxy_model3[4];
+    MVModel3        mv_model3[2];
+    OpModel3        op_model3[6];
+
+    int           (*get_freq)(RangeCoder *rc, unsigned total_freq, unsigned *freq);
+    int           (*decode)(GetByteContext *gb, RangeCoder *rc, unsigned cumFreq, unsigned freq, unsigned total_freq);
+} SCPRContext;
+
+static void renew_table3(unsigned nsym, uint32_t *cntsum,
+                         uint16_t *freqs, uint16_t *freqs1,
+                         uint16_t *cnts, uint8_t *dectab)
+{
+    unsigned a = 0, b = 4096 / nsym, c = b - (b >> 1);
+
+    *cntsum = c * nsym;
+
+    for (int d = 0; d < nsym; d++) {
+        freqs[d] = b;
+        freqs1[d] = a;
+        cnts[d] = c;
+        for (int q = a + 128 - 1 >> 7, f = (a + b - 1 >> 7) + 1; q < f; q++) {
+            dectab[q] = d;
+        }
+
+        a += b;
+    }
+}
+
+static void reinit_tables3(SCPRContext * s)
+{
+    for (int i = 0; i < 3; i++) {
+        for (int j = 0; j < 4096; j++) {
+            PixelModel3 *m = &s->pixel_model3[i][j];
+            m->type = 0;
+        }
+    }
+
+    for (int i = 0; i < 6; i++) {
+        renew_table3(256, &s->run_model3[i].cntsum,
+                     s->run_model3[i].freqs[0], s->run_model3[i].freqs[1],
+                     s->run_model3[i].cnts, s->run_model3[i].dectab);
+    }
+
+    renew_table3(256, &s->range_model3.cntsum,
+                 s->range_model3.freqs[0], s->range_model3.freqs[1],
+                 s->range_model3.cnts, s->range_model3.dectab);
+
+    renew_table3(5, &s->fill_model3.cntsum,
+                 s->fill_model3.freqs[0], s->fill_model3.freqs[1],
+                 s->fill_model3.cnts, s->fill_model3.dectab);
+
+    renew_table3(256, &s->count_model3.cntsum,
+                 s->count_model3.freqs[0], s->count_model3.freqs[1],
+                 s->count_model3.cnts, s->count_model3.dectab);
+
+    for (int i = 0; i < 4; i++) {
+        renew_table3(16, &s->sxy_model3[i].cntsum,
+                     s->sxy_model3[i].freqs[0], s->sxy_model3[i].freqs[1],
+                     s->sxy_model3[i].cnts, s->sxy_model3[i].dectab);
+    }
+
+    for (int i = 0; i < 2; i++) {
+        renew_table3(512, &s->mv_model3[i].cntsum,
+                     s->mv_model3[i].freqs[0], s->mv_model3[i].freqs[1],
+                     s->mv_model3[i].cnts, s->mv_model3[i].dectab);
+    }
+
+    for (int i = 0; i < 6; i++) {
+        renew_table3(6, &s->op_model3[i].cntsum,
+                     s->op_model3[i].freqs[0], s->op_model3[i].freqs[1],
+                     s->op_model3[i].cnts, s->op_model3[i].dectab);
+    }
+}
+
+static int decode3(GetByteContext *gb, RangeCoder *rc, unsigned a, unsigned b)
+{
+    unsigned x = a * (rc->code >> 12) + (rc->code & 0xFFF) - b;
+
+    while (x < 0x800000 && bytestream2_get_bytes_left(gb) > 0) {
+        x = bytestream2_get_byte(gb) | (x << 8);
+    }
+    rc->code = x;
+
+    return 0;
+}
+
+static void rescale(PixelModel3 *m, int *totfr)
+{
+    unsigned a, b, c;
+
+    for (a = 256 - m->size, b = 0, c = m->size; b < c; b++) {
+        m->freqs[b] -= m->freqs[b] >> 1;
+        a += m->freqs[b];
+    }
+
+    *totfr = a;
+}
+
+static int add_symbol(PixelModel3 *m, int index, unsigned symbol, int *totfr, int max)
+{
+    if (m->size == max)
+        return 0;
+
+    for (int c = m->size - 1; c >= index; c--) {
+        m->symbols[c + 1] = m->symbols[c];
+        m->freqs[c + 1] = m->freqs[c];
+    }
+
+    m->symbols[index] = symbol;
+    m->freqs[index] = 50;
+    m->size++;
+
+    if (m->maxpos >= index)
+        m->maxpos++;
+
+    *totfr += 50;
+    if (*totfr + 50 > 4096)
+        rescale(m, totfr);
+
+    return 1;
+}
+
+static int decode_adaptive45(PixelModel3 *m, int rccode, unsigned *value,
+                             uint16_t *a, uint16_t *b, uint32_t *c, int max)
+{
+    unsigned q, g, maxpos, d, e = *c, totfr = *c;
+    int ret;
+
+    for (d = 0; e <= 2048; d++)
+        e <<= 1;
+    maxpos = m->maxpos;
+    rccode >>= d;
+    *c = m->freqs[maxpos];
+    m->freqs[maxpos] += 4096 - e >> d;
+
+    for (q = 0, g = 0, e = 0; q < m->size; q++) {
+        unsigned f = m->symbols[q];
+        unsigned p = e + f - g;
+        unsigned k = m->freqs[q];
+
+        if (rccode < p) {
+            *value = rccode - e + g;
+            *b = rccode << d;
+            *a = 1 << d;
+            m->freqs[maxpos] = *c;
+            ret = add_symbol(m, q, *value, &totfr, max);
+            *c = totfr;
+            return ret;
+        }
+
+        if (p + k > rccode) {
+            *value = f;
+            e += *value - g;
+            *b = e << d;
+            *a = k << d;
+            m->freqs[maxpos] = *c;
+            m->freqs[q] += 50;
+            totfr += 50;
+            if ((q != maxpos) && (m->freqs[q] > m->freqs[maxpos]))
+                m->maxpos = q;
+            if (totfr + 50 > 4096)
+                rescale(m, &totfr);
+            *c = totfr;
+            return 1;
+        }
+
+        e += f - g + k;
+        g = f + 1;
+    }
+
+    m->freqs[maxpos] = *c;
+    *value = g + rccode - e;
+    *b = rccode << d;
+    *a = 1 << d;
+    ret = add_symbol(m, q, *value, &totfr, max);
+    *c = totfr;
+    return ret;
+}
+
+static int update_model6_to_7(PixelModel3 *n, PixelModel3 *m)
+{
+    int c, d, e, f, k, p, length, i, j, index;
+    uint16_t *freqs, *freqs1, *cnts;
+
+    n->type = 7;
+
+    length = m->length;
+    freqs = n->freqs;
+    freqs1 = n->freqs1;
+    cnts = n->cnts;
+    n->cntsum = m->cnts[length];
+    for (i = 0; i < length; i++) {
+        if (!m->cnts[i])
+            continue;
+        index = m->symbols[i];
+        freqs[index] = m->freqs[2 * i];
+        freqs1[index] = m->freqs[2 * i + 1];
+        cnts[index] = m->cnts[i];
+    }
+    c = 1 << m->fshift;
+    d = c - (c >> 1);
+    for (j = 0, e = 0; j < 256; j++) {
+        f = freqs[j];
+        if (!f) {
+            f = c;
+            freqs[j] = c;
+            freqs1[j] = e;
+            cnts[j] = d;
+        }
+        p = (e + 127) >> 7;
+        k = ((f + e - 1) >> 7) + 1;
+        for (i = 0; i < k - p; i++)
+            n->dectab[p + i] = j;
+        e += f;
+    }
+
+    memcpy(m, n, sizeof(*n));
+
+    return 0;
+}
+
+static void calc_sum(PixelModel3 *m)
+{
+    int a, b, c;
+
+    b = m->length;
+    a = 256 - m->size << (0 < m->fshift ? m->fshift - 1 : 0);
+    for (c = 0; c < b; c++)
+        a += m->cnts[c];
+    m->cnts[b] = a;
+}
+
+static void rescale_dec(PixelModel3 *m)
+{
+    uint16_t cnts[256] = {0};
+    uint16_t freqs[512] = {0};
+    int a, b, c, e, g;
+
+    for (a = 1 << (0 < m->fshift ? m->fshift - 1 : 0), b = 0; b < 256; b++) {
+        cnts[b] = a;
+    }
+
+    for (a = 0, b = m->size; a < b; a++) {
+        cnts[m->symbols[a]] = m->cnts[a];
+    }
+
+    for (b = a = 0; b < 256; b++) {
+        freqs[2 * b] = cnts[b];
+        freqs[2 * b + 1] = a;
+        a += cnts[b];
+    }
+
+    if (m->fshift > 0)
+        m->fshift--;
+
+    a = 256 - m->size << (0 < m->fshift ? m->fshift - 1 : 0);
+    for (b = 0, c = m->size; b < c; b++) {
+        m->cnts[b] -= m->cnts[b] >> 1;
+        a = a + m->cnts[b];
+        e = m->symbols[b];
+        g = freqs[2 * e + 1];
+        m->freqs[2 * b] = freqs[2 * e];
+        m->freqs[2 * b + 1] = g;
+    }
+    m->cnts[m->length] = a;
+}
+
+static int update_model5_to_6(PixelModel3 *n, PixelModel3 *m, uint8_t value)
+{
+    int c, d, e, f, g, k, q, p;
+
+    n->type = 6;
+    n->length = 32;
+
+    for (c = m->size, d = 256 - c, e = 0; e < c; e++)
+        d = d + m->freqs[e];
+
+    for (e = 0; 2048 >= d; e++)
+        d <<= 1;
+
+    for (q = d = 0, g = q = 0; g < c; g++) {
+        p = m->symbols[g];
+        d = d + (p - q);
+        q = m->freqs[g];
+        k = q << e;
+        n->freqs[2 * g] = k;
+        n->freqs[2 * g + 1] = d << e;
+        n->cnts[g] = k - (k >> 1);
+        n->symbols[g] = p;
+        d += q;
+        q = p + 1;
+    }
+
+    n->fshift = e;
+    e = 1 << n->fshift;
+    d = 0;
+    if (value > 0) {
+        d = -1;
+        for (p = f = g = 0; p < c; p++) {
+            k = n->symbols[p];
+            if (k > d && k < value) {
+                d = k;
+                g = n->freqs[2 * p];
+                f = n->freqs[2 * p + 1];
+            }
+        }
+        d = 0 < g ? f + g + (value - d - 1 << n->fshift) : value << n->fshift;
+    }
+    n->freqs[2 * c] = e;
+    n->freqs[2 * c + 1] = d;
+    n->cnts[c] = e - (e >> 1);
+    n->symbols[c] = value;
+    n->size = c + 1;
+    e = 25 << n->fshift;
+    n->cnts[c] += e;
+    n->cnts[32] += e;
+    if (n->cnts[32] + e > 4096) {
+        rescale_dec(n);
+    }
+    calc_sum(n);
+    c = 0;
+    for (e = n->size - 1; c < e;) {
+        for (d = c++, g = d + 1, f = n->size; g < f;) {
+            if (p = g++, q = n->freqs[2 * p], k = n->freqs[2 * d], q > k) {
+                int l = n->freqs[2 * d + 1];
+                int h = n->freqs[2 * p + 1];
+                n->freqs[2 * d] = q;
+                n->freqs[2 * d + 1] = h;
+                n->freqs[2 * p] = k;
+                n->freqs[2 * p + 1] = l;
+                FFSWAP(uint16_t, n->cnts[d], n->cnts[p]);
+                FFSWAP(uint8_t, n->symbols[d], n->symbols[p]);
+            }
+        }
+    }
+
+    memcpy(m, n, sizeof(*n));
+
+    return 0;
+}
+
+static void grow_dec(PixelModel3 *m)
+{
+    int a;
+
+    a = 2 * m->length;
+    m->cnts[2 * m->length] = m->cnts[m->length];
+    m->length = a;
+}
+
+static int add_dec(PixelModel3 *m, int a, int b, int c)
+{
+    int d;
+
+    if (m->size >= 40 || m->size >= m->length)
+        return -1;
+
+    d = m->size;
+    m->symbols[d] = a;
+    m->freqs[2 * d] = b;
+    m->freqs[2 * d + 1] = c;
+    m->cnts[d] = b - (b >> 1);
+    m->size++;
+
+    return d;
+}
+
+static void incr_cntdec(PixelModel3 *m, int a)
+{
+    int b, c, d, e, g;
+
+    b = 25 << m->fshift;
+    c = m->length;
+    m->cnts[a] += b;
+    m->cnts[c] += b;
+    if (a > 0 && m->cnts[a] > m->cnts[a - 1]) {
+        d = m->cnts[a];
+        m->cnts[a] = m->cnts[a - 1];
+        m->cnts[a - 1] = d;
+        d = m->freqs[2 * a];
+        e = m->freqs[2 * a + 1];
+        g = m->freqs[2 * (a - 1) + 1];
+        m->freqs[2 * a] = m->freqs[2 * (a - 1)];
+        m->freqs[2 * a + 1] = g;
+        g = a - 1;
+        m->freqs[2 * g] = d;
+        m->freqs[2 * g + 1] = e;
+        d = m->symbols[a];
+        m->symbols[a] = m->symbols[a - 1];
+        m->symbols[a - 1] = d;
+    }
+    if (m->cnts[c] + b > 4096)
+        rescale_dec(m);
+}
+
+static int decode_adaptive6(PixelModel3 *m, unsigned code, unsigned *value,
+                            uint16_t *a, uint16_t *b)
+{
+    int c, d, e, f, g, q;
+
+    for (c = 0, d = 0, e = 0, f = 0, g = 0, q = m->size; g < q; g++) {
+        unsigned p = m->freqs[2 * g + 1];
+
+        if (p <= code) {
+            unsigned k = m->freqs[2 * g];
+
+            if (p + k > code) {
+                *value = m->symbols[g];
+                *a = k;
+                *b = p;
+                incr_cntdec(m, g);
+                return 1;
+            }
+
+            if (p >= d) {
+                c = k;
+                d = p;
+                e = m->symbols[g];
+            }
+        }
+    }
+
+    g = 1 << m->fshift;
+    q = f = 0;
+
+    if (c > 0) {
+        f = code - (d + c) >> m->fshift;
+        q = f + e + 1;
+        f = d + c + (f << m->fshift);
+    } else {
+        q = code >> m->fshift;
+        f = q << m->fshift;
+    }
+
+    *a = g;
+    *b = f;
+    *value = q;
+
+    c = add_dec(m, q, g, f);
+    if (c < 0) {
+        if (m->length == 64)
+            return 0;
+        grow_dec(m);
+        c = add_dec(m, q, g, f);
+    }
+
+    incr_cntdec(m, c);
+    return 1;
+}
+
+static int cmpbytes(const void *p1, const void *p2)
+{
+    int left  = *(const uint8_t *)p1;
+    int right = *(const uint8_t *)p2;
+    return FFDIFFSIGN(left, right);
+}
+
+static int update_model1_to_2(PixelModel3 *m, unsigned val)
+{
+    PixelModel3 n = {0};
+    int i, b;
+
+    n.type = 2;
+    n.size = m->size + 1;
+    b = m->size;
+    for (i = 0; i < b; i++)
+        n.symbols[i] = m->symbols[i];
+    n.symbols[b] = val;
+
+    memcpy(m, &n, sizeof(n));
+
+    return 0;
+}
+
+static int update_model1_to_4(PixelModel3 *m, unsigned val)
+{
+    PixelModel3 n = {0};
+    int size, i;
+
+    size = m->size;
+    n.type = 4;
+    n.size = size;
+    for (i = 0; i < n.size; i++) {
+        n.symbols[i] = m->symbols[i];
+    }
+    AV_QSORT(n.symbols, size, uint8_t, cmpbytes);
+    for (i = 0; i < n.size; i++) {
+        if (val == n.symbols[i]) {
+            n.freqs[i] = 100;
+            n.maxpos = i;
+        } else {
+            n.freqs[i] = 50;
+        }
+    }
+
+    memcpy(m, &n, sizeof(n));
+
+    return 0;
+}
+
+static int update_model1_to_5(PixelModel3 *m, unsigned val)
+{
+    PixelModel3 n = {0};
+    int i, size, freqs;
+    unsigned a;
+
+    size = m->size;
+    n.size = size;
+    for (i = 0; i < size; i++) {
+        n.symbols[i] = m->symbols[i];
+    }
+    AV_QSORT(n.symbols, size, uint8_t, cmpbytes);
+    size = n.size;
+    for (i = 0; i < size; i++) {
+        if (val == n.symbols[i]) {
+            n.freqs[i] = 100;
+            n.maxpos = i;
+        } else {
+            n.freqs[i] = 50;
+        }
+    }
+    a = 256 - size;
+    for (i = 0; i < size; i++, a += freqs)
+        freqs = n.freqs[i];
+    n.type = 5;
+    n.cntsum = a;
+
+    memcpy(m, &n, sizeof(n));
+
+    return 0;
+}
+
+static int decode_static1(PixelModel3 *m, unsigned val)
+{
+    unsigned size;
+
+    size = m->size;
+    for (int i = 0; i < size; i++) {
+        if (val == m->symbols[i]) {
+            if (size <= 4)
+                return update_model1_to_4(m, val);
+            else
+                return update_model1_to_5(m, val);
+        }
+    }
+
+    if (size >= 14)
+        return update_model1_to_2(m, val);
+
+    m->symbols[size] = val;
+    m->size++;
+    return 0;
+}
+
+static int update_model2_to_6(PixelModel3 *m, uint8_t value, int a4)
+{
+    PixelModel3 n = {0};
+    int c, d, e, f, g, q;
+
+    n.type = 6;
+    n.length = a4;
+
+    memset(n.symbols, 1u, a4);
+
+    c = m->size;
+    d = 256 - c + (64 * c + 64);
+    for (e = 0; d <= 2048; e++) {
+        d <<= 1;
+    }
+
+    g = q = 0;
+    AV_QSORT(m->symbols, c, uint8_t, cmpbytes);
+    for (f = d = 0; f < c; f++) {
+        int p = f;
+        int k = m->symbols[p];
+        int l;
+        g = g + (k - q);
+
+        if (k == value) {
+            d = p;
+            q = 128;
+        } else {
+            q = 64;
+        }
+        l = q << e;
+        n.freqs[2 * p] = l;
+        n.freqs[2 * p + 1] = g << e;
+        n.symbols[p] = k;
+        n.cnts[p] = l - (l >> 1);
+        g += q;
+        q = k + 1;
+    }
+    n.size = c;
+    n.fshift = e;
+    calc_sum(&n);
+
+    if (d > 0) {
+        c = n.freqs[0];
+        e = n.freqs[1];
+        g = n.freqs[2 * d + 1];
+        n.freqs[0] = n.freqs[2 * d];
+        n.freqs[1] = g;
+        n.freqs[2 * d] = c;
+        n.freqs[2 * d + 1] = e;
+        FFSWAP(uint16_t, n.cnts[0], n.cnts[d]);
+        FFSWAP(uint8_t, n.symbols[0], n.symbols[d]);
+    }
+
+    memcpy(m, &n, sizeof(n));
+
+    return 0;
+}
+
+static int update_model2_to_3(PixelModel3 *m, unsigned val)
+{
+    PixelModel3 n = {0};
+    unsigned size;
+
+    n.type = 3;
+    n.size = m->size + 1;
+
+    size = m->size;
+    for (int i = 0; i < size; i++)
+        n.symbols[i] = m->symbols[i];
+    n.symbols[size] = val;
+
+    memcpy(m, &n, sizeof(n));
+
+    return 0;
+}
+
+static int decode_static2(PixelModel3 *m, unsigned val)
+{
+    unsigned size;
+
+    size = m->size;
+    for (int i = 0; i < size; i++) {
+        if (val == m->symbols[i]) {
+            int a;
+
+            if (m->size <= 32)
+                a = 32;
+            else
+                a = 64;
+            return update_model2_to_6(m, val, a);
+        }
+    }
+
+    if (size >= 64)
+        return update_model2_to_3(m, val);
+
+    m->symbols[size] = val;
+    m->size++;
+
+    return 0;
+}
+
+static int update_model3_to_7(PixelModel3 *m, uint8_t value)
+{
+    PixelModel3 n = {0};
+    int c, d, e, f, g, q;
+
+    n.type = 7;
+
+    for (c = 0; c < 256; c++) {
+        d = c;
+        n.freqs[d] = 1;
+        n.cnts[d] = 1;
+    }
+
+    for (c = m->size, d = (4096 - (256 - c)) / (c + 1) | 0, e = d - (d >> 1), g = 0; g < c;) {
+        q = g++;
+        q = m->symbols[q];
+        n.freqs[q] = d;
+        n.cnts[q] = e;
+    }
+    n.freqs[value] += d;
+    n.cnts[value] += 16;
+    for (d = c = n.cntsum = 0; 256 > d; d++) {
+        e = d;
+        n.cntsum += n.cnts[e];
+        n.freqs1[e] = c;
+        for (g = n.freqs[e], q = c + 128 - 1 >> 7, f = (c + g - 1 >> 7) + 1; q < f; q++) {
+            n.dectab[q] = e;
+        }
+        c += g;
+    }
+
+    memcpy(m, &n, sizeof(n));
+
+    return 0;
+}
+
+static int decode_static3(PixelModel3 *m, unsigned val)
+{
+    unsigned size = m->size;
+
+    for (int i = 0; i < size; i++) {
+        if (val == m->symbols[i])
+            return update_model3_to_7(m, val);
+    }
+
+    if (size >= 256)
+        return 0;
+
+    m->symbols[size] = val;
+    m->size++;
+    return 0;
+}
+
+static void sync_code3(GetByteContext *gb, RangeCoder *rc)
+{
+    rc->code1++;
+    if (rc->code1 == 0x20000) {
+        rc->code = bytestream2_get_le32(gb);
+        rc->code1 = 0;
+    }
+}
+
+static int decode_value3(SCPRContext *s, unsigned max, uint32_t *cntsum,
+                         uint16_t *freqs1, uint16_t *freqs2,
+                         uint16_t *cnts, uint8_t *dectable,
+                         unsigned *value)
+{
+    GetByteContext *gb = &s->gb;
+    RangeCoder *rc = &s->rc;
+    unsigned r, y, a, b, e, g, q;
+
+    r = dectable[(rc->code & 0xFFFu) >> 7];
+    if (r < max) {
+        while (freqs2[r + 1] <= (rc->code & 0xFFF)) {
+            if (++r >= max)
+                break;
+        }
+    }
+
+    cnts[r] += 16;
+    a = freqs1[r];
+    b = freqs2[r];
+    *cntsum += 16;
+    if (*cntsum + 16 > 4096) {
+        *cntsum = 0;
+        for (int c = 0, i = 0; i < max + 1; i++) {
+            e = cnts[i];
+            freqs2[i] = c;
+            freqs1[i] = e;
+            g = (c + 127) >> 7;
+            c += e;
+            q = ((c - 1) >> 7) + 1;
+            if (q > g) {
+                for (int j = 0; j < q - g; j++)
+                    dectable[j + g] = i;
+            }
+            y = e - (e >> 1);
+            cnts[i] = y;
+            *cntsum += y;
+        }
+    }
+
+    decode3(gb, rc, a, b);
+    sync_code3(gb, rc);
+
+    *value = r;
+
+    return 0;
+}
+
+static void calc_sum5(PixelModel3 *m)
+{
+    int a, b, c;
+
+    for (a = 256 - m->size, b = 0, c = m->size; b < c; b++) {
+        a += m->freqs[b];
+    }
+    m->cntsum = a;
+}
+
+static int update_model4_to_5(PixelModel3 *m, unsigned value)
+{
+    PixelModel3 n = {0};
+    int c, d, e, g, totfr;
+
+    n.type = 5;
+
+    for (c = 0, d = m->size, e = 0; c < d && m->symbols[c] < value; c++) {
+        n.symbols[c] = m->symbols[c];
+        e += n.freqs[c] = m->freqs[c];
+    }
+
+    g = c;
+    n.symbols[g] = value;
+    e += n.freqs[g] = 50;
+    for (++g; c < d;) {
+        n.symbols[g] = m->symbols[c];
+        e += n.freqs[g] = m->freqs[c];
+        ++c;
+        ++g;
+    }
+    n.size = d + 1;
+    if (e > 4096)
+        rescale(&n, &totfr);
+
+    calc_sum5(&n);
+
+    memcpy(m, &n, sizeof(n));
+
+    return 0;
+}
+
+static signed int decode_unit3(SCPRContext *s, PixelModel3 *m, unsigned code, unsigned *value)
+{
+    PixelModel3 n = {0};
+    GetByteContext *gb = &s->gb;
+    RangeCoder *rc = &s->rc;
+    uint16_t a = 0, b = 0;
+    uint32_t param;
+    int type;
+
+    type = m->type;
+    switch (type) {
+    case 0:
+        *value = bytestream2_get_byte(&s->gb);
+        m->type = 1;
+        m->size = 1;
+        m->symbols[0] = *value;
+        sync_code3(gb, rc);
+        break;
+    case 1:
+        *value = bytestream2_get_byte(&s->gb);
+        decode_static1(m, *value);
+        sync_code3(gb, rc);
+        break;
+    case 2:
+        *value = bytestream2_get_byte(&s->gb);
+        decode_static2(m, *value);
+        sync_code3(gb, rc);
+        break;
+    case 3:
+        *value = bytestream2_get_byte(&s->gb);
+        decode_static3(m, *value);
+        sync_code3(gb, rc);
+        break;
+    case 4:
+        param = m->freqs[0] + m->freqs[1] + m->freqs[2] + m->freqs[3] + 256 - m->size;
+        if (!decode_adaptive45(m, code, value, &a, &b, &param, 4)) {
+            update_model4_to_5(m, *value);
+        }
+        decode3(gb, rc, a, b);
+        sync_code3(gb, rc);
+        break;
+    case 5:
+        if (!decode_adaptive45(m, code, value, &a, &b, &m->cntsum, 16)) {
+            update_model5_to_6(&n, m, *value);
+        }
+        decode3(gb, rc, a, b);
+        sync_code3(gb, rc);
+        break;
+    case 6:
+        if (!decode_adaptive6(m, code, value, &a, &b)) {
+            update_model6_to_7(&n, m);
+        }
+        decode3(gb, rc, a, b);
+        sync_code3(gb, rc);
+        break;
+    case 7:
+        return decode_value3(s, 255, &m->cntsum,
+                            m->freqs, m->freqs1,
+                            m->cnts, m->dectab, value);
+    }
+    return 0;
+}
+
+static int decode_units3(SCPRContext * s, unsigned *red,
+                         unsigned *green, unsigned *blue,
+                         int *cx, int *cx1)
+{
+    RangeCoder *rc = &s->rc;
+
+    decode_unit3(s, &s->pixel_model3[0][*cx + *cx1], rc->code & 0xFFF, red);
+
+    *cx1 = (*cx << 6) & 0xFC0;
+    *cx = *red >> 2;
+
+    decode_unit3(s, &s->pixel_model3[1][*cx + *cx1], rc->code & 0xFFF, green);
+
+    *cx1 = (*cx << 6) & 0xFC0;
+    *cx = *green >> 2;
+
+    decode_unit3(s, &s->pixel_model3[2][*cx + *cx1], rc->code & 0xFFF, blue);
+
+    *cx1 = (*cx << 6) & 0xFC0;
+    *cx = *blue >> 2;
+
+    return 0;
+}
+
+static void init_rangecoder3(RangeCoder *rc, GetByteContext *gb)
+{
+    rc->code  = bytestream2_get_le32(gb);
+    rc->code1 = 0;
+}
+
+static int decode_run_i(AVCodecContext *avctx, unsigned ptype, int run,
+                        int *x, int *y, unsigned clr, uint32_t *dst,
+                        int linesize, unsigned *lx, unsigned *ly,
+                        unsigned backstep, int off, int *cx, int *cx1)
+{
+    unsigned r, g, b;
+    int z;
+
+    switch (ptype) {
+    case 0:
+        while (run-- > 0) {
+            if (*y >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            dst[*y * linesize + *x] = clr;
+            *lx = *x;
+            *ly = *y;
+            (*x)++;
+            if (*x >= avctx->width) {
+                *x = 0;
+                (*y)++;
+            }
+        }
+        break;
+    case 1:
+        while (run-- > 0) {
+            if (*y >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            dst[*y * linesize + *x] = dst[*ly * linesize + *lx];
+            *lx = *x;
+            *ly = *y;
+            (*x)++;
+            if (*x >= avctx->width) {
+                *x = 0;
+                (*y)++;
+            }
+        }
+        clr = dst[*ly * linesize + *lx];
+        break;
+    case 2:
+        while (run-- > 0) {
+            if (*y < 1 || *y >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            clr = dst[*y * linesize + *x + off + 1];
+            dst[*y * linesize + *x] = clr;
+            *lx = *x;
+            *ly = *y;
+            (*x)++;
+            if (*x >= avctx->width) {
+                *x = 0;
+                (*y)++;
+            }
+        }
+        break;
+    case 4:
+        while (run-- > 0) {
+            uint8_t *odst = (uint8_t *)dst;
+
+            if (*y < 1 || *y >= avctx->height ||
+                (*y == 1 && *x == 0))
+                return AVERROR_INVALIDDATA;
+
+            if (*x == 0) {
+                z = backstep;
+            } else {
+                z = 0;
+            }
+
+            r = odst[(*ly * linesize + *lx) * 4] +
+                odst[((*y * linesize + *x) + off) * 4 + 4] -
+                odst[((*y * linesize + *x) + off - z) * 4];
+            g = odst[(*ly * linesize + *lx) * 4 + 1] +
+                odst[((*y * linesize + *x) + off) * 4 + 5] -
+                odst[((*y * linesize + *x) + off - z) * 4 + 1];
+            b = odst[(*ly * linesize + *lx) * 4 + 2] +
+                odst[((*y * linesize + *x) + off) * 4 + 6] -
+                odst[((*y * linesize + *x) + off - z) * 4 + 2];
+            clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
+            dst[*y * linesize + *x] = clr;
+            *lx = *x;
+            *ly = *y;
+            (*x)++;
+            if (*x >= avctx->width) {
+                *x = 0;
+                (*y)++;
+            }
+        }
+        break;
+    case 5:
+        while (run-- > 0) {
+            if (*y < 1 || *y >= avctx->height ||
+                (*y == 1 && *x == 0))
+                return AVERROR_INVALIDDATA;
+
+            if (*x == 0) {
+                z = backstep;
+            } else {
+                z = 0;
+            }
+
+            clr = dst[*y * linesize + *x + off - z];
+            dst[*y * linesize + *x] = clr;
+            *lx = *x;
+            *ly = *y;
+            (*x)++;
+            if (*x >= avctx->width) {
+                *x = 0;
+                (*y)++;
+            }
+        }
+        break;
+    }
+
+    if (avctx->bits_per_coded_sample == 16) {
+        *cx1 = (clr & 0x3F00) >> 2;
+        *cx = (clr & 0x3FFFFF) >> 16;
+    } else {
+        *cx1 = (clr & 0xFC00) >> 4;
+        *cx = (clr & 0xFFFFFF) >> 18;
+    }
+
+    return 0;
+}
+
+static int decompress_i3(AVCodecContext *avctx, uint32_t *dst, int linesize)
+{
+    SCPRContext *s = avctx->priv_data;
+    GetByteContext *gb = &s->gb;
+    RangeCoder *rc = &s->rc;
+    int cx = 0, cx1 = 0, k = 0;
+    int run, off, y = 0, x = 0, ret;
+    unsigned backstep = linesize - avctx->width;
+    unsigned clr = 0, lx, ly, ptype, r, g, b;
+
+    bytestream2_skip(gb, 1);
+    init_rangecoder3(rc, gb);
+    reinit_tables3(s);
 
-typedef struct RangeCoder {
-    unsigned   code;
-    unsigned   range;
-    unsigned   code1;
-} RangeCoder;
+    while (k < avctx->width + 1) {
+        decode_units3(s, &r, &g, &b, &cx, &cx1);
+        ret = decode_value3(s, 255, &s->run_model3[0].cntsum,
+                            s->run_model3[0].freqs[0],
+                            s->run_model3[0].freqs[1],
+                            s->run_model3[0].cnts,
+                            s->run_model3[0].dectab, &run);
+        if (ret < 0)
+            return ret;
+        if (run <= 0)
+            return AVERROR_INVALIDDATA;
 
-typedef struct PixelModel {
-    unsigned    freq[256];
-    unsigned    lookup[16];
-    unsigned    total_freq;
-} PixelModel;
+        clr = (b << 16) + (g << 8) + r;
+        k += run;
+        while (run-- > 0) {
+            if (y >= avctx->height)
+                return AVERROR_INVALIDDATA;
 
-typedef struct SCPRContext {
-    AVFrame        *last_frame;
-    AVFrame        *current_frame;
-    GetByteContext  gb;
-    RangeCoder      rc;
-    PixelModel      pixel_model[3][4096];
-    unsigned        op_model[6][7];
-    unsigned        run_model[6][257];
-    unsigned        range_model[257];
-    unsigned        count_model[257];
-    unsigned        fill_model[6];
-    unsigned        sxy_model[4][17];
-    unsigned        mv_model[2][513];
-    unsigned        nbx, nby;
-    unsigned        nbcount;
-    unsigned       *blocks;
-    unsigned        cbits;
-    int             cxshift;
+            dst[y * linesize + x] = clr;
+            lx = x;
+            ly = y;
+            x++;
+            if (x >= avctx->width) {
+                x = 0;
+                y++;
+            }
+        }
+    }
+    off = -linesize - 1;
+    ptype = 0;
 
-    int           (*get_freq)(RangeCoder *rc, unsigned total_freq, unsigned *freq);
-    int           (*decode)(GetByteContext *gb, RangeCoder *rc, unsigned cumFreq, unsigned freq, unsigned total_freq);
-} SCPRContext;
+    while (x < avctx->width && y < avctx->height) {
+        ret = decode_value3(s, 5, &s->op_model3[ptype].cntsum,
+                            s->op_model3[ptype].freqs[0],
+                            s->op_model3[ptype].freqs[1],
+                            s->op_model3[ptype].cnts,
+                            s->op_model3[ptype].dectab, &ptype);
+        if (ret < 0)
+            return ret;
+        if (ptype == 0) {
+            decode_units3(s, &r, &g, &b, &cx, &cx1);
+            clr = (b << 16) + (g << 8) + r;
+        }
+        if (ptype > 5)
+            return AVERROR_INVALIDDATA;
+        ret = decode_value3(s, 255, &s->run_model3[ptype].cntsum,
+                            s->run_model3[ptype].freqs[0],
+                            s->run_model3[ptype].freqs[1],
+                            s->run_model3[ptype].cnts,
+                            s->run_model3[ptype].dectab, &run);
+        if (ret < 0)
+            return ret;
+        if (run <= 0)
+            return AVERROR_INVALIDDATA;
+
+        ret = decode_run_i(avctx, ptype, run, &x, &y, clr,
+                           dst, linesize, &lx, &ly,
+                           backstep, off, &cx, &cx1);
+        if (run < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+static int decode_run_p(AVCodecContext *avctx, unsigned ptype, int run,
+                        int x, int y, unsigned clr,
+                        uint32_t *dst, uint32_t *prev,
+                        int linesize, int plinesize,
+                        unsigned *bx, unsigned *by,
+                        unsigned backstep, int sx1, int sx2,
+                        int *cx, int *cx1)
+{
+    unsigned r, g, b;
+    int z;
+
+    switch (ptype) {
+    case 0:
+        while (run-- > 0) {
+            if (*by >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            dst[*by * linesize + *bx] = clr;
+            (*bx)++;
+            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
+                *bx = x * 16 + sx1;
+                (*by)++;
+            }
+        }
+        break;
+    case 1:
+        while (run-- > 0) {
+            if (*bx == 0) {
+                if (*by < 1)
+                    return AVERROR_INVALIDDATA;
+                z = backstep;
+            } else {
+                z = 0;
+            }
+
+            if (*by >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            clr = dst[*by * linesize + *bx - 1 - z];
+            dst[*by * linesize + *bx] = clr;
+            (*bx)++;
+            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
+                *bx = x * 16 + sx1;
+                (*by)++;
+            }
+        }
+        break;
+    case 2:
+        while (run-- > 0) {
+            if (*by < 1 || *by >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            clr = dst[(*by - 1) * linesize + *bx];
+            dst[*by * linesize + *bx] = clr;
+            (*bx)++;
+            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
+                *bx = x * 16 + sx1;
+                (*by)++;
+            }
+        }
+        break;
+    case 3:
+        while (run-- > 0) {
+            if (*by >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            clr = prev[*by * plinesize + *bx];
+            dst[*by * linesize + *bx] = clr;
+            (*bx)++;
+            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
+                *bx = x * 16 + sx1;
+                (*by)++;
+            }
+        }
+        break;
+    case 4:
+        while (run-- > 0) {
+            uint8_t *odst = (uint8_t *)dst;
+
+            if (*by < 1 || *by >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            if (*bx == 0) {
+                if (*by < 2)
+                    return AVERROR_INVALIDDATA;
+                z = backstep;
+            } else {
+                z = 0;
+            }
+
+            r = odst[((*by - 1) * linesize + *bx) * 4] +
+                odst[(*by * linesize + *bx - 1 - z) * 4] -
+                odst[((*by - 1) * linesize + *bx - 1 - z) * 4];
+            g = odst[((*by - 1) * linesize + *bx) * 4 + 1] +
+                odst[(*by * linesize + *bx - 1 - z) * 4 + 1] -
+                odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 1];
+            b = odst[((*by - 1) * linesize + *bx) * 4 + 2] +
+                odst[(*by * linesize + *bx - 1 - z) * 4 + 2] -
+                odst[((*by - 1) * linesize + *bx - 1 - z) * 4 + 2];
+            clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
+            dst[*by * linesize + *bx] = clr;
+            (*bx)++;
+            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
+                *bx = x * 16 + sx1;
+                (*by)++;
+            }
+        }
+        break;
+    case 5:
+        while (run-- > 0) {
+            if (*by < 1 || *by >= avctx->height)
+                return AVERROR_INVALIDDATA;
+
+            if (*bx == 0) {
+                if (*by < 2)
+                    return AVERROR_INVALIDDATA;
+                z = backstep;
+            } else {
+                z = 0;
+            }
+
+            clr = dst[(*by - 1) * linesize + *bx - 1 - z];
+            dst[*by * linesize + *bx] = clr;
+            (*bx)++;
+            if (*bx >= x * 16 + sx2 || *bx >= avctx->width) {
+                *bx = x * 16 + sx1;
+                (*by)++;
+            }
+        }
+        break;
+    }
+
+    if (avctx->bits_per_coded_sample == 16) {
+        *cx1 = (clr & 0x3F00) >> 2;
+        *cx = (clr & 0x3FFFFF) >> 16;
+    } else {
+        *cx1 = (clr & 0xFC00) >> 4;
+        *cx = (clr & 0xFFFFFF) >> 18;
+    }
+
+    return 0;
+}
+
+static int decompress_p3(AVCodecContext *avctx,
+                         uint32_t *dst, int linesize,
+                         uint32_t *prev, int plinesize)
+{
+    SCPRContext *s = avctx->priv_data;
+    GetByteContext *gb = &s->gb;
+    int ret, temp, min, max, x, y, cx = 0, cx1 = 0;
+    int backstep = linesize - avctx->width;
+    int mvx = 0, mvy = 0;
+
+    if (bytestream2_get_byte(gb) == 0)
+        return 0;
+    init_rangecoder3(&s->rc, gb);
+
+    ret  = decode_value3(s, 255, &s->range_model3.cntsum,
+                         s->range_model3.freqs[0],
+                         s->range_model3.freqs[1],
+                         s->range_model3.cnts,
+                         s->range_model3.dectab, &min);
+    ret |= decode_value3(s, 255, &s->range_model3.cntsum,
+                         s->range_model3.freqs[0],
+                         s->range_model3.freqs[1],
+                         s->range_model3.cnts,
+                         s->range_model3.dectab, &temp);
+    min += temp << 8;
+    ret |= decode_value3(s, 255, &s->range_model3.cntsum,
+                         s->range_model3.freqs[0],
+                         s->range_model3.freqs[1],
+                         s->range_model3.cnts,
+                         s->range_model3.dectab, &max);
+    ret |= decode_value3(s, 255, &s->range_model3.cntsum,
+                         s->range_model3.freqs[0],
+                         s->range_model3.freqs[1],
+                         s->range_model3.cnts,
+                         s->range_model3.dectab, &temp);
+    if (ret < 0)
+        return ret;
+
+    max += temp << 8;
+    memset(s->blocks, 0, sizeof(*s->blocks) * s->nbcount);
+
+    while (min <= max) {
+        int fill, count;
+
+        ret  = decode_value3(s, 4, &s->fill_model3.cntsum,
+                             s->fill_model3.freqs[0],
+                             s->fill_model3.freqs[1],
+                             s->fill_model3.cnts,
+                             s->fill_model3.dectab, &fill);
+        ret |= decode_value3(s, 255, &s->count_model3.cntsum,
+                             s->count_model3.freqs[0],
+                             s->count_model3.freqs[1],
+                             s->count_model3.cnts,
+                             s->count_model3.dectab, &count);
+        if (ret < 0)
+            return ret;
+
+        while (min < s->nbcount && count-- > 0) {
+            s->blocks[min++] = fill;
+        }
+    }
+
+    for (y = 0; y < s->nby; y++) {
+        for (x = 0; x < s->nbx; x++) {
+            int sy1 = 0, sy2 = 16, sx1 = 0, sx2 = 16;
+
+            if (s->blocks[y * s->nbx + x] == 0)
+                continue;
+
+            if (((s->blocks[y * s->nbx + x] + 1) & 1) > 0) {
+                ret  = decode_value3(s, 15, &s->sxy_model3[0].cntsum,
+                                     s->sxy_model3[0].freqs[0],
+                                     s->sxy_model3[0].freqs[1],
+                                     s->sxy_model3[0].cnts,
+                                     s->sxy_model3[0].dectab, &sx1);
+                ret |= decode_value3(s, 15, &s->sxy_model3[1].cntsum,
+                                     s->sxy_model3[1].freqs[0],
+                                     s->sxy_model3[1].freqs[1],
+                                     s->sxy_model3[1].cnts,
+                                     s->sxy_model3[1].dectab, &sy1);
+                ret |= decode_value3(s, 15, &s->sxy_model3[2].cntsum,
+                                     s->sxy_model3[2].freqs[0],
+                                     s->sxy_model3[2].freqs[1],
+                                     s->sxy_model3[2].cnts,
+                                     s->sxy_model3[2].dectab, &sx2);
+                ret |= decode_value3(s, 15, &s->sxy_model3[3].cntsum,
+                                     s->sxy_model3[3].freqs[0],
+                                     s->sxy_model3[3].freqs[1],
+                                     s->sxy_model3[3].cnts,
+                                     s->sxy_model3[3].dectab, &sy2);
+                if (ret < 0)
+                    return ret;
+
+                sx2++;
+                sy2++;
+            }
+            if (((s->blocks[y * s->nbx + x] + 3) & 2) > 0) {
+                int i, a, b, c, j, by = y * 16, bx = x * 16;
+                unsigned X;
+
+                a = s->rc.code & 0xFFF;
+                c = 1;
+
+                if (a < 0x800)
+                    c = 0;
+                b = 2048;
+                if (!c)
+                    b = 0;
+
+                X = a + ((s->rc.code >> 1) & 0xFFFFF800) - b;
+                while (X < 0x800000 && bytestream2_get_bytes_left(gb) > 0) {
+                    X = bytestream2_get_byte(gb) | (X << 8);
+                }
+                s->rc.code = X;
+
+                sync_code3(gb, &s->rc);
+
+                if (!c) {
+                    ret  = decode_value3(s, 511, &s->mv_model3[0].cntsum,
+                                         s->mv_model3[0].freqs[0],
+                                         s->mv_model3[0].freqs[1],
+                                         s->mv_model3[0].cnts,
+                                         s->mv_model3[0].dectab, &mvx);
+                    ret |= decode_value3(s, 511, &s->mv_model3[1].cntsum,
+                                         s->mv_model3[1].freqs[0],
+                                         s->mv_model3[1].freqs[1],
+                                         s->mv_model3[1].cnts,
+                                         s->mv_model3[1].dectab, &mvy);
+                    if (ret < 0)
+                        return ret;
+
+                    mvx -= 256;
+                    mvy -= 256;
+                }
+
+                if (by + mvy + sy1 < 0 || bx + mvx + sx1 < 0 ||
+                    by + mvy + sy1 >= avctx->height || bx + mvx + sx1 >= avctx->width)
+                    return AVERROR_INVALIDDATA;
+
+                for (i = 0; i < sy2 - sy1 && (by + sy1 + i) < avctx->height && (by + mvy + sy1 + i) < avctx->height; i++) {
+                    for (j = 0; j < sx2 - sx1 && (bx + sx1 + j) < avctx->width && (bx + mvx + sx1 + j) < avctx->width; j++) {
+                        dst[(by + i + sy1) * linesize + bx + sx1 + j] = prev[(by + mvy + sy1 + i) * plinesize + bx + sx1 + mvx + j];
+                    }
+                }
+            } else {
+                int run, bx = x * 16 + sx1, by = y * 16 + sy1;
+                unsigned clr, ptype = 0, r, g, b;
+
+                for (; by < y * 16 + sy2 && by < avctx->height;) {
+                    ret = decode_value3(s, 5, &s->op_model3[ptype].cntsum,
+                                        s->op_model3[ptype].freqs[0],
+                                        s->op_model3[ptype].freqs[1],
+                                        s->op_model3[ptype].cnts,
+                                        s->op_model3[ptype].dectab, &ptype);
+                    if (ret < 0)
+                        return ret;
+                    if (ptype == 0) {
+                        ret = decode_units3(s, &r, &g, &b, &cx, &cx1);
+                        if (ret < 0)
+                            return ret;
+
+                        clr = (b << 16) + (g << 8) + r;
+                    }
+                    if (ptype > 5)
+                        return AVERROR_INVALIDDATA;
+                    ret = decode_value3(s, 255, &s->run_model3[ptype].cntsum,
+                                        s->run_model3[ptype].freqs[0],
+                                        s->run_model3[ptype].freqs[1],
+                                        s->run_model3[ptype].cnts,
+                                        s->run_model3[ptype].dectab, &run);
+                    if (ret < 0)
+                        return ret;
+                    if (run <= 0)
+                        return AVERROR_INVALIDDATA;
+
+                    ret = decode_run_p(avctx, ptype, run, x, y, clr,
+                                       dst, prev, linesize, plinesize, &bx, &by,
+                                       backstep, sx1, sx2, &cx, &cx1);
+                    if (ret < 0)
+                        return ret;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
 
 static void init_rangecoder(RangeCoder *rc, GetByteContext *gb)
 {
@@ -329,9 +1820,9 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
 {
     SCPRContext *s = avctx->priv_data;
     GetByteContext *gb = &s->gb;
-    int cx = 0, cx1 = 0, k = 0, clr = 0;
-    int run, off, y = 0, x = 0, z, ret;
-    unsigned r, g, b, backstep = linesize - avctx->width;
+    int cx = 0, cx1 = 0, k = 0;
+    int run, off, y = 0, x = 0, ret;
+    unsigned clr = 0, r, g, b, backstep = linesize - avctx->width;
     unsigned lx, ly, ptype;
 
     reinit_tables(s);
@@ -387,120 +1878,11 @@  static int decompress_i(AVCodecContext *avctx, uint32_t *dst, int linesize)
         if (run <= 0)
             return AVERROR_INVALIDDATA;
 
-        switch (ptype) {
-        case 0:
-            while (run-- > 0) {
-                if (y >= avctx->height)
-                    return AVERROR_INVALIDDATA;
-
-                dst[y * linesize + x] = clr;
-                lx = x;
-                ly = y;
-                x++;
-                if (x >= avctx->width) {
-                    x = 0;
-                    y++;
-                }
-            }
-            break;
-        case 1:
-            while (run-- > 0) {
-                if (y >= avctx->height)
-                    return AVERROR_INVALIDDATA;
-
-                dst[y * linesize + x] = dst[ly * linesize + lx];
-                lx = x;
-                ly = y;
-                x++;
-                if (x >= avctx->width) {
-                    x = 0;
-                    y++;
-                }
-            }
-            clr = dst[ly * linesize + lx];
-            break;
-        case 2:
-            while (run-- > 0) {
-                if (y < 1 || y >= avctx->height)
-                    return AVERROR_INVALIDDATA;
-
-                clr = dst[y * linesize + x + off + 1];
-                dst[y * linesize + x] = clr;
-                lx = x;
-                ly = y;
-                x++;
-                if (x >= avctx->width) {
-                    x = 0;
-                    y++;
-                }
-            }
-            break;
-        case 4:
-            while (run-- > 0) {
-                uint8_t *odst = (uint8_t *)dst;
-
-                if (y < 1 || y >= avctx->height ||
-                    (y == 1 && x == 0))
-                    return AVERROR_INVALIDDATA;
-
-                if (x == 0) {
-                    z = backstep;
-                } else {
-                    z = 0;
-                }
-
-                r = odst[(ly * linesize + lx) * 4] +
-                    odst[((y * linesize + x) + off) * 4 + 4] -
-                    odst[((y * linesize + x) + off - z) * 4];
-                g = odst[(ly * linesize + lx) * 4 + 1] +
-                    odst[((y * linesize + x) + off) * 4 + 5] -
-                    odst[((y * linesize + x) + off - z) * 4 + 1];
-                b = odst[(ly * linesize + lx) * 4 + 2] +
-                    odst[((y * linesize + x) + off) * 4 + 6] -
-                    odst[((y * linesize + x) + off - z) * 4 + 2];
-                clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
-                dst[y * linesize + x] = clr;
-                lx = x;
-                ly = y;
-                x++;
-                if (x >= avctx->width) {
-                    x = 0;
-                    y++;
-                }
-            }
-            break;
-        case 5:
-            while (run-- > 0) {
-                if (y < 1 || y >= avctx->height ||
-                    (y == 1 && x == 0))
-                    return AVERROR_INVALIDDATA;
-
-                if (x == 0) {
-                    z = backstep;
-                } else {
-                    z = 0;
-                }
-
-                clr = dst[y * linesize + x + off - z];
-                dst[y * linesize + x] = clr;
-                lx = x;
-                ly = y;
-                x++;
-                if (x >= avctx->width) {
-                    x = 0;
-                    y++;
-                }
-            }
-            break;
-        }
-
-        if (avctx->bits_per_coded_sample == 16) {
-            cx1 = (clr & 0x3F00) >> 2;
-            cx = (clr & 0x3FFFFF) >> 16;
-        } else {
-            cx1 = (clr & 0xFC00) >> 4;
-            cx = (clr & 0xFFFFFF) >> 18;
-        }
+        ret = decode_run_i(avctx, ptype, run, &x, &y, clr,
+                           dst, linesize, &lx, &ly,
+                           backstep, off, &cx, &cx1);
+        if (run < 0)
+            return ret;
     }
 
     return 0;
@@ -587,7 +1969,7 @@  static int decompress_p(AVCodecContext *avctx,
                     }
                 }
             } else {
-                int run, z, bx = x * 16 + sx1, by = y * 16 + sy1;
+                int run, bx = x * 16 + sx1, by = y * 16 + sy1;
                 unsigned r, g, b, clr, ptype = 0;
 
                 for (; by < y * 16 + sy2 && by < avctx->height;) {
@@ -609,134 +1991,11 @@  static int decompress_p(AVCodecContext *avctx,
                     if (run <= 0)
                         return AVERROR_INVALIDDATA;
 
-                    switch (ptype) {
-                    case 0:
-                        while (run-- > 0) {
-                            if (by >= avctx->height)
-                                return AVERROR_INVALIDDATA;
-
-                            dst[by * linesize + bx] = clr;
-                            bx++;
-                            if (bx >= x * 16 + sx2 || bx >= avctx->width) {
-                                bx = x * 16 + sx1;
-                                by++;
-                            }
-                        }
-                        break;
-                    case 1:
-                        while (run-- > 0) {
-                            if (bx == 0) {
-                                if (by < 1)
-                                    return AVERROR_INVALIDDATA;
-                                z = backstep;
-                            } else {
-                                z = 0;
-                            }
-
-                            if (by >= avctx->height)
-                                return AVERROR_INVALIDDATA;
-
-                            clr = dst[by * linesize + bx - 1 - z];
-                            dst[by * linesize + bx] = clr;
-                            bx++;
-                            if (bx >= x * 16 + sx2 || bx >= avctx->width) {
-                                bx = x * 16 + sx1;
-                                by++;
-                            }
-                        }
-                        break;
-                    case 2:
-                        while (run-- > 0) {
-                            if (by < 1 || by >= avctx->height)
-                                return AVERROR_INVALIDDATA;
-
-                            clr = dst[(by - 1) * linesize + bx];
-                            dst[by * linesize + bx] = clr;
-                            bx++;
-                            if (bx >= x * 16 + sx2 || bx >= avctx->width) {
-                                bx = x * 16 + sx1;
-                                by++;
-                            }
-                        }
-                        break;
-                    case 3:
-                        while (run-- > 0) {
-                            if (by >= avctx->height)
-                                return AVERROR_INVALIDDATA;
-
-                            clr = prev[by * plinesize + bx];
-                            dst[by * linesize + bx] = clr;
-                            bx++;
-                            if (bx >= x * 16 + sx2 || bx >= avctx->width) {
-                                bx = x * 16 + sx1;
-                                by++;
-                            }
-                        }
-                        break;
-                    case 4:
-                        while (run-- > 0) {
-                            uint8_t *odst = (uint8_t *)dst;
-
-                            if (by < 1 || by >= avctx->height)
-                                return AVERROR_INVALIDDATA;
-
-                            if (bx == 0) {
-                                if (by < 2)
-                                    return AVERROR_INVALIDDATA;
-                                z = backstep;
-                            } else {
-                                z = 0;
-                            }
-
-                            r = odst[((by - 1) * linesize + bx) * 4] +
-                                odst[(by * linesize + bx - 1 - z) * 4] -
-                                odst[((by - 1) * linesize + bx - 1 - z) * 4];
-                            g = odst[((by - 1) * linesize + bx) * 4 + 1] +
-                                odst[(by * linesize + bx - 1 - z) * 4 + 1] -
-                                odst[((by - 1) * linesize + bx - 1 - z) * 4 + 1];
-                            b = odst[((by - 1) * linesize + bx) * 4 + 2] +
-                                odst[(by * linesize + bx - 1 - z) * 4 + 2] -
-                                odst[((by - 1) * linesize + bx - 1 - z) * 4 + 2];
-                            clr = ((b & 0xFF) << 16) + ((g & 0xFF) << 8) + (r & 0xFF);
-                            dst[by * linesize + bx] = clr;
-                            bx++;
-                            if (bx >= x * 16 + sx2 || bx >= avctx->width) {
-                                bx = x * 16 + sx1;
-                                by++;
-                            }
-                        }
-                        break;
-                    case 5:
-                        while (run-- > 0) {
-                            if (by < 1 || by >= avctx->height)
-                                return AVERROR_INVALIDDATA;
-
-                            if (bx == 0) {
-                                if (by < 2)
-                                    return AVERROR_INVALIDDATA;
-                                z = backstep;
-                            } else {
-                                z = 0;
-                            }
-
-                            clr = dst[(by - 1) * linesize + bx - 1 - z];
-                            dst[by * linesize + bx] = clr;
-                            bx++;
-                            if (bx >= x * 16 + sx2 || bx >= avctx->width) {
-                                bx = x * 16 + sx1;
-                                by++;
-                            }
-                        }
-                        break;
-                    }
-
-                    if (avctx->bits_per_coded_sample == 16) {
-                        cx1 = (clr & 0x3F00) >> 2;
-                        cx = (clr & 0x3FFFFF) >> 16;
-                    } else {
-                        cx1 = (clr & 0xFC00) >> 4;
-                        cx = (clr & 0xFFFFFF) >> 18;
-                    }
+                    ret = decode_run_p(avctx, ptype, run, x, y, clr,
+                                       dst, prev, linesize, plinesize, &bx, &by,
+                                       backstep, sx1, sx2, &cx, &cx1);
+                    if (ret < 0)
+                        return ret;
                 }
             }
         }
@@ -766,18 +2025,26 @@  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     type = bytestream2_peek_byte(gb);
 
     if (type == 2) {
+        s->version = 1;
         s->get_freq = get_freq0;
         s->decode = decode0;
         frame->key_frame = 1;
         ret = decompress_i(avctx, (uint32_t *)s->current_frame->data[0],
                            s->current_frame->linesize[0] / 4);
     } else if (type == 18) {
+        s->version = 2;
         s->get_freq = get_freq;
         s->decode = decode;
         frame->key_frame = 1;
         ret = decompress_i(avctx, (uint32_t *)s->current_frame->data[0],
                            s->current_frame->linesize[0] / 4);
-    } else if (type == 17) {
+    } else if (type == 34) {
+        frame->key_frame = 1;
+        s->version = 3;
+        ret = decompress_i3(avctx, (uint32_t *)s->current_frame->data[0],
+                            s->current_frame->linesize[0] / 4);
+        ret = 0;
+    } else if (type == 17 || type == 33) {
         uint32_t clr, *dst = (uint32_t *)s->current_frame->data[0];
         int x, y;
 
@@ -807,10 +2074,16 @@  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         if (ret < 0)
             return ret;
 
-        ret = decompress_p(avctx, (uint32_t *)s->current_frame->data[0],
-                           s->current_frame->linesize[0] / 4,
-                           (uint32_t *)s->last_frame->data[0],
-                           s->last_frame->linesize[0] / 4);
+        if (s->version == 1 || s->version == 2)
+            ret = decompress_p(avctx, (uint32_t *)s->current_frame->data[0],
+                               s->current_frame->linesize[0] / 4,
+                               (uint32_t *)s->last_frame->data[0],
+                               s->last_frame->linesize[0] / 4);
+        else
+            ret = decompress_p3(avctx, (uint32_t *)s->current_frame->data[0],
+                                s->current_frame->linesize[0] / 4,
+                                (uint32_t *)s->last_frame->data[0],
+                                s->last_frame->linesize[0] / 4);
     } else {
         return AVERROR_PATCHWELCOME;
     }
@@ -901,6 +2174,7 @@  static av_cold int decode_close(AVCodecContext *avctx)
     av_freep(&s->blocks);
     av_frame_free(&s->last_frame);
     av_frame_free(&s->current_frame);
+    reinit_tables3(s);
 
     return 0;
 }