int ff_rv34_decode_frame(AVCodecContext *avctx,
                            void *data, int *got_picture_ptr,
                            AVPacket *avpkt)
{
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;
    RV34DecContext *r = avctx->priv_data;
    MpegEncContext *s = &r->s;
    AVFrame *pict = data;
    SliceInfo si;
    int i;
    int slice_count;
    const uint8_t *slices_hdr = NULL;
    int last = 0;
    /* no supplementary picture */
    if (buf_size == 0) {
        /* special case for last picture */
        if (s->low_delay==0 && s->next_picture_ptr) {
            *pict = s->next_picture_ptr->f;
            s->next_picture_ptr = NULL;
            *got_picture_ptr = 1;
        }
        return 0;
    }
    if(!avctx->slice_count){
        slice_count = (*buf++) + 1;
        slices_hdr = buf + 4;
        buf += 8 * slice_count;
        buf_size -= 1 + 8 * slice_count;
    }else
        slice_count = avctx->slice_count;
    //parse first slice header to check whether this frame can be decoded
    if(get_slice_offset(avctx, slices_hdr, 0) < 0 ||
       get_slice_offset(avctx, slices_hdr, 0) > buf_size){
        av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n");
    }
    init_get_bits(&s->gb, buf+get_slice_offset(avctx, slices_hdr, 0), (buf_size-get_slice_offset(avctx, slices_hdr, 0))*8);
    if(r->parse_slice_header(r, &r->s.gb, &si) < 0 || si.start){
        av_log(avctx, AV_LOG_ERROR, "First slice header is incorrect\n");
    }
    if ((!s->last_picture_ptr || !s->last_picture_ptr->f.data[0]) &&
        si.type == AV_PICTURE_TYPE_B) {
        av_log(avctx, AV_LOG_ERROR, "Invalid decoder state: B-frame without "
               "reference data.\n");
    }
    if(   (avctx->skip_frame >= AVDISCARD_NONREF && si.type==AV_PICTURE_TYPE_B)
       || (avctx->skip_frame >= AVDISCARD_NONKEY && si.type!=AV_PICTURE_TYPE_I)
       ||  avctx->skip_frame >= AVDISCARD_ALL)
        return avpkt->size;
    /* first slice */
    if (si.start == 0) {
        if (s->mb_num_left > 0) {
            av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n",
                   s->mb_num_left);
            ff_er_frame_end(s);
            ff_MPV_frame_end(s);
        }
        if (s->width != si.width || s->height != si.height) {
            int err;
            av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n",
                   si.width, si.height);
            s->width  = si.width;
            s->height = si.height;
            avcodec_set_dimensions(s->avctx, s->width, s->height);
            if ((err = ff_MPV_common_frame_size_change(s)) < 0)
                return err;
            if ((err = rv34_decoder_realloc(r)) < 0)
                return err;
        }
        s->pict_type = si.type ? si.type : AV_PICTURE_TYPE_I;
        if (ff_MPV_frame_start(s, s->avctx) < 0)
            return -1;
        ff_er_frame_start(s);
        if (!r->tmp_b_block_base) {
            int i;
            r->tmp_b_block_base = av_malloc(s->linesize * 48);
            for (i = 0; i < 2; i++)
                r->tmp_b_block_y[i] = r->tmp_b_block_base
                                      + i * 16 * s->linesize;
            for (i = 0; i < 4; i++)
                r->tmp_b_block_uv[i] = r->tmp_b_block_base + 32 * s->linesize
                                       + (i >> 1) * 8 * s->uvlinesize
                                       + (i &  1) * 16;
        }
        r->cur_pts = si.pts;
        if (s->pict_type != AV_PICTURE_TYPE_B) {
            r->last_pts = r->next_pts;
            r->next_pts = r->cur_pts;
        } else {
            int refdist = GET_PTS_DIFF(r->next_pts, r->last_pts);
            int dist0   = GET_PTS_DIFF(r->cur_pts,  r->last_pts);
            int dist1   = GET_PTS_DIFF(r->next_pts, r->cur_pts);
            if(!refdist){
                r->mv_weight1 = r->mv_weight2 = r->weight1 = r->weight2 = 8192;
                r->scaled_weight = 0;
            }else{
                r->mv_weight1 = (dist0 << 14) / refdist;
                r->mv_weight2 = (dist1 << 14) / refdist;
                if((r->mv_weight1|r->mv_weight2) & 511){
                    r->weight1 = r->mv_weight1;
                    r->weight2 = r->mv_weight2;
                    r->scaled_weight = 0;
                }else{
                    r->weight1 = r->mv_weight1 >> 9;
                    r->weight2 = r->mv_weight2 >> 9;
                    r->scaled_weight = 1;
                }
            }
        }
        s->mb_x = s->mb_y = 0;
        ff_thread_finish_setup(s->avctx);
    } else if (HAVE_THREADS &&
               (s->avctx->active_thread_type & FF_THREAD_FRAME)) {
        av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames in frame "
               "multithreading mode (start MB is %d).\n", si.start);
    }
    for(i = 0; i < slice_count; i++){
        int offset = get_slice_offset(avctx, slices_hdr, i);
        int size;
        if(i+1 == slice_count)
            size = buf_size - offset;
        else
            size = get_slice_offset(avctx, slices_hdr, i+1) - offset;
        if(offset < 0 || offset > buf_size){
            av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n");
            break;
        }
        r->si.end = s->mb_width * s->mb_height;
        s->mb_num_left = r->s.mb_x + r->s.mb_y*r->s.mb_width - r->si.start;
        if(i+1 < slice_count){
            if (get_slice_offset(avctx, slices_hdr, i+1) < 0 ||
                get_slice_offset(avctx, slices_hdr, i+1) > buf_size) {
                av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n");
                break;
            }
            init_get_bits(&s->gb, buf+get_slice_offset(avctx, slices_hdr, i+1), (buf_size-get_slice_offset(avctx, slices_hdr, i+1))*8);
            if(r->parse_slice_header(r, &r->s.gb, &si) < 0){
                if(i+2 < slice_count)
                    size = get_slice_offset(avctx, slices_hdr, i+2) - offset;
                else
                    size = buf_size - offset;
            }else
                r->si.end = si.start;
        }
        if (size < 0 || size > buf_size - offset) {
            av_log(avctx, AV_LOG_ERROR, "Slice size is invalid\n");
            break;
        }
        last = rv34_decode_slice(r, r->si.end, buf + offset, size);
        if(last)
            break;
    }
    if (s->current_picture_ptr) {
        if (last) {
            if(r->loop_filter)
                r->loop_filter(r, s->mb_height - 1);
            *got_picture_ptr = finish_frame(avctx, pict);
        } else if (HAVE_THREADS &&
                   (s->avctx->active_thread_type & FF_THREAD_FRAME)) {
            av_log(avctx, AV_LOG_INFO, "marking unfished frame as finished\n");
            /* always mark the current frame as finished, frame-mt supports
             * only complete frames */
            ff_er_frame_end(s);
            ff_MPV_frame_end(s);
            s->mb_num_left = 0;
            ff_thread_report_progress(&s->current_picture_ptr->f, INT_MAX, 0);
        }
    }
    return avpkt->size;
}