static int cinepak_decode_vectors (CinepakContext *s, cvid_strip *strip,

                                   int chunk_id, int size, const uint8_t *data)

{

    const uint8_t   *eod = (data + size);

    uint32_t         flag, mask;

    uint8_t         *cb0, *cb1, *cb2, *cb3;

    unsigned int     x, y;

    char            *ip0, *ip1, *ip2, *ip3;



    flag = 0;

    mask = 0;



    for (y=strip->y1; y < strip->y2; y+=4) {



/* take care of y dimension not being multiple of 4, such streams exist */

        ip0 = ip1 = ip2 = ip3 = s->frame->data[0] +

          (s->palette_video?strip->x1:strip->x1*3) + (y * s->frame->linesize[0]);

        if(s->avctx->height - y > 1) {

            ip1 = ip0 + s->frame->linesize[0];

            if(s->avctx->height - y > 2) {

                ip2 = ip1 + s->frame->linesize[0];

                if(s->avctx->height - y > 3) {

                    ip3 = ip2 + s->frame->linesize[0];

                }

            }

        }

/* to get the correct picture for not-multiple-of-4 cases let us fill

 * each block from the bottom up, thus possibly overwriting the top line

 * more than once but ending with the correct data in place

 * (instead of in-loop checking) */



        for (x=strip->x1; x < strip->x2; x+=4) {

            if ((chunk_id & 0x01) && !(mask >>= 1)) {

                if ((data + 4) > eod)

                    return AVERROR_INVALIDDATA;



                flag  = AV_RB32 (data);

                data += 4;

                mask  = 0x80000000;

            }



            if (!(chunk_id & 0x01) || (flag & mask)) {

                if (!(chunk_id & 0x02) && !(mask >>= 1)) {

                    if ((data + 4) > eod)

                        return AVERROR_INVALIDDATA;



                    flag  = AV_RB32 (data);

                    data += 4;

                    mask  = 0x80000000;

                }



                if ((chunk_id & 0x02) || (~flag & mask)) {

                    uint8_t *p;

                    if (data >= eod)

                        return AVERROR_INVALIDDATA;



                    p = strip->v1_codebook[*data++];

                    if (s->palette_video) {

                        ip3[0] = ip3[1] = ip2[0] = ip2[1] = p[6];

                        ip3[2] = ip3[3] = ip2[2] = ip2[3] = p[9];

                        ip1[0] = ip1[1] = ip0[0] = ip0[1] = p[0];

                        ip1[2] = ip1[3] = ip0[2] = ip0[3] = p[3];

                    } else {

                        p += 6;

                        memcpy(ip3 + 0, p, 3); memcpy(ip3 + 3, p, 3);

                        memcpy(ip2 + 0, p, 3); memcpy(ip2 + 3, p, 3);

                        p += 3; /* ... + 9 */

                        memcpy(ip3 + 6, p, 3); memcpy(ip3 + 9, p, 3);

                        memcpy(ip2 + 6, p, 3); memcpy(ip2 + 9, p, 3);

                        p -= 9; /* ... + 0 */

                        memcpy(ip1 + 0, p, 3); memcpy(ip1 + 3, p, 3);

                        memcpy(ip0 + 0, p, 3); memcpy(ip0 + 3, p, 3);

                        p += 3; /* ... + 3 */

                        memcpy(ip1 + 6, p, 3); memcpy(ip1 + 9, p, 3);

                        memcpy(ip0 + 6, p, 3); memcpy(ip0 + 9, p, 3);

                    }



                } else if (flag & mask) {

                    if ((data + 4) > eod)

                        return AVERROR_INVALIDDATA;



                    cb0 = strip->v4_codebook[*data++];

                    cb1 = strip->v4_codebook[*data++];

                    cb2 = strip->v4_codebook[*data++];

                    cb3 = strip->v4_codebook[*data++];

                    if (s->palette_video) {

                        uint8_t *p;

                        p = ip3;

                        *p++ = cb2[6];

                        *p++ = cb2[9];

                        *p++ = cb3[6];

                        *p   = cb3[9];

                        p = ip2;

                        *p++ = cb2[0];

                        *p++ = cb2[3];

                        *p++ = cb3[0];

                        *p   = cb3[3];

                        p = ip1;

                        *p++ = cb0[6];

                        *p++ = cb0[9];

                        *p++ = cb1[6];

                        *p   = cb1[9];

                        p = ip0;

                        *p++ = cb0[0];

                        *p++ = cb0[3];

                        *p++ = cb1[0];

                        *p   = cb1[3];

                    } else {

                        memcpy(ip3 + 0, cb2 + 6, 6);

                        memcpy(ip3 + 6, cb3 + 6, 6);

                        memcpy(ip2 + 0, cb2 + 0, 6);

                        memcpy(ip2 + 6, cb3 + 0, 6);

                        memcpy(ip1 + 0, cb0 + 6, 6);

                        memcpy(ip1 + 6, cb1 + 6, 6);

                        memcpy(ip0 + 0, cb0 + 0, 6);

                        memcpy(ip0 + 6, cb1 + 0, 6);

                    }



                }

            }



            if (s->palette_video) {

                ip0 += 4;  ip1 += 4;

                ip2 += 4;  ip3 += 4;

            } else {

                ip0 += 12;  ip1 += 12;

                ip2 += 12;  ip3 += 12;

            }

        }

    }



    return 0;

}
