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;
    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;
}