static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
                            AVPacket *avpkt)
{
    VP8Context *s = avctx->priv_data;
    int ret, mb_x, mb_y, i, y, referenced;
    enum AVDiscard skip_thresh;
    AVFrame *av_uninit(curframe), *prev_frame;
    release_queued_segmaps(s, 0);
    if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0)
        return ret;
    prev_frame = s->framep[VP56_FRAME_CURRENT];
    referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT
                                || s->update_altref == VP56_FRAME_CURRENT;
    skip_thresh = !referenced ? AVDISCARD_NONREF :
                    !s->keyframe ? AVDISCARD_NONKEY : AVDISCARD_ALL;
    if (avctx->skip_frame >= skip_thresh) {
        s->invisible = 1;
        goto skip_decode;
    }
    s->deblock_filter = s->filter.level && avctx->skip_loop_filter < skip_thresh;
    for (i = 0; i < 5; i++)
        if (s->frames[i].data[0] &&
            &s->frames[i] != prev_frame &&
            &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&
            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&
            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2])
            vp8_release_frame(s, &s->frames[i], 1, 0);
    for (i = 0; i < 5; i++)
        if (&s->frames[i] != prev_frame &&
            &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&
            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&
            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) {
            curframe = s->framep[VP56_FRAME_CURRENT] = &s->frames[i];
            break;
        }
    if (i == 5) {
        av_log(avctx, AV_LOG_FATAL, "Ran out of free frames!\n");
        abort();
    }
    if (curframe->data[0])
        vp8_release_frame(s, curframe, 1, 0);
    curframe->key_frame = s->keyframe;
    curframe->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
    curframe->reference = referenced ? 3 : 0;
    if ((ret = vp8_alloc_frame(s, curframe))) {
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed!\n");
        return ret;
    }
    if (s->update_altref != VP56_FRAME_NONE) {
        s->next_framep[VP56_FRAME_GOLDEN2]  = s->framep[s->update_altref];
    } else {
        s->next_framep[VP56_FRAME_GOLDEN2]  = s->framep[VP56_FRAME_GOLDEN2];
    }
    if (s->update_golden != VP56_FRAME_NONE) {
        s->next_framep[VP56_FRAME_GOLDEN]   = s->framep[s->update_golden];
    } else {
        s->next_framep[VP56_FRAME_GOLDEN]   = s->framep[VP56_FRAME_GOLDEN];
    }
    if (s->update_last) {
        s->next_framep[VP56_FRAME_PREVIOUS] = curframe;
    } else {
        s->next_framep[VP56_FRAME_PREVIOUS] = s->framep[VP56_FRAME_PREVIOUS];
    }
    s->next_framep[VP56_FRAME_CURRENT]      = curframe;
    ff_thread_finish_setup(avctx);
    if (!s->keyframe && (!s->framep[VP56_FRAME_PREVIOUS] ||
                         !s->framep[VP56_FRAME_GOLDEN] ||
                         !s->framep[VP56_FRAME_GOLDEN2])) {
        av_log(avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n");
        return AVERROR_INVALIDDATA;
    }
    s->linesize   = curframe->linesize[0];
    s->uvlinesize = curframe->linesize[1];
    if (!s->edge_emu_buffer)
        s->edge_emu_buffer = av_malloc(21*s->linesize);
    memset(s->top_nnz, 0, s->mb_width*sizeof(*s->top_nnz));
    memset(s->macroblocks + s->mb_height*2 - 1, 0, (s->mb_width+1)*sizeof(*s->macroblocks));
    if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {
        s->top_border[0][15] = s->top_border[0][23] = 127;
        memset(s->top_border[1]-1, 127, s->mb_width*sizeof(*s->top_border)+1);
    }
    memset(s->ref_count, 0, sizeof(s->ref_count));
    if (s->keyframe)
        memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width*4);
#define MARGIN (16 << 2)
    s->mv_min.y = -MARGIN;
    s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
    for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
        VP56RangeCoder *c = &s->coeff_partition[mb_y & (s->num_coeff_partitions-1)];
        VP8Macroblock *mb = s->macroblocks + (s->mb_height - mb_y - 1)*2;
        int mb_xy = mb_y*s->mb_width;
        uint8_t *dst[3] = {
            curframe->data[0] + 16*mb_y*s->linesize,
            curframe->data[1] +  8*mb_y*s->uvlinesize,
            curframe->data[2] +  8*mb_y*s->uvlinesize
        };
        memset(mb - 1, 0, sizeof(*mb));
        memset(s->left_nnz, 0, sizeof(s->left_nnz));
        AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED*0x01010101);
        if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {
            for (i = 0; i < 3; i++)
                for (y = 0; y < 16>>!!i; y++)
                    dst[i][y*curframe->linesize[i]-1] = 129;
            if (mb_y == 1)
                s->top_border[0][15] = s->top_border[0][23] = s->top_border[0][31] = 129;
        }
        s->mv_min.x = -MARGIN;
        s->mv_max.x = ((s->mb_width  - 1) << 6) + MARGIN;
        if (prev_frame && s->segmentation.enabled && !s->segmentation.update_map)
            ff_thread_await_progress(prev_frame, mb_y, 0);
        for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) {
            s->dsp.prefetch(dst[0] + (mb_x&3)*4*s->linesize + 64, s->linesize, 4);
            s->dsp.prefetch(dst[1] + (mb_x&7)*s->uvlinesize + 64, dst[2] - dst[1], 2);
            decode_mb_mode(s, mb, mb_x, mb_y, curframe->ref_index[0] + mb_xy,
                           prev_frame && prev_frame->ref_index[0] ? prev_frame->ref_index[0] + mb_xy : NULL);
            prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS);
            if (!mb->skip)
                decode_mb_coeffs(s, c, mb, s->top_nnz[mb_x], s->left_nnz);
            if (mb->mode <= MODE_I4x4)
                intra_predict(s, dst, mb, mb_x, mb_y);
            else
                inter_predict(s, dst, mb, mb_x, mb_y);
            prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN);
            if (!mb->skip) {
                idct_mb(s, dst, mb);
            } else {
                AV_ZERO64(s->left_nnz);
                AV_WN64(s->top_nnz[mb_x], 0);
                if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) {
                    s->left_nnz[8]      = 0;
                    s->top_nnz[mb_x][8] = 0;
                }
            }
            if (s->deblock_filter)
                filter_level_for_mb(s, mb, &s->filter_strength[mb_x]);
            prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN2);
            dst[0] += 16;
            dst[1] += 8;
            dst[2] += 8;
            s->mv_min.x -= 64;
            s->mv_max.x -= 64;
        }
        if (s->deblock_filter) {
            if (s->filter.simple)
                filter_mb_row_simple(s, curframe, mb_y);
            else
                filter_mb_row(s, curframe, mb_y);
        }
        s->mv_min.y -= 64;
        s->mv_max.y -= 64;
        ff_thread_report_progress(curframe, mb_y, 0);
    }
    ff_thread_report_progress(curframe, INT_MAX, 0);
skip_decode:
    if (!s->update_probabilities)
        s->prob[0] = s->prob[1];
    memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4);
    if (!s->invisible) {
        *(AVFrame*)data = *curframe;
        *data_size = sizeof(AVFrame);
    }
    return avpkt->size;
}
['static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,\n                            AVPacket *avpkt)\n{\n    VP8Context *s = avctx->priv_data;\n    int ret, mb_x, mb_y, i, y, referenced;\n    enum AVDiscard skip_thresh;\n    AVFrame *av_uninit(curframe), *prev_frame;\n    release_queued_segmaps(s, 0);\n    if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0)\n        return ret;\n    prev_frame = s->framep[VP56_FRAME_CURRENT];\n    referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT\n                                || s->update_altref == VP56_FRAME_CURRENT;\n    skip_thresh = !referenced ? AVDISCARD_NONREF :\n                    !s->keyframe ? AVDISCARD_NONKEY : AVDISCARD_ALL;\n    if (avctx->skip_frame >= skip_thresh) {\n        s->invisible = 1;\n        goto skip_decode;\n    }\n    s->deblock_filter = s->filter.level && avctx->skip_loop_filter < skip_thresh;\n    for (i = 0; i < 5; i++)\n        if (s->frames[i].data[0] &&\n            &s->frames[i] != prev_frame &&\n            &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&\n            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&\n            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2])\n            vp8_release_frame(s, &s->frames[i], 1, 0);\n    for (i = 0; i < 5; i++)\n        if (&s->frames[i] != prev_frame &&\n            &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&\n            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&\n            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) {\n            curframe = s->framep[VP56_FRAME_CURRENT] = &s->frames[i];\n            break;\n        }\n    if (i == 5) {\n        av_log(avctx, AV_LOG_FATAL, "Ran out of free frames!\\n");\n        abort();\n    }\n    if (curframe->data[0])\n        vp8_release_frame(s, curframe, 1, 0);\n    curframe->key_frame = s->keyframe;\n    curframe->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;\n    curframe->reference = referenced ? 3 : 0;\n    if ((ret = vp8_alloc_frame(s, curframe))) {\n        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed!\\n");\n        return ret;\n    }\n    if (s->update_altref != VP56_FRAME_NONE) {\n        s->next_framep[VP56_FRAME_GOLDEN2]  = s->framep[s->update_altref];\n    } else {\n        s->next_framep[VP56_FRAME_GOLDEN2]  = s->framep[VP56_FRAME_GOLDEN2];\n    }\n    if (s->update_golden != VP56_FRAME_NONE) {\n        s->next_framep[VP56_FRAME_GOLDEN]   = s->framep[s->update_golden];\n    } else {\n        s->next_framep[VP56_FRAME_GOLDEN]   = s->framep[VP56_FRAME_GOLDEN];\n    }\n    if (s->update_last) {\n        s->next_framep[VP56_FRAME_PREVIOUS] = curframe;\n    } else {\n        s->next_framep[VP56_FRAME_PREVIOUS] = s->framep[VP56_FRAME_PREVIOUS];\n    }\n    s->next_framep[VP56_FRAME_CURRENT]      = curframe;\n    ff_thread_finish_setup(avctx);\n    if (!s->keyframe && (!s->framep[VP56_FRAME_PREVIOUS] ||\n                         !s->framep[VP56_FRAME_GOLDEN] ||\n                         !s->framep[VP56_FRAME_GOLDEN2])) {\n        av_log(avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\\n");\n        return AVERROR_INVALIDDATA;\n    }\n    s->linesize   = curframe->linesize[0];\n    s->uvlinesize = curframe->linesize[1];\n    if (!s->edge_emu_buffer)\n        s->edge_emu_buffer = av_malloc(21*s->linesize);\n    memset(s->top_nnz, 0, s->mb_width*sizeof(*s->top_nnz));\n    memset(s->macroblocks + s->mb_height*2 - 1, 0, (s->mb_width+1)*sizeof(*s->macroblocks));\n    if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {\n        s->top_border[0][15] = s->top_border[0][23] = 127;\n        memset(s->top_border[1]-1, 127, s->mb_width*sizeof(*s->top_border)+1);\n    }\n    memset(s->ref_count, 0, sizeof(s->ref_count));\n    if (s->keyframe)\n        memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width*4);\n#define MARGIN (16 << 2)\n    s->mv_min.y = -MARGIN;\n    s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;\n    for (mb_y = 0; mb_y < s->mb_height; mb_y++) {\n        VP56RangeCoder *c = &s->coeff_partition[mb_y & (s->num_coeff_partitions-1)];\n        VP8Macroblock *mb = s->macroblocks + (s->mb_height - mb_y - 1)*2;\n        int mb_xy = mb_y*s->mb_width;\n        uint8_t *dst[3] = {\n            curframe->data[0] + 16*mb_y*s->linesize,\n            curframe->data[1] +  8*mb_y*s->uvlinesize,\n            curframe->data[2] +  8*mb_y*s->uvlinesize\n        };\n        memset(mb - 1, 0, sizeof(*mb));\n        memset(s->left_nnz, 0, sizeof(s->left_nnz));\n        AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED*0x01010101);\n        if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {\n            for (i = 0; i < 3; i++)\n                for (y = 0; y < 16>>!!i; y++)\n                    dst[i][y*curframe->linesize[i]-1] = 129;\n            if (mb_y == 1)\n                s->top_border[0][15] = s->top_border[0][23] = s->top_border[0][31] = 129;\n        }\n        s->mv_min.x = -MARGIN;\n        s->mv_max.x = ((s->mb_width  - 1) << 6) + MARGIN;\n        if (prev_frame && s->segmentation.enabled && !s->segmentation.update_map)\n            ff_thread_await_progress(prev_frame, mb_y, 0);\n        for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) {\n            s->dsp.prefetch(dst[0] + (mb_x&3)*4*s->linesize + 64, s->linesize, 4);\n            s->dsp.prefetch(dst[1] + (mb_x&7)*s->uvlinesize + 64, dst[2] - dst[1], 2);\n            decode_mb_mode(s, mb, mb_x, mb_y, curframe->ref_index[0] + mb_xy,\n                           prev_frame && prev_frame->ref_index[0] ? prev_frame->ref_index[0] + mb_xy : NULL);\n            prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS);\n            if (!mb->skip)\n                decode_mb_coeffs(s, c, mb, s->top_nnz[mb_x], s->left_nnz);\n            if (mb->mode <= MODE_I4x4)\n                intra_predict(s, dst, mb, mb_x, mb_y);\n            else\n                inter_predict(s, dst, mb, mb_x, mb_y);\n            prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN);\n            if (!mb->skip) {\n                idct_mb(s, dst, mb);\n            } else {\n                AV_ZERO64(s->left_nnz);\n                AV_WN64(s->top_nnz[mb_x], 0);\n                if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) {\n                    s->left_nnz[8]      = 0;\n                    s->top_nnz[mb_x][8] = 0;\n                }\n            }\n            if (s->deblock_filter)\n                filter_level_for_mb(s, mb, &s->filter_strength[mb_x]);\n            prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN2);\n            dst[0] += 16;\n            dst[1] += 8;\n            dst[2] += 8;\n            s->mv_min.x -= 64;\n            s->mv_max.x -= 64;\n        }\n        if (s->deblock_filter) {\n            if (s->filter.simple)\n                filter_mb_row_simple(s, curframe, mb_y);\n            else\n                filter_mb_row(s, curframe, mb_y);\n        }\n        s->mv_min.y -= 64;\n        s->mv_max.y -= 64;\n        ff_thread_report_progress(curframe, mb_y, 0);\n    }\n    ff_thread_report_progress(curframe, INT_MAX, 0);\nskip_decode:\n    if (!s->update_probabilities)\n        s->prob[0] = s->prob[1];\n    memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4);\n    if (!s->invisible) {\n        *(AVFrame*)data = *curframe;\n        *data_size = sizeof(AVFrame);\n    }\n    return avpkt->size;\n}']