static int escape124_decode_frame(AVCodecContext *avctx,

                                  void *data, int *got_frame,

                                  AVPacket *avpkt)

{

    int buf_size = avpkt->size;

    Escape124Context *s = avctx->priv_data;

    AVFrame *frame = data;



    GetBitContext gb;

    unsigned frame_flags, frame_size;

    unsigned i;



    unsigned superblock_index, cb_index = 1,

             superblock_col_index = 0,

             superblocks_per_row = avctx->width / 8, skip = -1;



    uint16_t* old_frame_data, *new_frame_data;

    unsigned old_stride, new_stride;



    int ret;



    if ((ret = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)

        return ret;



    // This call also guards the potential depth reads for the

    // codebook unpacking.

    if (!can_safely_read(&gb, 64))

        return -1;



    frame_flags = get_bits_long(&gb, 32);

    frame_size  = get_bits_long(&gb, 32);



    // Leave last frame unchanged

    // FIXME: Is this necessary?  I haven't seen it in any real samples

    if (!(frame_flags & 0x114) || !(frame_flags & 0x7800000)) {

        if (!s->frame.data[0])

            return AVERROR_INVALIDDATA;



        av_log(avctx, AV_LOG_DEBUG, "Skipping frame\n");



        *got_frame = 1;

        if ((ret = av_frame_ref(frame, &s->frame)) < 0)

            return ret;



        return frame_size;

    }



    for (i = 0; i < 3; i++) {

        if (frame_flags & (1 << (17 + i))) {

            unsigned cb_depth, cb_size;

            if (i == 2) {

                // This codebook can be cut off at places other than

                // powers of 2, leaving some of the entries undefined.

                cb_size = get_bits_long(&gb, 20);

                cb_depth = av_log2(cb_size - 1) + 1;

            } else {

                cb_depth = get_bits(&gb, 4);

                if (i == 0) {

                    // This is the most basic codebook: pow(2,depth) entries

                    // for a depth-length key

                    cb_size = 1 << cb_depth;

                } else {

                    // This codebook varies per superblock

                    // FIXME: I don't think this handles integer overflow

                    // properly

                    cb_size = s->num_superblocks << cb_depth;

                }

            }

            av_free(s->codebooks[i].blocks);

            s->codebooks[i] = unpack_codebook(&gb, cb_depth, cb_size);

            if (!s->codebooks[i].blocks)

                return -1;

        }

    }



    if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)

        return ret;



    new_frame_data = (uint16_t*)frame->data[0];

    new_stride = frame->linesize[0] / 2;

    old_frame_data = (uint16_t*)s->frame.data[0];

    old_stride = s->frame.linesize[0] / 2;



    for (superblock_index = 0; superblock_index < s->num_superblocks;

         superblock_index++) {

        MacroBlock mb;

        SuperBlock sb;

        unsigned multi_mask = 0;



        if (skip == -1) {

            // Note that this call will make us skip the rest of the blocks

            // if the frame prematurely ends

            skip = decode_skip_count(&gb);

        }



        if (skip) {

            copy_superblock(new_frame_data, new_stride,

                            old_frame_data, old_stride);

        } else {

            copy_superblock(sb.pixels, 8,

                            old_frame_data, old_stride);



            while (can_safely_read(&gb, 1) && !get_bits1(&gb)) {

                unsigned mask;

                mb = decode_macroblock(s, &gb, &cb_index, superblock_index);

                mask = get_bits(&gb, 16);

                multi_mask |= mask;

                for (i = 0; i < 16; i++) {

                    if (mask & mask_matrix[i]) {

                        insert_mb_into_sb(&sb, mb, i);

                    }

                }

            }



            if (can_safely_read(&gb, 1) && !get_bits1(&gb)) {

                unsigned inv_mask = get_bits(&gb, 4);

                for (i = 0; i < 4; i++) {

                    if (inv_mask & (1 << i)) {

                        multi_mask ^= 0xF << i*4;

                    } else {

                        multi_mask ^= get_bits(&gb, 4) << i*4;

                    }

                }



                for (i = 0; i < 16; i++) {

                    if (multi_mask & mask_matrix[i]) {

                        if (!can_safely_read(&gb, 1))

                            break;

                        mb = decode_macroblock(s, &gb, &cb_index,

                                               superblock_index);

                        insert_mb_into_sb(&sb, mb, i);

                    }

                }

            } else if (frame_flags & (1 << 16)) {

                while (can_safely_read(&gb, 1) && !get_bits1(&gb)) {

                    mb = decode_macroblock(s, &gb, &cb_index, superblock_index);

                    insert_mb_into_sb(&sb, mb, get_bits(&gb, 4));

                }

            }



            copy_superblock(new_frame_data, new_stride, sb.pixels, 8);

        }



        superblock_col_index++;

        new_frame_data += 8;

        if (old_frame_data)

            old_frame_data += 8;

        if (superblock_col_index == superblocks_per_row) {

            new_frame_data += new_stride * 8 - superblocks_per_row * 8;

            if (old_frame_data)

                old_frame_data += old_stride * 8 - superblocks_per_row * 8;

            superblock_col_index = 0;

        }

        skip--;

    }



    av_log(avctx, AV_LOG_DEBUG,

           "Escape sizes: %i, %i, %i\n",

           frame_size, buf_size, get_bits_count(&gb) / 8);



    av_frame_unref(&s->frame);

    if ((ret = av_frame_ref(&s->frame, frame)) < 0)

        return ret;



    *got_frame = 1;



    return frame_size;

}
