📄 vp6.c
字号:
/** * @file vp6.c * VP6 compatible video decoder * * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org> * * The VP6F decoder accepts an optional 1 byte extradata. It is composed of: * - upper 4bits: difference between encoded width and visible width * - lower 4bits: difference between encoded height and visible height * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include <stdlib.h>#include "avcodec.h"#include "dsputil.h"#include "bitstream.h"#include "huffman.h"#include "mpegvideo.h"#include "vp56.h"#include "vp56data.h"#include "vp6data.h"static void vp6_parse_coeff(vp56_context_t *s);static void vp6_parse_coeff_huffman(vp56_context_t *s);static int vp6_parse_header(vp56_context_t *s, const uint8_t *buf, int buf_size, int *golden_frame){ vp56_range_coder_t *c = &s->c; int parse_filter_info = 0; int coeff_offset = 0; int vrt_shift = 0; int sub_version; int rows, cols; int res = 1; int separated_coeff = buf[0] & 1; s->framep[VP56_FRAME_CURRENT]->key_frame = !(buf[0] & 0x80); vp56_init_dequant(s, (buf[0] >> 1) & 0x3F); if (s->framep[VP56_FRAME_CURRENT]->key_frame) { sub_version = buf[1] >> 3; if (sub_version > 8) return 0; s->filter_header = buf[1] & 0x06; if (buf[1] & 1) { av_log(s->avctx, AV_LOG_ERROR, "interlacing not supported\n"); return 0; } if (separated_coeff || !s->filter_header) { coeff_offset = AV_RB16(buf+2) - 2; buf += 2; buf_size -= 2; } rows = buf[2]; /* number of stored macroblock rows */ cols = buf[3]; /* number of stored macroblock cols */ /* buf[4] is number of displayed macroblock rows */ /* buf[5] is number of displayed macroblock cols */ if (16*cols != s->avctx->coded_width || 16*rows != s->avctx->coded_height) { avcodec_set_dimensions(s->avctx, 16*cols, 16*rows); if (s->avctx->extradata_size == 1) { s->avctx->width -= s->avctx->extradata[0] >> 4; s->avctx->height -= s->avctx->extradata[0] & 0x0F; } res = 2; } vp56_init_range_decoder(c, buf+6, buf_size-6); vp56_rac_gets(c, 2); parse_filter_info = s->filter_header; if (sub_version < 8) vrt_shift = 5; s->sub_version = sub_version; } else { if (!s->sub_version) return 0; if (separated_coeff || !s->filter_header) { coeff_offset = AV_RB16(buf+1) - 2; buf += 2; buf_size -= 2; } vp56_init_range_decoder(c, buf+1, buf_size-1); *golden_frame = vp56_rac_get(c); if (s->filter_header) { s->deblock_filtering = vp56_rac_get(c); if (s->deblock_filtering) vp56_rac_get(c); if (s->sub_version > 7) parse_filter_info = vp56_rac_get(c); } } if (parse_filter_info) { if (vp56_rac_get(c)) { s->filter_mode = 2; s->sample_variance_threshold = vp56_rac_gets(c, 5) << vrt_shift; s->max_vector_length = 2 << vp56_rac_gets(c, 3); } else if (vp56_rac_get(c)) { s->filter_mode = 1; } else { s->filter_mode = 0; } if (s->sub_version > 7) s->filter_selection = vp56_rac_gets(c, 4); else s->filter_selection = 16; } s->use_huffman = vp56_rac_get(c); s->parse_coeff = vp6_parse_coeff; if (coeff_offset) { buf += coeff_offset; buf_size -= coeff_offset; if (s->use_huffman) { s->parse_coeff = vp6_parse_coeff_huffman; init_get_bits(&s->gb, buf, buf_size<<3); } else { vp56_init_range_decoder(&s->cc, buf, buf_size); s->ccp = &s->cc; } } else { s->ccp = &s->c; } return res;}static void vp6_coeff_order_table_init(vp56_context_t *s){ int i, pos, idx = 1; s->modelp->coeff_index_to_pos[0] = 0; for (i=0; i<16; i++) for (pos=1; pos<64; pos++) if (s->modelp->coeff_reorder[pos] == i) s->modelp->coeff_index_to_pos[idx++] = pos;}static void vp6_default_models_init(vp56_context_t *s){ vp56_model_t *model = s->modelp; model->vector_dct[0] = 0xA2; model->vector_dct[1] = 0xA4; model->vector_sig[0] = 0x80; model->vector_sig[1] = 0x80; memcpy(model->mb_types_stats, vp56_def_mb_types_stats, sizeof(model->mb_types_stats)); memcpy(model->vector_fdv, vp6_def_fdv_vector_model, sizeof(model->vector_fdv)); memcpy(model->vector_pdv, vp6_def_pdv_vector_model, sizeof(model->vector_pdv)); memcpy(model->coeff_runv, vp6_def_runv_coeff_model, sizeof(model->coeff_runv)); memcpy(model->coeff_reorder, vp6_def_coeff_reorder, sizeof(model->coeff_reorder)); vp6_coeff_order_table_init(s);}static void vp6_parse_vector_models(vp56_context_t *s){ vp56_range_coder_t *c = &s->c; vp56_model_t *model = s->modelp; int comp, node; for (comp=0; comp<2; comp++) { if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][0])) model->vector_dct[comp] = vp56_rac_gets_nn(c, 7); if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][1])) model->vector_sig[comp] = vp56_rac_gets_nn(c, 7); } for (comp=0; comp<2; comp++) for (node=0; node<7; node++) if (vp56_rac_get_prob(c, vp6_pdv_pct[comp][node])) model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7); for (comp=0; comp<2; comp++) for (node=0; node<8; node++) if (vp56_rac_get_prob(c, vp6_fdv_pct[comp][node])) model->vector_fdv[comp][node] = vp56_rac_gets_nn(c, 7);}static int vp6_huff_cmp(const void *va, const void *vb){ const Node *a = va, *b = vb; return a->count >= b->count;}static void vp6_build_huff_tree(vp56_context_t *s, uint8_t coeff_model[], const uint8_t *map, unsigned size, VLC *vlc){ Node nodes[2*size], *tmp = &nodes[size]; int a, b, i; /* first compute probabilities from model */ tmp[0].count = 256; for (i=0; i<size-1; i++) { a = tmp[i].count * coeff_model[i] >> 8; b = tmp[i].count * (255 - coeff_model[i]) >> 8; nodes[map[2*i ]].count = a + !a; nodes[map[2*i+1]].count = b + !b; } /* then build the huffman tree accodring to probabilities */ ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp, 1);}static void vp6_parse_coeff_models(vp56_context_t *s){ vp56_range_coder_t *c = &s->c; vp56_model_t *model = s->modelp; int def_prob[11]; int node, cg, ctx, pos; int ct; /* code type */ int pt; /* plane type (0 for Y, 1 for U or V) */ memset(def_prob, 0x80, sizeof(def_prob)); for (pt=0; pt<2; pt++) for (node=0; node<11; node++) if (vp56_rac_get_prob(c, vp6_dccv_pct[pt][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_dccv[pt][node] = def_prob[node]; } else if (s->framep[VP56_FRAME_CURRENT]->key_frame) { model->coeff_dccv[pt][node] = def_prob[node]; } if (vp56_rac_get(c)) { for (pos=1; pos<64; pos++) if (vp56_rac_get_prob(c, vp6_coeff_reorder_pct[pos])) model->coeff_reorder[pos] = vp56_rac_gets(c, 4); vp6_coeff_order_table_init(s); } for (cg=0; cg<2; cg++) for (node=0; node<14; node++) if (vp56_rac_get_prob(c, vp6_runv_pct[cg][node])) model->coeff_runv[cg][node] = vp56_rac_gets_nn(c, 7); for (ct=0; ct<3; ct++) for (pt=0; pt<2; pt++) for (cg=0; cg<6; cg++) for (node=0; node<11; node++) if (vp56_rac_get_prob(c, vp6_ract_pct[ct][pt][cg][node])) { def_prob[node] = vp56_rac_gets_nn(c, 7); model->coeff_ract[pt][ct][cg][node] = def_prob[node]; } else if (s->framep[VP56_FRAME_CURRENT]->key_frame) { model->coeff_ract[pt][ct][cg][node] = def_prob[node]; } if (s->use_huffman) { for (pt=0; pt<2; pt++) { vp6_build_huff_tree(s, model->coeff_dccv[pt], vp6_huff_coeff_map, 12, &s->dccv_vlc[pt]); vp6_build_huff_tree(s, model->coeff_runv[pt], vp6_huff_run_map, 9, &s->runv_vlc[pt]); for (ct=0; ct<3; ct++) for (cg = 0; cg < 6; cg++) vp6_build_huff_tree(s, model->coeff_ract[pt][ct][cg], vp6_huff_coeff_map, 12, &s->ract_vlc[pt][ct][cg]); } memset(s->nb_null, 0, sizeof(s->nb_null)); } else { /* coeff_dcct is a linear combination of coeff_dccv */ for (pt=0; pt<2; pt++) for (ctx=0; ctx<3; ctx++) for (node=0; node<5; node++) model->coeff_dcct[pt][ctx][node] = av_clip(((model->coeff_dccv[pt][node] * vp6_dccv_lc[ctx][node][0] + 128) >> 8) + vp6_dccv_lc[ctx][node][1], 1, 255); }}static void vp6_parse_vector_adjustment(vp56_context_t *s, vp56_mv_t *vect){ vp56_range_coder_t *c = &s->c; vp56_model_t *model = s->modelp; int comp; *vect = (vp56_mv_t) {0,0}; if (s->vector_candidate_pos < 2) *vect = s->vector_candidate[0]; for (comp=0; comp<2; comp++) { int i, delta = 0; if (vp56_rac_get_prob(c, model->vector_dct[comp])) { static const uint8_t prob_order[] = {0, 1, 2, 7, 6, 5, 4}; for (i=0; i<sizeof(prob_order); i++) { int j = prob_order[i]; delta |= vp56_rac_get_prob(c, model->vector_fdv[comp][j])<<j; } if (delta & 0xF0) delta |= vp56_rac_get_prob(c, model->vector_fdv[comp][3])<<3; else delta |= 8; } else { delta = vp56_rac_get_tree(c, vp56_pva_tree, model->vector_pdv[comp]); } if (delta && vp56_rac_get_prob(c, model->vector_sig[comp])) delta = -delta; if (!comp) vect->x += delta; else vect->y += delta; }}/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -