static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length)

{

    int x, y;

    const int width  = f->avctx->width;

    const int height = f->avctx->height;

    uint16_t *src    = (uint16_t *)f->last_picture.data[0];

    uint16_t *dst    = (uint16_t *)f->current_picture.data[0];

    const int stride =             f->current_picture.linesize[0] >> 1;

    unsigned int bitstream_size, bytestream_size, wordstream_size, extra,

                 bytestream_offset, wordstream_offset;



    if (f->version > 1) {

        extra           = 20;

        if (length < extra)

            return -1;

        bitstream_size  = AV_RL32(buf + 8);

        wordstream_size = AV_RL32(buf + 12);

        bytestream_size = AV_RL32(buf + 16);

    } else {

        extra           = 0;

        bitstream_size  = AV_RL16(buf - 4);

        wordstream_size = AV_RL16(buf - 2);

        bytestream_size = FFMAX(length - bitstream_size - wordstream_size, 0);

    }



    if (bitstream_size > length ||

        bytestream_size > length - bitstream_size ||

        wordstream_size > length - bytestream_size - bitstream_size ||

        extra > length - bytestream_size - bitstream_size - wordstream_size) {

        av_log(f->avctx, AV_LOG_ERROR, "lengths %d %d %d %d\n", bitstream_size, bytestream_size, wordstream_size,

        bitstream_size+ bytestream_size+ wordstream_size - length);

        return -1;

    }



    av_fast_malloc(&f->bitstream_buffer, &f->bitstream_buffer_size,

                   bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE);

    if (!f->bitstream_buffer)

        return AVERROR(ENOMEM);

    f->dsp.bswap_buf(f->bitstream_buffer, (const uint32_t*)(buf + extra),

                     bitstream_size / 4);

    memset((uint8_t*)f->bitstream_buffer + bitstream_size,

           0, FF_INPUT_BUFFER_PADDING_SIZE);

    init_get_bits(&f->gb, f->bitstream_buffer, 8 * bitstream_size);



    wordstream_offset = extra + bitstream_size;

    bytestream_offset = extra + bitstream_size + wordstream_size;

    bytestream2_init(&f->g2, buf + wordstream_offset,

                     length - wordstream_offset);

    bytestream2_init(&f->g, buf + bytestream_offset,

                     length - bytestream_offset);



    init_mv(f);



    for (y = 0; y < height; y += 8) {

        for (x = 0; x < width; x += 8)

            decode_p_block(f, dst + x, src + x, 3, 3, stride);

        src += 8 * stride;

        dst += 8 * stride;

    }



    return 0;

}
