int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
                      const uint8_t *buf, int buf_size)
{
    vp56_context_t *s = avctx->priv_data;
    AVFrame *const p = s->framep[VP56_FRAME_CURRENT];
    int is_alpha, alpha_offset;
    if (s->has_alpha) {
        alpha_offset = bytestream_get_be24(&buf);
        buf_size -= 3;
    }
    for (is_alpha=0; is_alpha < 1+s->has_alpha; is_alpha++) {
        int mb_row, mb_col, mb_row_flip, mb_offset = 0;
        int block, y, uv, stride_y, stride_uv;
        int golden_frame = 0;
        int res;
        s->modelp = &s->models[is_alpha];
        res = s->parse_header(s, buf, buf_size, &golden_frame);
        if (!res)
            return -1;
        if (!is_alpha) {
            p->reference = 1;
            if (avctx->get_buffer(avctx, p) < 0) {
                av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
                return -1;
            }
            if (res == 2)
                if (vp56_size_changed(avctx)) {
                    avctx->release_buffer(avctx, p);
                    return -1;
                }
        }
        if (p->key_frame) {
            p->pict_type = FF_I_TYPE;
            s->default_models_init(s);
            for (block=0; block<s->mb_height*s->mb_width; block++)
                s->macroblocks[block].type = VP56_MB_INTRA;
        } else {
            p->pict_type = FF_P_TYPE;
            vp56_parse_mb_type_models(s);
            s->parse_vector_models(s);
            s->mb_type = VP56_MB_INTER_NOVEC_PF;
        }
        s->parse_coeff_models(s);
        memset(s->prev_dc, 0, sizeof(s->prev_dc));
        s->prev_dc[1][VP56_FRAME_CURRENT] = 128;
        s->prev_dc[2][VP56_FRAME_CURRENT] = 128;
        for (block=0; block < 4*s->mb_width+6; block++) {
            s->above_blocks[block].ref_frame = -1;
            s->above_blocks[block].dc_coeff = 0;
            s->above_blocks[block].not_null_dc = 0;
        }
        s->above_blocks[2*s->mb_width + 2].ref_frame = 0;
        s->above_blocks[3*s->mb_width + 4].ref_frame = 0;
        stride_y  = p->linesize[0];
        stride_uv = p->linesize[1];
        if (s->flip < 0)
            mb_offset = 7;
        for (mb_row=0; mb_row<s->mb_height; mb_row++) {
            if (s->flip < 0)
                mb_row_flip = s->mb_height - mb_row - 1;
            else
                mb_row_flip = mb_row;
            for (block=0; block<4; block++) {
                s->left_block[block].ref_frame = -1;
                s->left_block[block].dc_coeff = 0;
                s->left_block[block].not_null_dc = 0;
            }
            memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx));
            memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last));
            s->above_block_idx[0] = 1;
            s->above_block_idx[1] = 2;
            s->above_block_idx[2] = 1;
            s->above_block_idx[3] = 2;
            s->above_block_idx[4] = 2*s->mb_width + 2 + 1;
            s->above_block_idx[5] = 3*s->mb_width + 4 + 1;
            s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y;
            s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y;
            s->block_offset[1] = s->block_offset[0] + 8;
            s->block_offset[3] = s->block_offset[2] + 8;
            s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv;
            s->block_offset[5] = s->block_offset[4];
            for (mb_col=0; mb_col<s->mb_width; mb_col++) {
                vp56_decode_mb(s, mb_row, mb_col, is_alpha);
                for (y=0; y<4; y++) {
                    s->above_block_idx[y] += 2;
                    s->block_offset[y] += 16;
                }
                for (uv=4; uv<6; uv++) {
                    s->above_block_idx[uv] += 1;
                    s->block_offset[uv] += 8;
                }
            }
        }
        if (p->key_frame || golden_frame) {
            if (s->framep[VP56_FRAME_GOLDEN]->data[0] &&
                s->framep[VP56_FRAME_GOLDEN] != s->framep[VP56_FRAME_GOLDEN2])
                avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN]);
            s->framep[VP56_FRAME_GOLDEN] = p;
        }
        if (s->has_alpha) {
            FFSWAP(AVFrame *, s->framep[VP56_FRAME_GOLDEN],
                              s->framep[VP56_FRAME_GOLDEN2]);
            buf += alpha_offset;
            buf_size -= alpha_offset;
        }
    }
    if (s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN] ||
        s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN2]) {
        if (s->framep[VP56_FRAME_UNUSED] != s->framep[VP56_FRAME_GOLDEN] &&
            s->framep[VP56_FRAME_UNUSED] != s->framep[VP56_FRAME_GOLDEN2])
            FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS],
                              s->framep[VP56_FRAME_UNUSED]);
        else
            FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS],
                              s->framep[VP56_FRAME_UNUSED2]);
    } else if (s->framep[VP56_FRAME_PREVIOUS]->data[0])
        avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]);
    FFSWAP(AVFrame *, s->framep[VP56_FRAME_CURRENT],
                      s->framep[VP56_FRAME_PREVIOUS]);
    *(AVFrame*)data = *p;
    *data_size = sizeof(AVFrame);
    return buf_size;
}
['int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,\n                      const uint8_t *buf, int buf_size)\n{\n    vp56_context_t *s = avctx->priv_data;\n    AVFrame *const p = s->framep[VP56_FRAME_CURRENT];\n    int is_alpha, alpha_offset;\n    if (s->has_alpha) {\n        alpha_offset = bytestream_get_be24(&buf);\n        buf_size -= 3;\n    }\n    for (is_alpha=0; is_alpha < 1+s->has_alpha; is_alpha++) {\n        int mb_row, mb_col, mb_row_flip, mb_offset = 0;\n        int block, y, uv, stride_y, stride_uv;\n        int golden_frame = 0;\n        int res;\n        s->modelp = &s->models[is_alpha];\n        res = s->parse_header(s, buf, buf_size, &golden_frame);\n        if (!res)\n            return -1;\n        if (!is_alpha) {\n            p->reference = 1;\n            if (avctx->get_buffer(avctx, p) < 0) {\n                av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\\n");\n                return -1;\n            }\n            if (res == 2)\n                if (vp56_size_changed(avctx)) {\n                    avctx->release_buffer(avctx, p);\n                    return -1;\n                }\n        }\n        if (p->key_frame) {\n            p->pict_type = FF_I_TYPE;\n            s->default_models_init(s);\n            for (block=0; block<s->mb_height*s->mb_width; block++)\n                s->macroblocks[block].type = VP56_MB_INTRA;\n        } else {\n            p->pict_type = FF_P_TYPE;\n            vp56_parse_mb_type_models(s);\n            s->parse_vector_models(s);\n            s->mb_type = VP56_MB_INTER_NOVEC_PF;\n        }\n        s->parse_coeff_models(s);\n        memset(s->prev_dc, 0, sizeof(s->prev_dc));\n        s->prev_dc[1][VP56_FRAME_CURRENT] = 128;\n        s->prev_dc[2][VP56_FRAME_CURRENT] = 128;\n        for (block=0; block < 4*s->mb_width+6; block++) {\n            s->above_blocks[block].ref_frame = -1;\n            s->above_blocks[block].dc_coeff = 0;\n            s->above_blocks[block].not_null_dc = 0;\n        }\n        s->above_blocks[2*s->mb_width + 2].ref_frame = 0;\n        s->above_blocks[3*s->mb_width + 4].ref_frame = 0;\n        stride_y  = p->linesize[0];\n        stride_uv = p->linesize[1];\n        if (s->flip < 0)\n            mb_offset = 7;\n        for (mb_row=0; mb_row<s->mb_height; mb_row++) {\n            if (s->flip < 0)\n                mb_row_flip = s->mb_height - mb_row - 1;\n            else\n                mb_row_flip = mb_row;\n            for (block=0; block<4; block++) {\n                s->left_block[block].ref_frame = -1;\n                s->left_block[block].dc_coeff = 0;\n                s->left_block[block].not_null_dc = 0;\n            }\n            memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx));\n            memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last));\n            s->above_block_idx[0] = 1;\n            s->above_block_idx[1] = 2;\n            s->above_block_idx[2] = 1;\n            s->above_block_idx[3] = 2;\n            s->above_block_idx[4] = 2*s->mb_width + 2 + 1;\n            s->above_block_idx[5] = 3*s->mb_width + 4 + 1;\n            s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y;\n            s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y;\n            s->block_offset[1] = s->block_offset[0] + 8;\n            s->block_offset[3] = s->block_offset[2] + 8;\n            s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv;\n            s->block_offset[5] = s->block_offset[4];\n            for (mb_col=0; mb_col<s->mb_width; mb_col++) {\n                vp56_decode_mb(s, mb_row, mb_col, is_alpha);\n                for (y=0; y<4; y++) {\n                    s->above_block_idx[y] += 2;\n                    s->block_offset[y] += 16;\n                }\n                for (uv=4; uv<6; uv++) {\n                    s->above_block_idx[uv] += 1;\n                    s->block_offset[uv] += 8;\n                }\n            }\n        }\n        if (p->key_frame || golden_frame) {\n            if (s->framep[VP56_FRAME_GOLDEN]->data[0] &&\n                s->framep[VP56_FRAME_GOLDEN] != s->framep[VP56_FRAME_GOLDEN2])\n                avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN]);\n            s->framep[VP56_FRAME_GOLDEN] = p;\n        }\n        if (s->has_alpha) {\n            FFSWAP(AVFrame *, s->framep[VP56_FRAME_GOLDEN],\n                              s->framep[VP56_FRAME_GOLDEN2]);\n            buf += alpha_offset;\n            buf_size -= alpha_offset;\n        }\n    }\n    if (s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN] ||\n        s->framep[VP56_FRAME_PREVIOUS] == s->framep[VP56_FRAME_GOLDEN2]) {\n        if (s->framep[VP56_FRAME_UNUSED] != s->framep[VP56_FRAME_GOLDEN] &&\n            s->framep[VP56_FRAME_UNUSED] != s->framep[VP56_FRAME_GOLDEN2])\n            FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS],\n                              s->framep[VP56_FRAME_UNUSED]);\n        else\n            FFSWAP(AVFrame *, s->framep[VP56_FRAME_PREVIOUS],\n                              s->framep[VP56_FRAME_UNUSED2]);\n    } else if (s->framep[VP56_FRAME_PREVIOUS]->data[0])\n        avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]);\n    FFSWAP(AVFrame *, s->framep[VP56_FRAME_CURRENT],\n                      s->framep[VP56_FRAME_PREVIOUS]);\n    *(AVFrame*)data = *p;\n    *data_size = sizeof(AVFrame);\n    return buf_size;\n}']