static int mxpeg_decode_frame(AVCodecContext *avctx,

                          void *data, int *got_frame,

                          AVPacket *avpkt)

{

    const uint8_t *buf = avpkt->data;

    int buf_size = avpkt->size;

    MXpegDecodeContext *s = avctx->priv_data;

    MJpegDecodeContext *jpg = &s->jpg;

    const uint8_t *buf_end, *buf_ptr;

    const uint8_t *unescaped_buf_ptr;

    int unescaped_buf_size;

    int start_code;

    int ret;



    buf_ptr = buf;

    buf_end = buf + buf_size;

    jpg->got_picture = 0;

    s->got_mxm_bitmask = 0;

    while (buf_ptr < buf_end) {

        start_code = ff_mjpeg_find_marker(jpg, &buf_ptr, buf_end,

                                          &unescaped_buf_ptr, &unescaped_buf_size);

        if (start_code < 0)

            goto the_end;

        {

            init_get_bits(&jpg->gb, unescaped_buf_ptr, unescaped_buf_size*8);



            if (start_code >= APP0 && start_code <= APP15) {

                mxpeg_decode_app(s, unescaped_buf_ptr, unescaped_buf_size);

            }



            switch (start_code) {

            case SOI:

                if (jpg->got_picture) //emulating EOI

                    goto the_end;

                break;

            case EOI:

                goto the_end;

            case DQT:

                ret = ff_mjpeg_decode_dqt(jpg);

                if (ret < 0) {

                    av_log(avctx, AV_LOG_ERROR,

                           "quantization table decode error\n");

                    return ret;

                }

                break;

            case DHT:

                ret = ff_mjpeg_decode_dht(jpg);

                if (ret < 0) {

                    av_log(avctx, AV_LOG_ERROR,

                           "huffman table decode error\n");

                    return ret;

                }

                break;

            case COM:

                ret = mxpeg_decode_com(s, unescaped_buf_ptr,

                                       unescaped_buf_size);

                if (ret < 0)

                    return ret;

                break;

            case SOF0:

                s->got_sof_data = 0;

                ret = ff_mjpeg_decode_sof(jpg);

                if (ret < 0) {

                    av_log(avctx, AV_LOG_ERROR,

                           "SOF data decode error\n");

                    return ret;

                }

                if (jpg->interlaced) {

                    av_log(avctx, AV_LOG_ERROR,

                           "Interlaced mode not supported in MxPEG\n");

                    return AVERROR(EINVAL);

                }

                s->got_sof_data = 1;

                break;

            case SOS:

                if (!s->got_sof_data) {

                    av_log(avctx, AV_LOG_WARNING,

                           "Can not process SOS without SOF data, skipping\n");

                    break;

                }

                if (!jpg->got_picture) {

                    if (jpg->first_picture) {

                        av_log(avctx, AV_LOG_WARNING,

                               "First picture has no SOF, skipping\n");

                        break;

                    }

                    if (!s->got_mxm_bitmask){

                        av_log(avctx, AV_LOG_WARNING,

                               "Non-key frame has no MXM, skipping\n");

                        break;

                    }

                    /* use stored SOF data to allocate current picture */

                    av_frame_unref(jpg->picture_ptr);

                    if ((ret = ff_get_buffer(avctx, jpg->picture_ptr,

                                             AV_GET_BUFFER_FLAG_REF)) < 0)

                        return ret;

                    jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_P;

                    jpg->picture_ptr->key_frame = 0;

                    jpg->got_picture = 1;

                } else {

                    jpg->picture_ptr->pict_type = AV_PICTURE_TYPE_I;

                    jpg->picture_ptr->key_frame = 1;

                }



                if (s->got_mxm_bitmask) {

                    AVFrame *reference_ptr = s->picture[s->picture_index ^ 1];

                    if (mxpeg_check_dimensions(s, jpg, reference_ptr) < 0)

                        break;



                    /* allocate dummy reference picture if needed */

                    if (!reference_ptr->data[0] &&

                        (ret = ff_get_buffer(avctx, reference_ptr,

                                             AV_GET_BUFFER_FLAG_REF)) < 0)

                        return ret;



                    ret = ff_mjpeg_decode_sos(jpg, s->mxm_bitmask, reference_ptr);

                    if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))

                        return ret;

                } else {

                    ret = ff_mjpeg_decode_sos(jpg, NULL, NULL);

                    if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))

                        return ret;

                }



                break;

            }



            buf_ptr += (get_bits_count(&jpg->gb)+7) >> 3;

        }



    }



the_end:

    if (jpg->got_picture) {

        int ret = av_frame_ref(data, jpg->picture_ptr);

        if (ret < 0)

            return ret;

        *got_frame = 1;



        s->picture_index ^= 1;

        jpg->picture_ptr = s->picture[s->picture_index];



        if (!s->has_complete_frame) {

            if (!s->got_mxm_bitmask)

                s->has_complete_frame = 1;

            else

                *got_frame = 0;

        }

    }



    return buf_ptr - buf;

}
