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

                            int *data_size, const uint8_t * buf,

                            int buf_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 = FF_I_TYPE;

        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 = FF_P_TYPE;

        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++, offset;

        unsigned int code = byte >> 6;

        unsigned int length = byte & ~0xC0;



        /* 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

            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, const uint8_t * buf,

                            int buf_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 = FF_I_TYPE;

        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 = FF_P_TYPE;

        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++, offset;

        unsigned int code = byte >> 6;

        unsigned int length = byte & ~0xC0;



        

        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:                

            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;

}

        unsigned int byte = *buf++, offset;
static int FUNC_0(AVCodecContext * VAR_0, void *VAR_1,

                            int *VAR_2, const uint8_t * VAR_3,

                            int VAR_4)

{

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

    uint32_t *pal;

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



    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 = FF_I_TYPE;

        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_5 = 0; VAR_5 < VAR_0->extradata_size / 3; VAR_5++) {

            int shift = 16;

            *pal = 0;

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

                *pal +=

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

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

            pal++;

        }

        bfi->frame.palette_has_changed = 1;

    } else {

        bfi->frame.pict_type = FF_P_TYPE;

        bfi->frame.key_frame = 0;

    }



    VAR_3 += 4; 



    while (dst != frame_end) {

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

        unsigned int VAR_9 = *VAR_3++, VAR_10;

        unsigned int VAR_11 = VAR_9 >> 6;

        unsigned int VAR_12 = VAR_9 & ~0xC0;



        

        if (VAR_12 == 0) {

            if (VAR_11 == 1) {

                VAR_12 = bytestream_get_byte(&VAR_3);

                VAR_10 = bytestream_get_le16(&VAR_3);

            } else {

                VAR_12 = bytestream_get_le16(&VAR_3);

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

                    break;

            }

        } else {

            if (VAR_11 == 1)

                VAR_10 = bytestream_get_byte(&VAR_3);

        }



        

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

            break;



        switch (VAR_11) {



        case 0:                

            bytestream_get_buffer(&VAR_3, dst, VAR_12);

            dst += VAR_12;

            break;



        case 1:                

            dst_offset = dst - VAR_10;

            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_3);

            colour2 = bytestream_get_byte(&VAR_3);

            while (VAR_12--) {

                *dst++ = colour1;

                *dst++ = colour2;

            }

            break;



        }

    }



    src = bfi->dst;

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

    while (VAR_7--) {

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

}

static int FUNC_0(AVCodecContext * VAR_0, void *VAR_1,
int *VAR_2, const uint8_t * VAR_3,
int VAR_4)
{ 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_7; uint32_t *pal; int VAR_5, VAR_6, VAR_7 = VAR_0->VAR_7; 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 = FF_I_TYPE; 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_5 = 0; VAR_5 < VAR_0->extradata_size / 3; VAR_5++) { int shift = 16; *pal = 0; for (VAR_6 = 0; VAR_6 < 3; VAR_6++, shift -= 8) *pal +=
((VAR_0->extradata[VAR_5 * 3 + VAR_6] << 2) |
(VAR_0->extradata[VAR_5 * 3 + VAR_6] >> 4)) << shift; pal++; } bfi->frame.palette_has_changed = 1; } else { bfi->frame.pict_type = FF_P_TYPE; bfi->frame.key_frame = 0; } VAR_3 += 4; while (dst != frame_end) { static const uint8_t VAR_8[4]={0,2,0,1}; unsigned int VAR_9 = *VAR_3++, VAR_10; unsigned int VAR_11 = VAR_9 >> 6; unsigned int VAR_12 = VAR_9 & ~0xC0; if (VAR_12 == 0) { if (VAR_11 == 1) { VAR_12 = bytestream_get_byte(&VAR_3); VAR_10 = bytestream_get_le16(&VAR_3); } else { VAR_12 = bytestream_get_le16(&VAR_3); if (VAR_11 == 2 && VAR_12 == 0)
break; } } else { if (VAR_11 == 1)
VAR_10 = bytestream_get_byte(&VAR_3); } if (dst + (VAR_12<<VAR_8[VAR_11]) > frame_end)
break; switch (VAR_11) { case 0:
bytestream_get_buffer(&VAR_3, dst, VAR_12); dst += VAR_12; break; case 1:
dst_offset = dst - VAR_10; 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_3); colour2 = bytestream_get_byte(&VAR_3); while (VAR_12--) { *dst++ = colour1; *dst++ = colour2; } break; } } src = bfi->dst; dst = bfi->frame.VAR_1[0]; while (VAR_7--) { 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_4; }