static int bfi_decode_frame(AVCodecContext *avctx, void *data,

                            int *data_size, AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data, *buf_end = avpkt->data + avpkt->size;

    int buf_size = avpkt->size;

    BFIContext *bfi = avctx->priv_data;

    uint8_t *dst = bfi->dst;

    uint8_t *src, *dst_offset, colour1, colour2;

    uint8_t *frame_end = bfi->dst + avctx->width * avctx->height;

    uint32_t *pal;

    int i, j, height = avctx->height;



    if (bfi->frame.data[0])

        avctx->release_buffer(avctx, &bfi->frame);



    bfi->frame.reference = 1;



    if (avctx->get_buffer(avctx, &bfi->frame) < 0) {

        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");

        return -1;

    }



    /* Set frame parameters and palette, if necessary */

    if (!avctx->frame_number) {

        bfi->frame.pict_type = AV_PICTURE_TYPE_I;

        bfi->frame.key_frame = 1;

        /* Setting the palette */

        if (avctx->extradata_size > 768) {

            av_log(NULL, AV_LOG_ERROR, "Palette is too large.\n");

            return -1;

        }

        pal = (uint32_t *)bfi->frame.data[1];

        for (i = 0; i < avctx->extradata_size / 3; i++) {

            int shift = 16;

            *pal = 0;

            for (j = 0; j < 3; j++, shift -= 8)

                *pal +=

                    ((avctx->extradata[i * 3 + j] << 2) |

                    (avctx->extradata[i * 3 + j] >> 4)) << shift;

            pal++;

        }

        bfi->frame.palette_has_changed = 1;

    } else {

        bfi->frame.pict_type = AV_PICTURE_TYPE_P;

        bfi->frame.key_frame = 0;

    }



    buf += 4; // Unpacked size, not required.



    while (dst != frame_end) {

        static const uint8_t lentab[4] = { 0, 2, 0, 1 };

        unsigned int byte   = *buf++, av_uninit(offset);

        unsigned int code   = byte >> 6;

        unsigned int length = byte & ~0xC0;



        if (buf >= buf_end) {

            av_log(avctx, AV_LOG_ERROR,

                   "Input resolution larger than actual frame.\n");

            return -1;

        }



        /* Get length and offset(if required) */

        if (length == 0) {

            if (code == 1) {

                length = bytestream_get_byte(&buf);

                offset = bytestream_get_le16(&buf);

            } else {

                length = bytestream_get_le16(&buf);

                if (code == 2 && length == 0)

                    break;

            }

        } else {

            if (code == 1)

                offset = bytestream_get_byte(&buf);

        }



        /* Do boundary check */

        if (dst + (length << lentab[code]) > frame_end)

            break;



        switch (code) {



        case 0:                //Normal Chain

            if (length >= buf_end - buf) {

                av_log(avctx, AV_LOG_ERROR, "Frame larger than buffer.\n");

                return -1;

            }

            bytestream_get_buffer(&buf, dst, length);

            dst += length;

            break;



        case 1:                //Back Chain

            dst_offset = dst - offset;

            length *= 4;        //Convert dwords to bytes.

            if (dst_offset < bfi->dst)

                break;

            while (length--)

                *dst++ = *dst_offset++;

            break;



        case 2:                //Skip Chain

            dst += length;

            break;



        case 3:                //Fill Chain

            colour1 = bytestream_get_byte(&buf);

            colour2 = bytestream_get_byte(&buf);

            while (length--) {

                *dst++ = colour1;

                *dst++ = colour2;

            }

            break;



        }

    }



    src = bfi->dst;

    dst = bfi->frame.data[0];

    while (height--) {

        memcpy(dst, src, avctx->width);

        src += avctx->width;

        dst += bfi->frame.linesize[0];

    }

    *data_size = sizeof(AVFrame);

    *(AVFrame *)data = bfi->frame;

    return buf_size;

}

static int bfi_decode_frame(AVCodecContext *avctx, void *data,

                            int *data_size, AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data, *buf_end = avpkt->data + avpkt->size;

    int buf_size = avpkt->size;

    BFIContext *bfi = avctx->priv_data;

    uint8_t *dst = bfi->dst;

    uint8_t *src, *dst_offset, colour1, colour2;

    uint8_t *frame_end = bfi->dst + avctx->width * avctx->height;

    uint32_t *pal;

    int i, j, height = avctx->height;



    if (bfi->frame.data[0])

        avctx->release_buffer(avctx, &bfi->frame);



    bfi->frame.reference = 1;



    if (avctx->get_buffer(avctx, &bfi->frame) < 0) {

        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");

        return -1;

    }



    

    if (!avctx->frame_number) {

        bfi->frame.pict_type = AV_PICTURE_TYPE_I;

        bfi->frame.key_frame = 1;

        

        if (avctx->extradata_size > 768) {

            av_log(NULL, AV_LOG_ERROR, "Palette is too large.\n");

            return -1;

        }

        pal = (uint32_t *)bfi->frame.data[1];

        for (i = 0; i < avctx->extradata_size / 3; i++) {

            int shift = 16;

            *pal = 0;

            for (j = 0; j < 3; j++, shift -= 8)

                *pal +=

                    ((avctx->extradata[i * 3 + j] << 2) |

                    (avctx->extradata[i * 3 + j] >> 4)) << shift;

            pal++;

        }

        bfi->frame.palette_has_changed = 1;

    } else {

        bfi->frame.pict_type = AV_PICTURE_TYPE_P;

        bfi->frame.key_frame = 0;

    }



    buf += 4; 



    while (dst != frame_end) {

        static const uint8_t lentab[4] = { 0, 2, 0, 1 };

        unsigned int byte   = *buf++, av_uninit(offset);

        unsigned int code   = byte >> 6;

        unsigned int length = byte & ~0xC0;



        if (buf >= buf_end) {

            av_log(avctx, AV_LOG_ERROR,

                   "Input resolution larger than actual frame.\n");

            return -1;

        }



        

        if (length == 0) {

            if (code == 1) {

                length = bytestream_get_byte(&buf);

                offset = bytestream_get_le16(&buf);

            } else {

                length = bytestream_get_le16(&buf);

                if (code == 2 && length == 0)

                    break;

            }

        } else {

            if (code == 1)

                offset = bytestream_get_byte(&buf);

        }



        

        if (dst + (length << lentab[code]) > frame_end)

            break;



        switch (code) {



        case 0:                

            if (length >= buf_end - buf) {

                av_log(avctx, AV_LOG_ERROR, "Frame larger than buffer.\n");

                return -1;

            }

            bytestream_get_buffer(&buf, dst, length);

            dst += length;

            break;



        case 1:                

            dst_offset = dst - offset;

            length *= 4;        

            if (dst_offset < bfi->dst)

                break;

            while (length--)

                *dst++ = *dst_offset++;

            break;



        case 2:                

            dst += length;

            break;



        case 3:                

            colour1 = bytestream_get_byte(&buf);

            colour2 = bytestream_get_byte(&buf);

            while (length--) {

                *dst++ = colour1;

                *dst++ = colour2;

            }

            break;



        }

    }



    src = bfi->dst;

    dst = bfi->frame.data[0];

    while (height--) {

        memcpy(dst, src, avctx->width);

        src += avctx->width;

        dst += bfi->frame.linesize[0];

    }

    *data_size = sizeof(AVFrame);

    *(AVFrame *)data = bfi->frame;

    return buf_size;

}

    const uint8_t *buf = avpkt->data, *buf_end = avpkt->data + avpkt->size;         unsigned int byte   = *buf++, av_uninit(offset);         if (buf >= buf_end) {                 length = bytestream_get_byte(&buf);                 offset = bytestream_get_le16(&buf);                 length = bytestream_get_le16(&buf);                 offset = bytestream_get_byte(&buf);             if (length >= buf_end - buf) {             bytestream_get_buffer(&buf, dst, length);             colour1 = bytestream_get_byte(&buf);             colour2 = bytestream_get_byte(&buf);
static int FUNC_0(AVCodecContext *VAR_0, void *VAR_1,

                            int *VAR_2, AVPacket *VAR_3)

{

    const uint8_t *VAR_4 = VAR_3->VAR_1, *buf_end = VAR_3->VAR_1 + VAR_3->size;

    int VAR_5 = VAR_3->size;

    BFIContext *bfi = VAR_0->priv_data;

    uint8_t *dst = bfi->dst;

    uint8_t *src, *dst_offset, colour1, colour2;

    uint8_t *frame_end = bfi->dst + VAR_0->width * VAR_0->VAR_8;

    uint32_t *pal;

    int VAR_6, VAR_7, VAR_8 = VAR_0->VAR_8;



    if (bfi->frame.VAR_1[0])

        VAR_0->release_buffer(VAR_0, &bfi->frame);



    bfi->frame.reference = 1;



    if (VAR_0->get_buffer(VAR_0, &bfi->frame) < 0) {

        av_log(VAR_0, AV_LOG_ERROR, "get_buffer() failed\n");

        return -1;

    }



    

    if (!VAR_0->frame_number) {

        bfi->frame.pict_type = AV_PICTURE_TYPE_I;

        bfi->frame.key_frame = 1;

        

        if (VAR_0->extradata_size > 768) {

            av_log(NULL, AV_LOG_ERROR, "Palette is too large.\n");

            return -1;

        }

        pal = (uint32_t *)bfi->frame.VAR_1[1];

        for (VAR_6 = 0; VAR_6 < VAR_0->extradata_size / 3; VAR_6++) {

            int shift = 16;

            *pal = 0;

            for (VAR_7 = 0; VAR_7 < 3; VAR_7++, shift -= 8)

                *pal +=

                    ((VAR_0->extradata[VAR_6 * 3 + VAR_7] << 2) |

                    (VAR_0->extradata[VAR_6 * 3 + VAR_7] >> 4)) << shift;

            pal++;

        }

        bfi->frame.palette_has_changed = 1;

    } else {

        bfi->frame.pict_type = AV_PICTURE_TYPE_P;

        bfi->frame.key_frame = 0;

    }



    VAR_4 += 4; 



    while (dst != frame_end) {

        static const uint8_t VAR_9[4] = { 0, 2, 0, 1 };

        unsigned int VAR_10   = *VAR_4++, FUNC_1(offset);

        unsigned int VAR_11   = VAR_10 >> 6;

        unsigned int VAR_12 = VAR_10 & ~0xC0;



        if (VAR_4 >= buf_end) {

            av_log(VAR_0, AV_LOG_ERROR,

                   "Input resolution larger than actual frame.\n");

            return -1;

        }



        

        if (VAR_12 == 0) {

            if (VAR_11 == 1) {

                VAR_12 = bytestream_get_byte(&VAR_4);

                offset = bytestream_get_le16(&VAR_4);

            } else {

                VAR_12 = bytestream_get_le16(&VAR_4);

                if (VAR_11 == 2 && VAR_12 == 0)

                    break;

            }

        } else {

            if (VAR_11 == 1)

                offset = bytestream_get_byte(&VAR_4);

        }



        

        if (dst + (VAR_12 << VAR_9[VAR_11]) > frame_end)

            break;



        switch (VAR_11) {



        case 0:                

            if (VAR_12 >= buf_end - VAR_4) {

                av_log(VAR_0, AV_LOG_ERROR, "Frame larger than buffer.\n");

                return -1;

            }

            bytestream_get_buffer(&VAR_4, dst, VAR_12);

            dst += VAR_12;

            break;



        case 1:                

            dst_offset = dst - offset;

            VAR_12 *= 4;        

            if (dst_offset < bfi->dst)

                break;

            while (VAR_12--)

                *dst++ = *dst_offset++;

            break;



        case 2:                

            dst += VAR_12;

            break;



        case 3:                

            colour1 = bytestream_get_byte(&VAR_4);

            colour2 = bytestream_get_byte(&VAR_4);

            while (VAR_12--) {

                *dst++ = colour1;

                *dst++ = colour2;

            }

            break;



        }

    }



    src = bfi->dst;

    dst = bfi->frame.VAR_1[0];

    while (VAR_8--) {

        memcpy(dst, src, VAR_0->width);

        src += VAR_0->width;

        dst += bfi->frame.linesize[0];

    }

    *VAR_2 = sizeof(AVFrame);

    *(AVFrame *)VAR_1 = bfi->frame;

    return VAR_5;

}

static int FUNC_0(AVCodecContext *VAR_0, void *VAR_1,
int *VAR_2, AVPacket *VAR_3)
{ const uint8_t *VAR_4 = VAR_3->VAR_1, *buf_end = VAR_3->VAR_1 + VAR_3->size; int VAR_5 = VAR_3->size; BFIContext *bfi = VAR_0->priv_data; uint8_t *dst = bfi->dst; uint8_t *src, *dst_offset, colour1, colour2; uint8_t *frame_end = bfi->dst + VAR_0->width * VAR_0->VAR_8; uint32_t *pal; int VAR_6, VAR_7, VAR_8 = VAR_0->VAR_8; if (bfi->frame.VAR_1[0])
VAR_0->release_buffer(VAR_0, &bfi->frame); bfi->frame.reference = 1; if (VAR_0->get_buffer(VAR_0, &bfi->frame) < 0) { av_log(VAR_0, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } if (!VAR_0->frame_number) { bfi->frame.pict_type = AV_PICTURE_TYPE_I; bfi->frame.key_frame = 1; if (VAR_0->extradata_size > 768) { av_log(NULL, AV_LOG_ERROR, "Palette is too large.\n"); return -1; } pal = (uint32_t *)bfi->frame.VAR_1[1]; for (VAR_6 = 0; VAR_6 < VAR_0->extradata_size / 3; VAR_6++) { int shift = 16; *pal = 0; for (VAR_7 = 0; VAR_7 < 3; VAR_7++, shift -= 8) *pal +=
((VAR_0->extradata[VAR_6 * 3 + VAR_7] << 2) |
(VAR_0->extradata[VAR_6 * 3 + VAR_7] >> 4)) << shift; pal++; } bfi->frame.palette_has_changed = 1; } else { bfi->frame.pict_type = AV_PICTURE_TYPE_P; bfi->frame.key_frame = 0; } VAR_4 += 4; while (dst != frame_end) { static const uint8_t VAR_9[4] = { 0, 2, 0, 1 }; unsigned int VAR_10   = *VAR_4++, FUNC_1(offset); unsigned int VAR_11   = VAR_10 >> 6; unsigned int VAR_12 = VAR_10 & ~0xC0; if (VAR_4 >= buf_end) { av_log(VAR_0, AV_LOG_ERROR,
"Input resolution larger than actual frame.\n"); return -1; } if (VAR_12 == 0) { if (VAR_11 == 1) { VAR_12 = bytestream_get_byte(&VAR_4); offset = bytestream_get_le16(&VAR_4); } else { VAR_12 = bytestream_get_le16(&VAR_4); if (VAR_11 == 2 && VAR_12 == 0)
break; } } else { if (VAR_11 == 1)
offset = bytestream_get_byte(&VAR_4); } if (dst + (VAR_12 << VAR_9[VAR_11]) > frame_end)
break; switch (VAR_11) { case 0:
if (VAR_12 >= buf_end - VAR_4) { av_log(VAR_0, AV_LOG_ERROR, "Frame larger than buffer.\n"); return -1; } bytestream_get_buffer(&VAR_4, dst, VAR_12); dst += VAR_12; break; case 1:
dst_offset = dst - offset; VAR_12 *= 4; if (dst_offset < bfi->dst)
break; while (VAR_12--)
*dst++ = *dst_offset++; break; case 2:
dst += VAR_12; break; case 3:
colour1 = bytestream_get_byte(&VAR_4); colour2 = bytestream_get_byte(&VAR_4); while (VAR_12--) { *dst++ = colour1; *dst++ = colour2; } break; } } src = bfi->dst; dst = bfi->frame.VAR_1[0]; while (VAR_8--) { memcpy(dst, src, VAR_0->width); src += VAR_0->width; dst += bfi->frame.linesize[0]; } *VAR_2 = sizeof(AVFrame); *(AVFrame *)VAR_1 = bfi->frame; return VAR_5; }