VP5 and VP6 video decoder

Originally committed as revision 6213 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Aurelien Jacobs 2006-09-09 17:19:37 +00:00
parent 34a8dcd031
commit 5ce117c37c
18 changed files with 2544 additions and 15 deletions

View File

@ -56,6 +56,8 @@ version <next>
- MacIntel support
- AVISynth support
- VMware video decoder
- VP5 video decoder
- VP6 video decoder
version 0.4.9-pre1:

View File

@ -164,6 +164,8 @@ Codecs:
vcr1.c Michael Niedermayer
vmnc.c Kostya Shishkov
vp3* Mike Melanson
vp5 Aurelien Jacobs
vp6 Aurelien Jacobs
vqavideo.c Mike Melanson
wmv2.c Michael Niedermayer
wnv1.c Kostya Shishkov

View File

@ -778,6 +778,8 @@ following image formats are supported:
@item Sorenson Video 1 @tab X @tab X @tab fourcc: SVQ1
@item Sorenson Video 3 @tab @tab X @tab fourcc: SVQ3
@item On2 VP3 @tab @tab X @tab still experimental
@item On2 VP5 @tab @tab X @tab fourcc: VP50
@item On2 VP6 @tab @tab X @tab fourcc: VP62
@item Theora @tab @tab X @tab still experimental
@item Intel Indeo 3 @tab @tab X
@item FLV @tab X @tab X @tab Sorenson H.263 used in Flash

View File

@ -123,6 +123,8 @@ OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o
OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o
OBJS-$(CONFIG_VORBIS_DECODER) += vorbis.o
OBJS-$(CONFIG_VP3_DECODER) += vp3.o
OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o
OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o
OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
OBJS-$(CONFIG_WMAV1_DECODER) += wmadec.o
OBJS-$(CONFIG_WMAV2_DECODER) += wmadec.o

View File

@ -371,6 +371,15 @@ void avcodec_register_all(void)
#ifdef CONFIG_THEORA_DECODER
register_avcodec(&theora_decoder);
#endif //CONFIG_THEORA_DECODER
#ifdef CONFIG_VP5_DECODER
register_avcodec(&vp5_decoder);
#endif //CONFIG_VP5_DECODER
#ifdef CONFIG_VP6_DECODER
register_avcodec(&vp6_decoder);
#endif //CONFIG_VP6_DECODER
#ifdef CONFIG_VP6F_DECODER
register_avcodec(&vp6f_decoder);
#endif //CONFIG_VP6F_DECODER
#ifdef CONFIG_ASV1_DECODER
register_avcodec(&asv1_decoder);
#endif //CONFIG_ASV1_DECODER

View File

@ -17,8 +17,8 @@ extern "C" {
#define AV_STRINGIFY(s) AV_TOSTRING(s)
#define AV_TOSTRING(s) #s
#define LIBAVCODEC_VERSION_INT ((51<<16)+(13<<8)+0)
#define LIBAVCODEC_VERSION 51.13.0
#define LIBAVCODEC_VERSION_INT ((51<<16)+(14<<8)+0)
#define LIBAVCODEC_VERSION 51.14.0
#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT
#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
@ -121,6 +121,9 @@ enum CodecID {
CODEC_ID_CAVS,
CODEC_ID_JPEG2000,
CODEC_ID_VMNC,
CODEC_ID_VP5,
CODEC_ID_VP6,
CODEC_ID_VP6F,
/* various pcm "codecs" */
CODEC_ID_PCM_S16LE= 0x10000,
@ -2192,6 +2195,9 @@ extern AVCodec h264_decoder;
extern AVCodec indeo3_decoder;
extern AVCodec vp3_decoder;
extern AVCodec theora_decoder;
extern AVCodec vp5_decoder;
extern AVCodec vp6_decoder;
extern AVCodec vp6f_decoder;
extern AVCodec amr_nb_decoder;
extern AVCodec amr_nb_encoder;
extern AVCodec amr_wb_encoder;

289
libavcodec/vp5.c Normal file
View File

@ -0,0 +1,289 @@
/**
* @file vp5.c
* VP5 compatible video decoder
*
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "avcodec.h"
#include "dsputil.h"
#include "bitstream.h"
#include "mpegvideo.h"
#include "vp56.h"
#include "vp56data.h"
#include "vp5data.h"
static int vp5_parse_header(vp56_context_t *s, uint8_t *buf, int buf_size,
int *golden_frame)
{
vp56_range_coder_t *c = &s->c;
int rows, cols;
vp56_init_range_decoder(&s->c, buf, buf_size);
s->frames[VP56_FRAME_CURRENT].key_frame = !vp56_rac_get(c);
vp56_rac_get(c);
vp56_init_dequant(s, vp56_rac_gets(c, 6));
if (s->frames[VP56_FRAME_CURRENT].key_frame)
{
vp56_rac_gets(c, 8);
if(vp56_rac_gets(c, 5) > 5)
return 0;
vp56_rac_gets(c, 2);
if (vp56_rac_get(c)) {
av_log(s->avctx, AV_LOG_ERROR, "interlacing not supported\n");
return 0;
}
rows = vp56_rac_gets(c, 8); /* number of stored macroblock rows */
cols = vp56_rac_gets(c, 8); /* number of stored macroblock cols */
vp56_rac_gets(c, 8); /* number of displayed macroblock rows */
vp56_rac_gets(c, 8); /* number of displayed macroblock cols */
vp56_rac_gets(c, 2);
if (16*cols != s->avctx->coded_width ||
16*rows != s->avctx->coded_height) {
avcodec_set_dimensions(s->avctx, 16*cols, 16*rows);
return 2;
}
}
return 1;
}
/* Gives very similar result than the vp6 version except in a few cases */
static int vp5_adjust(int v, int t)
{
int s2, s1 = v >> 31;
v ^= s1;
v -= s1;
v *= v < 2*t;
v -= t;
s2 = v >> 31;
v ^= s2;
v -= s2;
v = t - v;
v += s1;
v ^= s1;
return v;
}
static void vp5_parse_vector_adjustment(vp56_context_t *s, vp56_mv_t *vector)
{
vp56_range_coder_t *c = &s->c;
int comp, di;
for (comp=0; comp<2; comp++) {
int delta = 0;
if (vp56_rac_get_prob(c, s->vector_model_dct[comp])) {
int sign = vp56_rac_get_prob(c, s->vector_model_sig[comp]);
di = vp56_rac_get_prob(c, s->vector_model_pdi[comp][0]);
di |= vp56_rac_get_prob(c, s->vector_model_pdi[comp][1]) << 1;
delta = vp56_rac_get_tree(c, vp56_pva_tree,
s->vector_model_pdv[comp]);
delta = di | (delta << 2);
delta = (delta ^ -sign) + sign;
}
if (!comp)
vector->x = delta;
else
vector->y = delta;
}
}
static void vp5_parse_vector_models(vp56_context_t *s)
{
vp56_range_coder_t *c = &s->c;
int comp, node;
for (comp=0; comp<2; comp++) {
if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][0]))
s->vector_model_dct[comp] = vp56_rac_gets_nn(c, 7);
if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][1]))
s->vector_model_sig[comp] = vp56_rac_gets_nn(c, 7);
if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][2]))
s->vector_model_pdi[comp][0] = vp56_rac_gets_nn(c, 7);
if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][3]))
s->vector_model_pdi[comp][1] = vp56_rac_gets_nn(c, 7);
}
for (comp=0; comp<2; comp++)
for (node=0; node<7; node++)
if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][4 + node]))
s->vector_model_pdv[comp][node] = vp56_rac_gets_nn(c, 7);
}
static void vp5_parse_coeff_models(vp56_context_t *s)
{
vp56_range_coder_t *c = &s->c;
uint8_t def_prob[11];
int node, cg, ctx;
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, vp5_dccv_pct[pt][node])) {
def_prob[node] = vp56_rac_gets_nn(c, 7);
s->coeff_model_dccv[pt][node] = def_prob[node];
} else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
s->coeff_model_dccv[pt][node] = def_prob[node];
}
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, vp5_ract_pct[ct][pt][cg][node])) {
def_prob[node] = vp56_rac_gets_nn(c, 7);
s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
} else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
}
/* coeff_model_dcct is a linear combination of coeff_model_dccv */
for (pt=0; pt<2; pt++)
for (ctx=0; ctx<36; ctx++)
for (node=0; node<5; node++)
s->coeff_model_dcct[pt][ctx][node] = clip(((s->coeff_model_dccv[pt][node] * vp5_dccv_lc[node][ctx][0] + 128) >> 8) + vp5_dccv_lc[node][ctx][1], 1, 254);
/* coeff_model_acct is a linear combination of coeff_model_ract */
for (ct=0; ct<3; ct++)
for (pt=0; pt<2; pt++)
for (cg=0; cg<3; cg++)
for (ctx=0; ctx<6; ctx++)
for (node=0; node<5; node++)
s->coeff_model_acct[pt][ct][cg][ctx][node] = clip(((s->coeff_model_ract[pt][ct][cg][node] * vp5_ract_lc[ct][cg][node][ctx][0] + 128) >> 8) + vp5_ract_lc[ct][cg][node][ctx][1], 1, 254);
}
static void vp5_parse_coeff(vp56_context_t *s)
{
vp56_range_coder_t *c = &s->c;
uint8_t *permute = s->scantable.permutated;
uint8_t *model, *model2;
int coeff, sign, coeff_idx;
int b, i, cg, idx, ctx, ctx_last;
int pt = 0; /* plane type (0 for Y, 1 for U or V) */
for (b=0; b<6; b++) {
int ct = 1; /* code type */
if (b > 3) pt = 1;
ctx = 6*s->coeff_ctx[vp56_b6to4[b]][0]
+ s->above_blocks[s->above_block_idx[b]].not_null_dc;
model = s->coeff_model_dccv[pt];
model2 = s->coeff_model_dcct[pt][ctx];
for (coeff_idx=0; coeff_idx<64; ) {
if (vp56_rac_get_prob(c, model2[0])) {
if (vp56_rac_get_prob(c, model2[2])) {
if (vp56_rac_get_prob(c, model2[3])) {
s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 4;
idx = vp56_rac_get_tree(c, vp56_pc_tree, model);
sign = vp56_rac_get(c);
coeff = vp56_coeff_bias[idx];
for (i=vp56_coeff_bit_length[idx]; i>=0; i--)
coeff += vp56_rac_get_prob(c, vp56_coeff_parse_table[idx][i]) << i;
} else {
if (vp56_rac_get_prob(c, model2[4])) {
coeff = 3 + vp56_rac_get_prob(c, model[5]);
s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 3;
} else {
coeff = 2;
s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 2;
}
sign = vp56_rac_get(c);
}
ct = 2;
} else {
ct = 1;
s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 1;
sign = vp56_rac_get(c);
coeff = 1;
}
coeff = (coeff ^ -sign) + sign;
if (coeff_idx)
coeff *= s->dequant_ac;
s->block_coeff[b][permute[coeff_idx]] = coeff;
} else {
if (ct && !vp56_rac_get_prob(c, model2[1]))
break;
ct = 0;
s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 0;
}
cg = vp5_coeff_groups[++coeff_idx];
ctx = s->coeff_ctx[vp56_b6to4[b]][coeff_idx];
model = s->coeff_model_ract[pt][ct][cg];
model2 = cg > 2 ? model : s->coeff_model_acct[pt][ct][cg][ctx];
}
ctx_last = FFMIN(s->coeff_ctx_last[vp56_b6to4[b]], 24);
s->coeff_ctx_last[vp56_b6to4[b]] = coeff_idx;
if (coeff_idx < ctx_last)
for (i=coeff_idx; i<=ctx_last; i++)
s->coeff_ctx[vp56_b6to4[b]][i] = 5;
s->above_blocks[s->above_block_idx[b]].not_null_dc = s->coeff_ctx[vp56_b6to4[b]][0];
}
}
static void vp5_default_models_init(vp56_context_t *s)
{
int i;
for (i=0; i<2; i++) {
s->vector_model_sig[i] = 0x80;
s->vector_model_dct[i] = 0x80;
s->vector_model_pdi[i][0] = 0x55;
s->vector_model_pdi[i][1] = 0x80;
}
memcpy(s->mb_types_stats, vp56_def_mb_types_stats, sizeof(s->mb_types_stats));
memset(s->vector_model_pdv, 0x80, sizeof(s->vector_model_pdv));
}
static int vp5_decode_init(AVCodecContext *avctx)
{
vp56_context_t *s = avctx->priv_data;
vp56_init(s, avctx, 1);
s->vp56_coord_div = vp5_coord_div;
s->parse_vector_adjustment = vp5_parse_vector_adjustment;
s->adjust = vp5_adjust;
s->parse_coeff = vp5_parse_coeff;
s->default_models_init = vp5_default_models_init;
s->parse_vector_models = vp5_parse_vector_models;
s->parse_coeff_models = vp5_parse_coeff_models;
s->parse_header = vp5_parse_header;
return 0;
}
AVCodec vp5_decoder = {
"vp5",
CODEC_TYPE_VIDEO,
CODEC_ID_VP5,
sizeof(vp56_context_t),
vp5_decode_init,
NULL,
vp56_free,
vp56_decode_frame,
};

662
libavcodec/vp56.c Normal file
View File

@ -0,0 +1,662 @@
/**
* @file vp56.c
* VP5 and VP6 compatible video decoder (common features)
*
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avcodec.h"
#include "vp56.h"
#include "vp56data.h"
void vp56_init_dequant(vp56_context_t *s, int quantizer)
{
s->quantizer = quantizer;
s->dequant_dc = vp56_dc_dequant[quantizer] << 2;
s->dequant_ac = vp56_ac_dequant[quantizer] << 2;
}
static int vp56_get_vectors_predictors(vp56_context_t *s, int row, int col,
vp56_frame_t ref_frame)
{
int nb_pred = 0;
vp56_mv_t vector[2] = {{0,0}, {0,0}};
int pos, offset;
vp56_mv_t mvp;
for (pos=0; pos<12; pos++) {
mvp.x = col + vp56_candidate_predictor_pos[pos][0];
mvp.y = row + vp56_candidate_predictor_pos[pos][1];
if (mvp.x < 0 || mvp.x >= s->mb_width ||
mvp.y < 0 || mvp.y >= s->mb_height)
continue;
offset = mvp.x + s->mb_width*mvp.y;
if (vp56_reference_frame[s->macroblocks[offset].type] != ref_frame)
continue;
if ((s->macroblocks[offset].mv.x == vector[0].x &&
s->macroblocks[offset].mv.y == vector[0].y) ||
(s->macroblocks[offset].mv.x == 0 &&
s->macroblocks[offset].mv.y == 0))
continue;
vector[nb_pred++] = s->macroblocks[offset].mv;
if (nb_pred > 1) {
nb_pred = -1;
break;
}
s->vector_candidate_pos = pos;
}
s->vector_candidate[0] = vector[0];
s->vector_candidate[1] = vector[1];
return nb_pred+1;
}
static void vp56_parse_mb_type_models(vp56_context_t *s)
{
vp56_range_coder_t *c = &s->c;
int i, ctx, type;
for (ctx=0; ctx<3; ctx++) {
if (vp56_rac_get_prob(c, 174)) {
int idx = vp56_rac_gets(c, 4);
memcpy(s->mb_types_stats[ctx],vp56_pre_def_mb_type_stats[idx][ctx],
sizeof(s->mb_types_stats[ctx]));
}
if (vp56_rac_get_prob(c, 254)) {
for (type=0; type<10; type++) {
for(i=0; i<2; i++) {
if (vp56_rac_get_prob(c, 205)) {
int delta, sign = vp56_rac_get(c);
delta = vp56_rac_get_tree(c, vp56_pmbtm_tree,
vp56_mb_type_model_model);
if (!delta)
delta = 4 * vp56_rac_gets(c, 7);
s->mb_types_stats[ctx][type][i] += (delta ^ -sign) + sign;
}
}
}
}
}
/* compute MB type probability tables based on previous MB type */
for (ctx=0; ctx<3; ctx++) {
int p[10];
for (type=0; type<10; type++)
p[type] = 100 * s->mb_types_stats[ctx][type][1];
for (type=0; type<10; type++) {
int p02, p34, p0234, p17, p56, p89, p5689, p156789;
/* conservative MB type probability */
s->mb_type_model[ctx][type][0] = 255 - (255 * s->mb_types_stats[ctx][type][0]) / (1 + s->mb_types_stats[ctx][type][0] + s->mb_types_stats[ctx][type][1]);
p[type] = 0; /* same MB type => weight is null */
/* binary tree parsing probabilities */
p02 = p[0] + p[2];
p34 = p[3] + p[4];
p0234 = p02 + p34;
p17 = p[1] + p[7];
p56 = p[5] + p[6];
p89 = p[8] + p[9];
p5689 = p56 + p89;
p156789 = p17 + p5689;
s->mb_type_model[ctx][type][1] = 1 + 255 * p0234/(1+p0234+p156789);
s->mb_type_model[ctx][type][2] = 1 + 255 * p02 / (1+p0234);
s->mb_type_model[ctx][type][3] = 1 + 255 * p17 / (1+p156789);
s->mb_type_model[ctx][type][4] = 1 + 255 * p[0] / (1+p02);
s->mb_type_model[ctx][type][5] = 1 + 255 * p[3] / (1+p34);
s->mb_type_model[ctx][type][6] = 1 + 255 * p[1] / (1+p17);
s->mb_type_model[ctx][type][7] = 1 + 255 * p56 / (1+p5689);
s->mb_type_model[ctx][type][8] = 1 + 255 * p[5] / (1+p56);
s->mb_type_model[ctx][type][9] = 1 + 255 * p[8] / (1+p89);
/* restore initial value */
p[type] = 100 * s->mb_types_stats[ctx][type][1];
}
}
}
static vp56_mb_t vp56_parse_mb_type(vp56_context_t *s,
vp56_mb_t prev_type, int ctx)
{
uint8_t *mb_type_model = s->mb_type_model[ctx][prev_type];
vp56_range_coder_t *c = &s->c;
if (vp56_rac_get_prob(c, mb_type_model[0]))
return prev_type;
else
return vp56_rac_get_tree(c, vp56_pmbt_tree, mb_type_model);
}
static void vp56_decode_4mv(vp56_context_t *s, int row, int col)
{
vp56_mv_t mv = {0,0};
int type[4];
int b;
/* parse each block type */
for (b=0; b<4; b++) {
type[b] = vp56_rac_gets(&s->c, 2);
if (type[b])
type[b]++; /* only returns 0, 2, 3 or 4 (all INTER_PF) */
}
/* get vectors */
for (b=0; b<4; b++) {
switch (type[b]) {
case VP56_MB_INTER_NOVEC_PF:
s->mv[b] = (vp56_mv_t) {0,0};
break;
case VP56_MB_INTER_DELTA_PF:
s->parse_vector_adjustment(s, &s->mv[b]);
break;
case VP56_MB_INTER_V1_PF:
s->mv[b] = s->vector_candidate[0];
break;
case VP56_MB_INTER_V2_PF:
s->mv[b] = s->vector_candidate[1];
break;
}
mv.x += s->mv[b].x;
mv.y += s->mv[b].y;
}
/* this is the one selected for the whole MB for prediction */
s->macroblocks[row * s->mb_width + col].mv = s->mv[3];
/* chroma vectors are average luma vectors */
if (s->avctx->codec->id == CODEC_ID_VP5) {
s->mv[4].x = s->mv[5].x = RSHIFT(mv.x,2);
s->mv[4].y = s->mv[5].y = RSHIFT(mv.y,2);
} else {
s->mv[4] = s->mv[5] = (vp56_mv_t) {mv.x/4, mv.y/4};
}
}
static vp56_mb_t vp56_decode_mv(vp56_context_t *s, int row, int col)
{
vp56_mv_t *mv, vector = {0,0};
int ctx, b;
ctx = vp56_get_vectors_predictors(s, row, col, VP56_FRAME_PREVIOUS);
s->mb_type = vp56_parse_mb_type(s, s->mb_type, ctx);
s->macroblocks[row * s->mb_width + col].type = s->mb_type;
switch (s->mb_type) {
case VP56_MB_INTER_V1_PF:
mv = &s->vector_candidate[0];
break;
case VP56_MB_INTER_V2_PF:
mv = &s->vector_candidate[1];
break;
case VP56_MB_INTER_V1_GF:
vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN);
mv = &s->vector_candidate[0];
break;
case VP56_MB_INTER_V2_GF:
vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN);
mv = &s->vector_candidate[1];
break;
case VP56_MB_INTER_DELTA_PF:
s->parse_vector_adjustment(s, &vector);
mv = &vector;
break;
case VP56_MB_INTER_DELTA_GF:
vp56_get_vectors_predictors(s, row, col, VP56_FRAME_GOLDEN);
s->parse_vector_adjustment(s, &vector);
mv = &vector;
break;
case VP56_MB_INTER_4V:
vp56_decode_4mv(s, row, col);
return s->mb_type;
default:
mv = &vector;
break;
}
s->macroblocks[row*s->mb_width + col].mv = *mv;
/* same vector for all blocks */
for (b=0; b<6; b++)
s->mv[b] = *mv;
return s->mb_type;
}
static void vp56_add_predictors_dc(vp56_context_t *s, vp56_frame_t ref_frame)
{
int idx = s->scantable.permutated[0];
int i;
for (i=0; i<6; i++) {
vp56_ref_dc_t *ab = &s->above_blocks[s->above_block_idx[i]];
vp56_ref_dc_t *lb = &s->left_block[vp56_b6to4[i]];
int count = 0;
int dc = 0;
if (ref_frame == lb->ref_frame) {
dc += lb->dc_coeff;
count++;
}
if (ref_frame == ab->ref_frame) {
dc += ab->dc_coeff;
count++;
}
if (s->avctx->codec->id == CODEC_ID_VP5) {
if (count < 2 && ref_frame == ab[-1].ref_frame) {
dc += ab[-1].dc_coeff;
count++;
}
if (count < 2 && ref_frame == ab[1].ref_frame) {
dc += ab[1].dc_coeff;
count++;
}
}
if (count == 0)
dc = s->prev_dc[vp56_b6to3[i]][ref_frame];
else if (count == 2)
dc /= 2;
s->block_coeff[i][idx] += dc;
s->prev_dc[vp56_b6to3[i]][ref_frame] = s->block_coeff[i][idx];
ab->dc_coeff = s->block_coeff[i][idx];
ab->ref_frame = ref_frame;
lb->dc_coeff = s->block_coeff[i][idx];
lb->ref_frame = ref_frame;
s->block_coeff[i][idx] *= s->dequant_dc;
}
}
static void vp56_edge_filter(vp56_context_t *s, uint8_t *yuv,
int pix_inc, int line_inc, int t)
{
int pix2_inc = 2 * pix_inc;
int i, v;
for (i=0; i<12; i++) {
v = (yuv[-pix2_inc] + 3*(yuv[0]-yuv[-pix_inc]) - yuv[pix_inc] + 4) >>3;
v = s->adjust(v, t);
yuv[-pix_inc] = clip_uint8(yuv[-pix_inc] + v);
yuv[0] = clip_uint8(yuv[0] - v);
yuv += line_inc;
}
}
static void vp56_deblock_filter(vp56_context_t *s, uint8_t *yuv,
int stride, int dx, int dy)
{
int t = vp56_filter_threshold[s->quantizer];
if (dx) vp56_edge_filter(s, yuv + 10-dx , 1, stride, t);
if (dy) vp56_edge_filter(s, yuv + stride*(10-dy), stride, 1, t);
}
static void vp56_mc(vp56_context_t *s, int b, uint8_t *src,
int stride, int x, int y)
{
int plane = vp56_b6to3[b];
uint8_t *dst= s->frames[VP56_FRAME_CURRENT].data[plane]+s->block_offset[b];
uint8_t *src_block;
int src_offset;
int overlap_offset = 0;
int mask = s->vp56_coord_div[b] - 1;
int deblock_filtering = s->deblock_filtering;
int dx;
int dy;
if (s->avctx->skip_loop_filter >= AVDISCARD_ALL ||
(s->avctx->skip_loop_filter >= AVDISCARD_NONKEY
&& !s->frames[VP56_FRAME_CURRENT].key_frame))
deblock_filtering = 0;
dx = s->mv[b].x / s->vp56_coord_div[b];
dy = s->mv[b].y / s->vp56_coord_div[b];
if (b >= 4) {
x /= 2;
y /= 2;
}
x += dx - 2;
y += dy - 2;
if (x<0 || x+12>=s->plane_width[plane] ||
y<0 || y+12>=s->plane_height[plane]) {
ff_emulated_edge_mc(s->edge_emu_buffer,
src + s->block_offset[b] + (dy-2)*stride + (dx-2),
stride, 12, 12, x, y,
s->plane_width[plane],
s->plane_height[plane]);
src_block = s->edge_emu_buffer;
src_offset = 2 + 2*stride;
} else if (deblock_filtering) {
/* only need a 12x12 block, but there is no such dsp function, */
/* so copy a 16x12 block */
s->dsp.put_pixels_tab[0][0](s->edge_emu_buffer,
src + s->block_offset[b] + (dy-2)*stride + (dx-2),
stride, 12);
src_block = s->edge_emu_buffer;
src_offset = 2 + 2*stride;
} else {
src_block = src;
src_offset = s->block_offset[b] + dy*stride + dx;
}
if (deblock_filtering)
vp56_deblock_filter(s, src_block, stride, dx&7, dy&7);
if (s->mv[b].x & mask)
overlap_offset += (s->mv[b].x > 0) ? 1 : -1;
if (s->mv[b].y & mask)
overlap_offset += (s->mv[b].y > 0) ? stride : -stride;
if (overlap_offset) {
if (s->filter)
s->filter(s, dst, src_block, src_offset, src_offset+overlap_offset,
stride, s->mv[b], mask, s->filter_selection, b<4);
else
s->dsp.put_no_rnd_pixels_l2[1](dst, src_block+src_offset,
src_block+src_offset+overlap_offset,
stride, 8);
} else {
s->dsp.put_pixels_tab[1][0](dst, src_block+src_offset, stride, 8);
}
}
static void vp56_decode_mb(vp56_context_t *s, int row, int col)
{
AVFrame *frame_current, *frame_ref;
vp56_mb_t mb_type;
vp56_frame_t ref_frame;
int b, plan, off;
if (s->frames[VP56_FRAME_CURRENT].key_frame)
mb_type = VP56_MB_INTRA;
else
mb_type = vp56_decode_mv(s, row, col);
ref_frame = vp56_reference_frame[mb_type];
memset(s->block_coeff, 0, sizeof(s->block_coeff));
s->parse_coeff(s);
vp56_add_predictors_dc(s, ref_frame);
frame_current = &s->frames[VP56_FRAME_CURRENT];
frame_ref = &s->frames[ref_frame];
switch (mb_type) {
case VP56_MB_INTRA:
for (b=0; b<6; b++) {
plan = vp56_b6to3[b];
s->dsp.idct_put(frame_current->data[plan] + s->block_offset[b],
s->stride[plan], s->block_coeff[b]);
}
break;
case VP56_MB_INTER_NOVEC_PF:
case VP56_MB_INTER_NOVEC_GF:
for (b=0; b<6; b++) {
plan = vp56_b6to3[b];
off = s->block_offset[b];
s->dsp.put_pixels_tab[1][0](frame_current->data[plan] + off,
frame_ref->data[plan] + off,
s->stride[plan], 8);
s->dsp.idct_add(frame_current->data[plan] + off,
s->stride[plan], s->block_coeff[b]);
}
break;
case VP56_MB_INTER_DELTA_PF:
case VP56_MB_INTER_V1_PF:
case VP56_MB_INTER_V2_PF:
case VP56_MB_INTER_DELTA_GF:
case VP56_MB_INTER_4V:
case VP56_MB_INTER_V1_GF:
case VP56_MB_INTER_V2_GF:
for (b=0; b<6; b++) {
int x_off = b==1 || b==3 ? 8 : 0;
int y_off = b==2 || b==3 ? 8 : 0;
plan = vp56_b6to3[b];
vp56_mc(s, b, frame_ref->data[plan], s->stride[plan],
16*col+x_off, 16*row+y_off);
s->dsp.idct_add(frame_current->data[plan] + s->block_offset[b],
s->stride[plan], s->block_coeff[b]);
}
break;
}
}
static int vp56_size_changed(AVCodecContext *avctx, vp56_context_t *s)
{
int stride = s->frames[VP56_FRAME_CURRENT].linesize[0];
int i;
s->plane_width[0] = s->avctx->width;
s->plane_width[1] = s->plane_width[2] = s->avctx->width/2;
s->plane_height[0] = s->avctx->height;
s->plane_height[1] = s->plane_height[2] = s->avctx->height/2;
for (i=0; i<3; i++)
s->stride[i] = s->flip * s->frames[VP56_FRAME_CURRENT].linesize[i];
s->mb_width = (s->avctx->width+15) / 16;
s->mb_height = (s->avctx->height+15) / 16;
if (s->mb_width > 1000 || s->mb_height > 1000) {
av_log(avctx, AV_LOG_ERROR, "picture too big\n");
return -1;
}
s->above_blocks = av_realloc(s->above_blocks,
(4*s->mb_width+6) * sizeof(*s->above_blocks));
s->macroblocks = av_realloc(s->macroblocks,
s->mb_width*s->mb_height*sizeof(*s->macroblocks));
s->edge_emu_buffer_alloc = av_realloc(s->edge_emu_buffer_alloc, 16*stride);
s->edge_emu_buffer = s->edge_emu_buffer_alloc;
if (s->flip < 0)
s->edge_emu_buffer += 15 * stride;
return 0;
}
int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
uint8_t *buf, int buf_size)
{
vp56_context_t *s = avctx->priv_data;
AVFrame *const p = &s->frames[VP56_FRAME_CURRENT];
AVFrame *picture = data;
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;
res = s->parse_header(s, buf, buf_size, &golden_frame);
if (!res)
return -1;
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, s)) {
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;
/* main macroblocks loop */
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[block], 0, 64*sizeof(s->coeff_ctx[block][0]));
}
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);
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 (s->frames[VP56_FRAME_PREVIOUS].data[0]
&& (s->frames[VP56_FRAME_PREVIOUS].data[0]
!= s->frames[VP56_FRAME_GOLDEN].data[0])) {
avctx->release_buffer(avctx, &s->frames[VP56_FRAME_PREVIOUS]);
}
if (p->key_frame || golden_frame) {
if (s->frames[VP56_FRAME_GOLDEN].data[0])
avctx->release_buffer(avctx, &s->frames[VP56_FRAME_GOLDEN]);
s->frames[VP56_FRAME_GOLDEN] = *p;
}
s->frames[VP56_FRAME_PREVIOUS] = *p;
*picture = *p;
*data_size = sizeof(AVPicture);
return buf_size;
}
void vp56_init(vp56_context_t *s, AVCodecContext *avctx, int flip)
{
int i;
s->avctx = avctx;
avctx->pix_fmt = PIX_FMT_YUV420P;
if (s->avctx->idct_algo == FF_IDCT_AUTO)
s->avctx->idct_algo = FF_IDCT_VP3;
dsputil_init(&s->dsp, s->avctx);
ff_init_scantable(s->dsp.idct_permutation, &s->scantable,ff_zigzag_direct);
avcodec_set_dimensions(s->avctx, 0, 0);
for (i=0; i<3; i++)
s->frames[i].data[0] = NULL;
s->edge_emu_buffer_alloc = NULL;
s->above_blocks = NULL;
s->macroblocks = NULL;
s->quantizer = -1;
s->deblock_filtering = 1;
s->filter = NULL;
if (flip) {
s->flip = -1;
s->frbi = 2;
s->srbi = 0;
} else {
s->flip = 1;
s->frbi = 0;
s->srbi = 2;
}
}
int vp56_free(AVCodecContext *avctx)
{
vp56_context_t *s = avctx->priv_data;
av_free(s->above_blocks);
av_free(s->macroblocks);
av_free(s->edge_emu_buffer_alloc);
if (s->frames[VP56_FRAME_GOLDEN].data[0]
&& (s->frames[VP56_FRAME_PREVIOUS].data[0]
!= s->frames[VP56_FRAME_GOLDEN].data[0]))
avctx->release_buffer(avctx, &s->frames[VP56_FRAME_GOLDEN]);
if (s->frames[VP56_FRAME_PREVIOUS].data[0])
avctx->release_buffer(avctx, &s->frames[VP56_FRAME_PREVIOUS]);
return 0;
}

248
libavcodec/vp56.h Normal file
View File

@ -0,0 +1,248 @@
/**
* @file vp56.h
* VP5 and VP6 compatible video decoder (common features)
*
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef VP56_H
#define VP56_H
#include <stdint.h>
#include "vp56data.h"
#include "dsputil.h"
#include "mpegvideo.h"
typedef struct vp56_context vp56_context_t;
typedef struct vp56_mv vp56_mv_t;
typedef void (*vp56_parse_vector_adjustment_t)(vp56_context_t *s,
vp56_mv_t *vector);
typedef int (*vp56_adjust_t)(int v, int t);
typedef void (*vp56_filter_t)(vp56_context_t *s, uint8_t *dst, uint8_t *src,
int offset1, int offset2, int stride,
vp56_mv_t mv, int mask, int select, int luma);
typedef void (*vp56_parse_coeff_t)(vp56_context_t *s);
typedef void (*vp56_default_models_init_t)(vp56_context_t *s);
typedef void (*vp56_parse_vector_models_t)(vp56_context_t *s);
typedef void (*vp56_parse_coeff_models_t)(vp56_context_t *s);
typedef int (*vp56_parse_header_t)(vp56_context_t *s, uint8_t *buf,
int buf_size, int *golden_frame);
typedef struct {
int high;
int bits;
const uint8_t *buffer;
unsigned long code_word;
} vp56_range_coder_t;
typedef struct {
uint8_t not_null_dc;
vp56_frame_t ref_frame;
DCTELEM dc_coeff;
} vp56_ref_dc_t;
struct vp56_mv {
int x;
int y;
};
typedef struct {
uint8_t type;
vp56_mv_t mv;
} vp56_macroblock_t;
struct vp56_context {
AVCodecContext *avctx;
DSPContext dsp;
ScanTable scantable;
AVFrame frames[3];
uint8_t *edge_emu_buffer_alloc;
uint8_t *edge_emu_buffer;
vp56_range_coder_t c;
/* frame info */
int plane_width[3];
int plane_height[3];
int mb_width; /* number of horizontal MB */
int mb_height; /* number of vertical MB */
int block_offset[6];
int quantizer;
uint16_t dequant_dc;
uint16_t dequant_ac;
/* DC predictors management */
vp56_ref_dc_t *above_blocks;
vp56_ref_dc_t left_block[4];
int above_block_idx[6];
DCTELEM prev_dc[3][3]; /* [plan][ref_frame] */
/* blocks / macroblock */
vp56_mb_t mb_type;
vp56_macroblock_t *macroblocks;
DECLARE_ALIGNED_16(DCTELEM, block_coeff[6][64]);
uint8_t coeff_reorder[64]; /* used in vp6 only */
uint8_t coeff_index_to_pos[64]; /* used in vp6 only */
/* motion vectors */
vp56_mv_t mv[6]; /* vectors for each block in MB */
vp56_mv_t vector_candidate[2];
int vector_candidate_pos;
/* filtering hints */
int deblock_filtering;
int filter_selection;
int filter_mode;
int max_vector_length;
int sample_variance_threshold;
/* AC models */
uint8_t vector_model_sig[2]; /* delta sign */
uint8_t vector_model_dct[2]; /* delta coding types */
uint8_t vector_model_pdi[2][2]; /* predefined delta init */
uint8_t vector_model_pdv[2][7]; /* predefined delta values */
uint8_t vector_model_fdv[2][8]; /* 8 bit delta value definition */
uint8_t mb_type_model[3][10][10]; /* model for decoding MB type */
uint8_t coeff_model_dccv[2][11]; /* DC coeff value */
uint8_t coeff_model_ract[2][3][6][11]; /* Run/AC coding type and AC coeff value */
uint8_t coeff_model_acct[2][3][3][6][5];/* vp5 only AC coding type for coding group < 3 */
uint8_t coeff_model_dcct[2][36][5]; /* DC coeff coding type */
uint8_t coeff_model_runv[2][14]; /* run value (vp6 only) */
uint8_t mb_types_stats[3][10][2]; /* contextual, next MB type stats */
uint8_t coeff_ctx[4][64]; /* used in vp5 only */
uint8_t coeff_ctx_last[4]; /* used in vp5 only */
/* upside-down flipping hints */
int flip; /* are we flipping ? */
int frbi; /* first row block index in MB */
int srbi; /* second row block index in MB */
int stride[3]; /* stride for each plan */
const uint8_t *vp56_coord_div;
vp56_parse_vector_adjustment_t parse_vector_adjustment;
vp56_adjust_t adjust;
vp56_filter_t filter;
vp56_parse_coeff_t parse_coeff;
vp56_default_models_init_t default_models_init;
vp56_parse_vector_models_t parse_vector_models;
vp56_parse_coeff_models_t parse_coeff_models;
vp56_parse_header_t parse_header;
};
void vp56_init(vp56_context_t *s, AVCodecContext *avctx, int flip);
int vp56_free(AVCodecContext *avctx);
void vp56_init_dequant(vp56_context_t *s, int quantizer);
int vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
uint8_t *buf, int buf_size);
/**
* vp56 specific range coder implementation
*/
static inline void vp56_init_range_decoder(vp56_range_coder_t *c,
const uint8_t *buf, int buf_size)
{
c->high = 255;
c->bits = 8;
c->buffer = buf;
c->code_word = *c->buffer++ << 8;
c->code_word |= *c->buffer++;
}
static inline int vp56_rac_get_prob(vp56_range_coder_t *c, uint8_t prob)
{
unsigned int low = 1 + (((c->high - 1) * prob) / 256);
unsigned int low_shift = low << 8;
int bit = c->code_word >= low_shift;
if (bit) {
c->high -= low;
c->code_word -= low_shift;
} else {
c->high = low;
}
/* normalize */
while (c->high < 128) {
c->high <<= 1;
c->code_word <<= 1;
if (--c->bits == 0) {
c->bits = 8;
c->code_word |= *c->buffer++;
}
}
return bit;
}
static inline int vp56_rac_get(vp56_range_coder_t *c)
{
/* equiprobable */
int low = (c->high + 1) >> 1;
unsigned int low_shift = low << 8;
int bit = c->code_word >= low_shift;
if (bit) {
c->high = (c->high - low) << 1;
c->code_word -= low_shift;
} else {
c->high = low << 1;
}
/* normalize */
c->code_word <<= 1;
if (--c->bits == 0) {
c->bits = 8;
c->code_word |= *c->buffer++;
}
return bit;
}
static inline int vp56_rac_gets(vp56_range_coder_t *c, int bits)
{
int value = 0;
while (bits--) {
value = (value << 1) | vp56_rac_get(c);
}
return value;
}
static inline int vp56_rac_gets_nn(vp56_range_coder_t *c, int bits)
{
int v = vp56_rac_gets(c, 7) << 1;
return v + !v;
}
static inline int vp56_rac_get_tree(vp56_range_coder_t *c,
const vp56_tree_t *tree,
const uint8_t *probs)
{
while (tree->val > 0) {
if (vp56_rac_get_prob(c, probs[tree->prob_idx]))
tree += tree->val;
else
tree++;
}
return -tree->val;
}
#endif /* VP56_H */

65
libavcodec/vp56data.c Normal file
View File

@ -0,0 +1,65 @@
/**
* @file vp56data.c
* VP5 and VP6 compatible video decoder (common data)
*
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include "vp56data.h"
const uint8_t vp56_b6to3[] = { 0, 0, 0, 0, 1, 2 };
const uint8_t vp56_b6to4[] = { 0, 0, 1, 1, 2, 3 };
const uint8_t vp56_coeff_parse_table[6][11] = {
{ 159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 145, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 140, 148, 173, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 135, 140, 155, 176, 0, 0, 0, 0, 0, 0, 0 },
{ 130, 134, 141, 157, 180, 0, 0, 0, 0, 0, 0 },
{ 129, 130, 133, 140, 153, 177, 196, 230, 243, 254, 254 },
};
const uint8_t vp56_def_mb_types_stats[3][10][2] = {
{ { 69, 42 }, { 1, 2 }, { 1, 7 }, { 44, 42 }, { 6, 22 },
{ 1, 3 }, { 0, 2 }, { 1, 5 }, { 0, 1 }, { 0, 0 }, },
{ { 229, 8 }, { 1, 1 }, { 0, 8 }, { 0, 0 }, { 0, 0 },
{ 1, 2 }, { 0, 1 }, { 0, 0 }, { 1, 1 }, { 0, 0 }, },
{ { 122, 35 }, { 1, 1 }, { 1, 6 }, { 46, 34 }, { 0, 0 },
{ 1, 2 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 0, 0 }, },
};
const vp56_tree_t vp56_pva_tree[] = {
{ 8, 0},
{ 4, 1},
{ 2, 2}, {-0}, {-1},
{ 2, 3}, {-2}, {-3},
{ 4, 4},
{ 2, 5}, {-4}, {-5},
{ 2, 6}, {-6}, {-7},
};
const vp56_tree_t vp56_pc_tree[] = {
{ 4, 6},
{ 2, 7}, {-0}, {-1},
{ 4, 8},
{ 2, 9}, {-2}, {-3},
{ 2,10}, {-4}, {-5},
};
const uint8_t vp56_coeff_bias[] = { 5, 7, 11, 19, 35, 67 };
const uint8_t vp56_coeff_bit_length[] = { 0, 1, 2, 3, 4, 10 };

246
libavcodec/vp56data.h Normal file
View File

@ -0,0 +1,246 @@
/**
* @file vp56data.h
* VP5 and VP6 compatible video decoder (common data)
*
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef VP56DATA_H
#define VP56DATA_H
#include <inttypes.h>
typedef enum {
VP56_FRAME_CURRENT = 0,
VP56_FRAME_PREVIOUS = 1,
VP56_FRAME_GOLDEN = 2,
} vp56_frame_t;
typedef enum {
VP56_MB_INTER_NOVEC_PF = 0, /**< Inter MB, no vector, from previous frame */
VP56_MB_INTRA = 1, /**< Intra MB */
VP56_MB_INTER_DELTA_PF = 2, /**< Inter MB, above/left vector + delta, from previous frame */
VP56_MB_INTER_V1_PF = 3, /**< Inter MB, first vector, from previous frame */
VP56_MB_INTER_V2_PF = 4, /**< Inter MB, second vector, from previous frame */
VP56_MB_INTER_NOVEC_GF = 5, /**< Inter MB, no vector, from golden frame */
VP56_MB_INTER_DELTA_GF = 6, /**< Inter MB, above/left vector + delta, from golden frame */
VP56_MB_INTER_4V = 7, /**< Inter MB, 4 vectors, from previous frame */
VP56_MB_INTER_V1_GF = 8, /**< Inter MB, first vector, from golden frame */
VP56_MB_INTER_V2_GF = 9, /**< Inter MB, second vector, from golden frame */
} vp56_mb_t;
typedef struct {
int8_t val;
int8_t prob_idx;
} vp56_tree_t;
extern const uint8_t vp56_b6to3[];
extern const uint8_t vp56_b6to4[];
extern const uint8_t vp56_coeff_parse_table[6][11];
extern const uint8_t vp56_def_mb_types_stats[3][10][2];
extern const vp56_tree_t vp56_pva_tree[];
extern const vp56_tree_t vp56_pc_tree[];
extern const uint8_t vp56_coeff_bias[];
extern const uint8_t vp56_coeff_bit_length[];
static const vp56_frame_t vp56_reference_frame[] = {
VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_NOVEC_PF */
VP56_FRAME_CURRENT, /* VP56_MB_INTRA */
VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_DELTA_PF */
VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_V1_PF */
VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_V2_PF */
VP56_FRAME_GOLDEN, /* VP56_MB_INTER_NOVEC_GF */
VP56_FRAME_GOLDEN, /* VP56_MB_INTER_DELTA_GF */
VP56_FRAME_PREVIOUS, /* VP56_MB_INTER_4V */
VP56_FRAME_GOLDEN, /* VP56_MB_INTER_V1_GF */
VP56_FRAME_GOLDEN, /* VP56_MB_INTER_V2_GF */
};
static const uint8_t vp56_ac_dequant[64] = {
94, 92, 90, 88, 86, 82, 78, 74,
70, 66, 62, 58, 54, 53, 52, 51,
50, 49, 48, 47, 46, 45, 44, 43,
42, 40, 39, 37, 36, 35, 34, 33,
32, 31, 30, 29, 28, 27, 26, 25,
24, 23, 22, 21, 20, 19, 18, 17,
16, 15, 14, 13, 12, 11, 10, 9,
8, 7, 6, 5, 4, 3, 2, 1,
};
static const uint8_t vp56_dc_dequant[64] = {
47, 47, 47, 47, 45, 43, 43, 43,
43, 43, 42, 41, 41, 40, 40, 40,
40, 35, 35, 35, 35, 33, 33, 33,
33, 32, 32, 32, 27, 27, 26, 26,
25, 25, 24, 24, 23, 23, 19, 19,
19, 19, 18, 18, 17, 16, 16, 16,
16, 16, 15, 11, 11, 11, 10, 10,
9, 8, 7, 5, 3, 3, 2, 2,
};
static const uint8_t vp56_pre_def_mb_type_stats[16][3][10][2] = {
{ { { 9, 15 }, { 32, 25 }, { 7, 19 }, { 9, 21 }, { 1, 12 },
{ 14, 12 }, { 3, 18 }, { 14, 23 }, { 3, 10 }, { 0, 4 }, },
{ { 41, 22 }, { 1, 0 }, { 1, 31 }, { 0, 0 }, { 0, 0 },
{ 0, 1 }, { 1, 7 }, { 0, 1 }, { 98, 25 }, { 4, 10 }, },
{ { 2, 3 }, { 2, 3 }, { 0, 2 }, { 0, 2 }, { 0, 0 },
{ 11, 4 }, { 1, 4 }, { 0, 2 }, { 3, 2 }, { 0, 4 }, }, },
{ { { 48, 39 }, { 1, 2 }, { 11, 27 }, { 29, 44 }, { 7, 27 },
{ 1, 4 }, { 0, 3 }, { 1, 6 }, { 1, 2 }, { 0, 0 }, },
{ { 123, 37 }, { 6, 4 }, { 1, 27 }, { 0, 0 }, { 0, 0 },
{ 5, 8 }, { 1, 7 }, { 0, 1 }, { 12, 10 }, { 0, 2 }, },
{ { 49, 46 }, { 3, 4 }, { 7, 31 }, { 42, 41 }, { 0, 0 },
{ 2, 6 }, { 1, 7 }, { 1, 4 }, { 2, 4 }, { 0, 1 }, }, },
{ { { 21, 32 }, { 1, 2 }, { 4, 10 }, { 32, 43 }, { 6, 23 },
{ 2, 3 }, { 1, 19 }, { 1, 6 }, { 12, 21 }, { 0, 7 }, },
{ { 26, 14 }, { 14, 12 }, { 0, 24 }, { 0, 0 }, { 0, 0 },
{ 55, 17 }, { 1, 9 }, { 0, 36 }, { 5, 7 }, { 1, 3 }, },
{ { 26, 25 }, { 1, 1 }, { 2, 10 }, { 67, 39 }, { 0, 0 },
{ 1, 1 }, { 0, 14 }, { 0, 2 }, { 31, 26 }, { 1, 6 }, }, },
{ { { 69, 83 }, { 0, 0 }, { 0, 2 }, { 10, 29 }, { 3, 12 },
{ 0, 1 }, { 0, 3 }, { 0, 3 }, { 2, 2 }, { 0, 0 }, },
{ { 209, 5 }, { 0, 0 }, { 0, 27 }, { 0, 0 }, { 0, 0 },
{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, },
{ { 103, 46 }, { 1, 2 }, { 2, 10 }, { 33, 42 }, { 0, 0 },
{ 1, 4 }, { 0, 3 }, { 0, 1 }, { 1, 3 }, { 0, 0 }, }, },
{ { { 11, 20 }, { 1, 4 }, { 18, 36 }, { 43, 48 }, { 13, 35 },
{ 0, 2 }, { 0, 5 }, { 3, 12 }, { 1, 2 }, { 0, 0 }, },
{ { 2, 5 }, { 4, 5 }, { 0, 121 }, { 0, 0 }, { 0, 0 },
{ 0, 3 }, { 2, 4 }, { 1, 4 }, { 2, 2 }, { 0, 1 }, },
{ { 14, 31 }, { 9, 13 }, { 14, 54 }, { 22, 29 }, { 0, 0 },
{ 2, 6 }, { 4, 18 }, { 6, 13 }, { 1, 5 }, { 0, 1 }, }, },
{ { { 70, 44 }, { 0, 1 }, { 2, 10 }, { 37, 46 }, { 8, 26 },
{ 0, 2 }, { 0, 2 }, { 0, 2 }, { 0, 1 }, { 0, 0 }, },
{ { 175, 5 }, { 0, 1 }, { 0, 48 }, { 0, 0 }, { 0, 0 },
{ 0, 2 }, { 0, 1 }, { 0, 2 }, { 0, 1 }, { 0, 0 }, },
{ { 85, 39 }, { 0, 0 }, { 1, 9 }, { 69, 40 }, { 0, 0 },
{ 0, 1 }, { 0, 3 }, { 0, 1 }, { 2, 3 }, { 0, 0 }, }, },
{ { { 8, 15 }, { 0, 1 }, { 8, 21 }, { 74, 53 }, { 22, 42 },
{ 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 0, 0 }, },
{ { 83, 5 }, { 2, 3 }, { 0, 102 }, { 0, 0 }, { 0, 0 },
{ 1, 3 }, { 0, 2 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, },
{ { 31, 28 }, { 0, 0 }, { 3, 14 }, { 130, 34 }, { 0, 0 },
{ 0, 1 }, { 0, 3 }, { 0, 1 }, { 3, 3 }, { 0, 1 }, }, },
{ { { 141, 42 }, { 0, 0 }, { 1, 4 }, { 11, 24 }, { 1, 11 },
{ 0, 1 }, { 0, 1 }, { 0, 2 }, { 0, 0 }, { 0, 0 }, },
{ { 233, 6 }, { 0, 0 }, { 0, 8 }, { 0, 0 }, { 0, 0 },
{ 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 1 }, { 0, 0 }, },
{ { 171, 25 }, { 0, 0 }, { 1, 5 }, { 25, 21 }, { 0, 0 },
{ 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, }, },
{ { { 8, 19 }, { 4, 10 }, { 24, 45 }, { 21, 37 }, { 9, 29 },
{ 0, 3 }, { 1, 7 }, { 11, 25 }, { 0, 2 }, { 0, 1 }, },
{ { 34, 16 }, { 112, 21 }, { 1, 28 }, { 0, 0 }, { 0, 0 },
{ 6, 8 }, { 1, 7 }, { 0, 3 }, { 2, 5 }, { 0, 2 }, },
{ { 17, 21 }, { 68, 29 }, { 6, 15 }, { 13, 22 }, { 0, 0 },
{ 6, 12 }, { 3, 14 }, { 4, 10 }, { 1, 7 }, { 0, 3 }, }, },
{ { { 46, 42 }, { 0, 1 }, { 2, 10 }, { 54, 51 }, { 10, 30 },
{ 0, 2 }, { 0, 2 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, },
{ { 159, 35 }, { 2, 2 }, { 0, 25 }, { 0, 0 }, { 0, 0 },
{ 3, 6 }, { 0, 5 }, { 0, 1 }, { 4, 4 }, { 0, 1 }, },
{ { 51, 39 }, { 0, 1 }, { 2, 12 }, { 91, 44 }, { 0, 0 },
{ 0, 2 }, { 0, 3 }, { 0, 1 }, { 2, 3 }, { 0, 1 }, }, },
{ { { 28, 32 }, { 0, 0 }, { 3, 10 }, { 75, 51 }, { 14, 33 },
{ 0, 1 }, { 0, 2 }, { 0, 1 }, { 1, 2 }, { 0, 0 }, },
{ { 75, 39 }, { 5, 7 }, { 2, 48 }, { 0, 0 }, { 0, 0 },
{ 3, 11 }, { 2, 16 }, { 1, 4 }, { 7, 10 }, { 0, 2 }, },
{ { 81, 25 }, { 0, 0 }, { 2, 9 }, { 106, 26 }, { 0, 0 },
{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 0, 0 }, }, },
{ { { 100, 46 }, { 0, 1 }, { 3, 9 }, { 21, 37 }, { 5, 20 },
{ 0, 1 }, { 0, 2 }, { 1, 2 }, { 0, 1 }, { 0, 0 }, },
{ { 212, 21 }, { 0, 1 }, { 0, 9 }, { 0, 0 }, { 0, 0 },
{ 1, 2 }, { 0, 2 }, { 0, 0 }, { 2, 2 }, { 0, 0 }, },
{ { 140, 37 }, { 0, 1 }, { 1, 8 }, { 24, 33 }, { 0, 0 },
{ 1, 2 }, { 0, 2 }, { 0, 1 }, { 1, 2 }, { 0, 0 }, }, },
{ { { 27, 29 }, { 0, 1 }, { 9, 25 }, { 53, 51 }, { 12, 34 },
{ 0, 1 }, { 0, 3 }, { 1, 5 }, { 0, 2 }, { 0, 0 }, },
{ { 4, 2 }, { 0, 0 }, { 0, 172 }, { 0, 0 }, { 0, 0 },
{ 0, 1 }, { 0, 2 }, { 0, 0 }, { 2, 0 }, { 0, 0 }, },
{ { 14, 23 }, { 1, 3 }, { 11, 53 }, { 90, 31 }, { 0, 0 },
{ 0, 3 }, { 1, 5 }, { 2, 6 }, { 1, 2 }, { 0, 0 }, }, },
{ { { 80, 38 }, { 0, 0 }, { 1, 4 }, { 69, 33 }, { 5, 16 },
{ 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 1 }, { 0, 0 }, },
{ { 187, 22 }, { 1, 1 }, { 0, 17 }, { 0, 0 }, { 0, 0 },
{ 3, 6 }, { 0, 4 }, { 0, 1 }, { 4, 4 }, { 0, 1 }, },
{ { 123, 29 }, { 0, 0 }, { 1, 7 }, { 57, 30 }, { 0, 0 },
{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, }, },
{ { { 16, 20 }, { 0, 0 }, { 2, 8 }, { 104, 49 }, { 15, 33 },
{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 0, 0 }, },
{ { 133, 6 }, { 1, 2 }, { 1, 70 }, { 0, 0 }, { 0, 0 },
{ 0, 2 }, { 0, 4 }, { 0, 3 }, { 1, 1 }, { 0, 0 }, },
{ { 13, 14 }, { 0, 0 }, { 4, 20 }, { 175, 20 }, { 0, 0 },
{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 1, 1 }, { 0, 0 }, }, },
{ { { 194, 16 }, { 0, 0 }, { 1, 1 }, { 1, 9 }, { 1, 3 },
{ 0, 0 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, },
{ { 251, 1 }, { 0, 0 }, { 0, 2 }, { 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, },
{ { 202, 23 }, { 0, 0 }, { 1, 3 }, { 2, 9 }, { 0, 0 },
{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 0 }, { 0, 0 }, }, },
};
static const uint8_t vp56_filter_threshold[] = {
14, 14, 13, 13, 12, 12, 10, 10,
10, 10, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 7, 7, 7, 7,
7, 7, 6, 6, 6, 6, 6, 6,
5, 5, 5, 5, 4, 4, 4, 4,
4, 4, 4, 3, 3, 3, 3, 2,
};
static const uint8_t vp56_mb_type_model_model[] = {
171, 83, 199, 140, 125, 104,
};
static const vp56_tree_t vp56_pmbtm_tree[] = {
{ 4, 0},
{ 2, 1}, {-8}, {-4},
{ 8, 2},
{ 6, 3},
{ 4, 4},
{ 2, 5}, {-24}, {-20}, {-16}, {-12}, {-0},
};
static const vp56_tree_t vp56_pmbt_tree[] = {
{ 8, 1},
{ 4, 2},
{ 2, 4}, {-VP56_MB_INTER_NOVEC_PF}, {-VP56_MB_INTER_DELTA_PF},
{ 2, 5}, {-VP56_MB_INTER_V1_PF}, {-VP56_MB_INTER_V2_PF},
{ 4, 3},
{ 2, 6}, {-VP56_MB_INTRA}, {-VP56_MB_INTER_4V},
{ 4, 7},
{ 2, 8}, {-VP56_MB_INTER_NOVEC_GF}, {-VP56_MB_INTER_DELTA_GF},
{ 2, 9}, {-VP56_MB_INTER_V1_GF}, {-VP56_MB_INTER_V2_GF},
};
/* relative pos of surrounding blocks, from closest to farthest */
static const int8_t vp56_candidate_predictor_pos[12][2] = {
{ 0, -1 },
{ -1, 0 },
{ -1, -1 },
{ 1, -1 },
{ 0, -2 },
{ -2, 0 },
{ -2, -1 },
{ -1, -2 },
{ 1, -2 },
{ 2, -1 },
{ -2, -2 },
{ 2, -2 },
};
#endif /* VP56DATA */

173
libavcodec/vp5data.h Normal file
View File

@ -0,0 +1,173 @@
/**
* @file vp5data.h
* VP5 compatible video decoder
*
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef VP5DATA_H
#define VP5DATA_H
#include <inttypes.h>
static const uint8_t vp5_coeff_groups[] = {
-1, 0, 1, 1, 2, 1, 1, 2,
2, 1, 1, 2, 2, 2, 1, 2,
2, 2, 2, 2, 1, 1, 2, 2,
3, 3, 4, 3, 4, 4, 4, 3,
3, 3, 3, 3, 4, 3, 3, 3,
4, 4, 4, 4, 4, 3, 3, 4,
4, 4, 3, 4, 4, 4, 4, 4,
4, 4, 5, 5, 5, 5, 5, 5,
};
static const uint8_t vp5_vmc_pct[2][11] = {
{ 243, 220, 251, 253, 237, 232, 241, 245, 247, 251, 253 },
{ 235, 211, 246, 249, 234, 231, 248, 249, 252, 252, 254 },
};
static const uint8_t vp5_dccv_pct[2][11] = {
{ 146, 197, 181, 207, 232, 243, 238, 251, 244, 250, 249 },
{ 179, 219, 214, 240, 250, 254, 244, 254, 254, 254, 254 },
};
static const uint8_t vp5_ract_pct[3][2][6][11] = {
{ { { 227, 246, 230, 247, 244, 254, 254, 254, 254, 254, 254 },
{ 202, 254, 209, 231, 231, 249, 249, 253, 254, 254, 254 },
{ 206, 254, 225, 242, 241, 251, 253, 254, 254, 254, 254 },
{ 235, 254, 241, 253, 252, 254, 254, 254, 254, 254, 254 },
{ 234, 254, 248, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } },
{ { 240, 254, 248, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 238, 254, 240, 253, 254, 254, 254, 254, 254, 254, 254 },
{ 244, 254, 251, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } } },
{ { { 206, 203, 227, 239, 247, 254, 253, 254, 254, 254, 254 },
{ 207, 199, 220, 236, 243, 252, 252, 254, 254, 254, 254 },
{ 212, 219, 230, 243, 244, 253, 252, 254, 254, 254, 254 },
{ 236, 237, 247, 252, 253, 254, 254, 254, 254, 254, 254 },
{ 240, 240, 248, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } },
{ { 230, 233, 249, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 238, 238, 250, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 248, 251, 254, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } } },
{ { { 225, 239, 227, 231, 244, 253, 243, 254, 254, 253, 254 },
{ 232, 234, 224, 228, 242, 249, 242, 252, 251, 251, 254 },
{ 235, 249, 238, 240, 251, 254, 249, 254, 253, 253, 254 },
{ 249, 253, 251, 250, 254, 254, 254, 254, 254, 254, 254 },
{ 251, 250, 249, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } },
{ { 243, 244, 250, 250, 254, 254, 254, 254, 254, 254, 254 },
{ 249, 248, 250, 253, 254, 254, 254, 254, 254, 254, 254 },
{ 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 },
{ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254 } } },
};
static const int16_t vp5_dccv_lc[5][36][2] = {
{ {154, 61}, {141, 54}, { 90, 45}, { 54, 34}, { 54, 13}, {128, 109},
{136, 54}, {148, 45}, { 92, 41}, { 54, 33}, { 51, 15}, { 87, 113},
{ 87, 44}, { 97, 40}, { 67, 36}, { 46, 29}, { 41, 15}, { 64, 80},
{ 59, 33}, { 61, 31}, { 51, 28}, { 44, 22}, { 33, 12}, { 49, 63},
{ 69, 12}, { 59, 16}, { 46, 14}, { 31, 13}, { 26, 6}, { 92, 26},
{128, 108}, { 77, 119}, { 54, 84}, { 26, 71}, { 87, 19}, { 95, 155} },
{ {154, 4}, {182, 0}, {159, -8}, {128, -5}, {143, -5}, {187, 55},
{182, 0}, {228, -3}, {187, -7}, {174, -9}, {189, -11}, {169, 79},
{161, -9}, {192, -8}, {187, -9}, {169, -10}, {136, -9}, {184, 40},
{164, -11}, {179, -10}, {174, -10}, {161, -10}, {115, -7}, {197, 20},
{195, -11}, {195, -11}, {146, -10}, {110, -6}, { 95, -4}, {195, 39},
{182, 55}, {172, 77}, {177, 37}, {169, 29}, {172, 52}, { 92, 162} },
{ {174, 80}, {164, 80}, { 95, 80}, { 46, 66}, { 56, 24}, { 36, 193},
{164, 80}, {166, 77}, {105, 76}, { 49, 68}, { 46, 31}, { 49, 186},
{ 97, 78}, {110, 74}, { 72, 72}, { 44, 60}, { 33, 30}, { 69, 131},
{ 61, 61}, { 69, 63}, { 51, 57}, { 31, 48}, { 26, 27}, { 64, 89},
{ 67, 23}, { 51, 32}, { 36, 33}, { 26, 28}, { 20, 12}, { 44, 68},
{ 26, 197}, { 41, 189}, { 61, 129}, { 28, 103}, { 49, 52}, {-12, 245} },
{ {102, 141}, { 79, 166}, { 72, 162}, { 97, 125}, {179, 4}, {307, 0},
{ 72, 168}, { 69, 175}, { 84, 160}, {105, 127}, {148, 34}, {310, 0},
{ 84, 151}, { 82, 161}, { 87, 153}, { 87, 135}, {115, 51}, {317, 0},
{ 97, 125}, {102, 131}, {105, 125}, { 87, 122}, { 84, 64}, { 54, 184},
{166, 18}, {146, 43}, {125, 51}, { 90, 64}, { 95, 7}, { 38, 154},
{294, 0}, { 13, 225}, { 10, 225}, { 67, 168}, { 0, 167}, {161, 94} },
{ {172, 76}, {172, 75}, {136, 80}, { 64, 98}, { 74, 67}, {315, 0},
{169, 76}, {207, 56}, {164, 66}, { 97, 80}, { 67, 72}, {328, 0},
{136, 80}, {187, 53}, {154, 62}, { 72, 85}, { -2, 105}, {305, 0},
{ 74, 91}, {128, 64}, {113, 64}, { 61, 77}, { 41, 75}, {259, 0},
{ 46, 84}, { 51, 81}, { 28, 89}, { 31, 78}, { 23, 77}, {202, 0},
{323, 0}, {323, 0}, {300, 0}, {236, 0}, {195, 0}, {328, 0} },
};
static const int16_t vp5_ract_lc[3][3][5][6][2] = {
{ { { {276, 0}, {238, 0}, {195, 0}, {156, 0}, {113, 0}, {274, 0} },
{ { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1} },
{ {192, 59}, {182, 50}, {141, 48}, {110, 40}, { 92, 19}, {125,128} },
{ {169, 87}, {169, 83}, {184, 62}, {220, 16}, {184, 0}, {264, 0} },
{ {212, 40}, {212, 36}, {169, 49}, {174, 27}, { 8,120}, {182, 71} } },
{ { {259, 10}, {197, 19}, {143, 22}, {123, 16}, {110, 8}, {133, 88} },
{ { 0, 1}, {256, 0}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1} },
{ {207, 46}, {187, 50}, { 97, 83}, { 23,100}, { 41, 56}, { 56,188} },
{ {166, 90}, {146,108}, {161, 88}, {136, 95}, {174, 0}, {266, 0} },
{ {264, 7}, {243, 18}, {184, 43}, {-14,154}, { 20,112}, { 20,199} } },
{ { {230, 26}, {197, 22}, {159, 20}, {146, 12}, {136, 4}, { 54,162} },
{ { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1}, { 0, 1} },
{ {192, 59}, {156, 72}, { 84,101}, { 49,101}, { 79, 47}, { 79,167} },
{ {138,115}, {136,116}, {166, 80}, {238, 0}, {195, 0}, {261, 0} },
{ {225, 33}, {205, 42}, {159, 61}, { 79, 96}, { 92, 66}, { 28,195} } },
}, {
{ { {200, 37}, {197, 18}, {159, 13}, {143, 7}, {102, 5}, {123,126} },
{ {197, 3}, {220, -9}, {210,-12}, {187, -6}, {151, -2}, {174, 80} },
{ {200, 53}, {187, 47}, {159, 40}, {118, 38}, {100, 18}, {141,111} },
{ {179, 78}, {166, 86}, {197, 50}, {207, 27}, {187, 0}, {115,139} },
{ {218, 34}, {220, 29}, {174, 46}, {128, 61}, { 54, 89}, {187, 65} } },
{ { {238, 14}, {197, 18}, {125, 26}, { 90, 25}, { 82, 13}, {161, 86} },
{ {189, 1}, {205, -2}, {156, -4}, {143, -4}, {146, -4}, {172, 72} },
{ {230, 31}, {192, 45}, {102, 76}, { 38, 85}, { 56, 41}, { 64,173} },
{ {166, 91}, {141,111}, {128,116}, {118,109}, {177, 0}, { 23,222} },
{ {253, 14}, {236, 21}, {174, 49}, { 33,118}, { 44, 93}, { 23,187} } },
{ { {218, 28}, {179, 28}, {118, 35}, { 95, 30}, { 72, 24}, {128,108} },
{ {187, 1}, {174, -1}, {125, -1}, {110, -1}, {108, -1}, {202, 52} },
{ {197, 53}, {146, 75}, { 46,118}, { 33,103}, { 64, 50}, {118,126} },
{ {138,114}, {128,122}, {161, 86}, {243, -6}, {195, 0}, { 38,210} },
{ {215, 39}, {179, 58}, { 97,101}, { 95, 85}, { 87, 70}, { 69,152} } },
}, {
{ { {236, 24}, {205, 18}, {172, 12}, {154, 6}, {125, 1}, {169, 75} },
{ {187, 4}, {230, -2}, {228, -4}, {236, -4}, {241, -2}, {192, 66} },
{ {200, 46}, {187, 42}, {159, 34}, {136, 25}, {105, 10}, {179, 62} },
{ {207, 55}, {192, 63}, {192, 54}, {195, 36}, {177, 1}, {143, 98} },
{ {225, 27}, {207, 34}, {200, 30}, {131, 57}, { 97, 60}, {197, 45} } },
{ { {271, 8}, {218, 13}, {133, 19}, { 90, 19}, { 72, 7}, {182, 51} },
{ {179, 1}, {225, -1}, {154, -2}, {110, -1}, { 92, 0}, {195, 41} },
{ {241, 26}, {189, 40}, { 82, 64}, { 33, 60}, { 67, 17}, {120, 94} },
{ {192, 68}, {151, 94}, {146, 90}, {143, 72}, {161, 0}, {113,128} },
{ {256, 12}, {218, 29}, {166, 48}, { 44, 99}, { 31, 87}, {148, 78} } },
{ { {238, 20}, {184, 22}, {113, 27}, { 90, 22}, { 74, 9}, {192, 37} },
{ {184, 0}, {215, -1}, {141, -1}, { 97, 0}, { 49, 0}, {264, 13} },
{ {182, 51}, {138, 61}, { 95, 63}, { 54, 59}, { 64, 25}, {200, 45} },
{ {179, 75}, {156, 87}, {174, 65}, {177, 44}, {174, 0}, {164, 85} },
{ {195, 45}, {148, 65}, {105, 79}, { 95, 72}, { 87, 60}, {169, 63} } },
}
};
static const uint8_t vp5_coord_div[] = { 2, 2, 2, 2, 4, 4 };
#endif /* VP5DATA_H */

512
libavcodec/vp6.c Normal file
View File

@ -0,0 +1,512 @@
/**
* @file vp6.c
* VP6 compatible video decoder
*
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <inttypes.h>
#include "avcodec.h"
#include "dsputil.h"
#include "bitstream.h"
#include "mpegvideo.h"
#include "vp56.h"
#include "vp56data.h"
#include "vp6data.h"
static int vp6_parse_header(vp56_context_t *s, uint8_t *buf, int buf_size,
int *golden_frame)
{
vp56_range_coder_t *c = &s->c;
int parse_filter_info;
int rows, cols;
int res = 1;
if (buf[0] & 1)
return 0;
s->frames[VP56_FRAME_CURRENT].key_frame = !(buf[0] & 0x80);
vp56_init_dequant(s, (buf[0] >> 1) & 0x3F);
if (s->frames[VP56_FRAME_CURRENT].key_frame) {
if ((buf[1] & 0xFE) != 0x46) /* would be 0x36 for VP61 */
return 0;
if (buf[1] & 1) {
av_log(s->avctx, AV_LOG_ERROR, "interlacing not supported\n");
return 0;
}
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);
res = 2;
}
vp56_init_range_decoder(c, buf+6, buf_size-6);
vp56_rac_gets(c, 2);
parse_filter_info = 1;
} else {
vp56_init_range_decoder(c, buf+1, buf_size-1);
*golden_frame = vp56_rac_get(c);
s->deblock_filtering = vp56_rac_get(c);
if (s->deblock_filtering)
vp56_rac_get(c);
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);
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;
}
s->filter_selection = vp56_rac_gets(c, 4);
}
vp56_rac_get(c);
return res;
}
static void vp6_coeff_order_table_init(vp56_context_t *s)
{
int i, pos, idx = 1;
s->coeff_index_to_pos[0] = 0;
for (i=0; i<16; i++)
for (pos=1; pos<64; pos++)
if (s->coeff_reorder[pos] == i)
s->coeff_index_to_pos[idx++] = pos;
}
static void vp6_default_models_init(vp56_context_t *s)
{
s->vector_model_dct[0] = 0xA2;
s->vector_model_dct[1] = 0xA4;
s->vector_model_sig[0] = 0x80;
s->vector_model_sig[1] = 0x80;
memcpy(s->mb_types_stats, vp56_def_mb_types_stats, sizeof(s->mb_types_stats));
memcpy(s->vector_model_fdv, vp6_def_fdv_vector_model, sizeof(s->vector_model_fdv));
memcpy(s->vector_model_pdv, vp6_def_pdv_vector_model, sizeof(s->vector_model_pdv));
memcpy(s->coeff_model_runv, vp6_def_runv_coeff_model, sizeof(s->coeff_model_runv));
memcpy(s->coeff_reorder, vp6_def_coeff_reorder, sizeof(s->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;
int comp, node;
for (comp=0; comp<2; comp++) {
if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][0]))
s->vector_model_dct[comp] = vp56_rac_gets_nn(c, 7);
if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][1]))
s->vector_model_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]))
s->vector_model_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]))
s->vector_model_fdv[comp][node] = vp56_rac_gets_nn(c, 7);
}
static void vp6_parse_coeff_models(vp56_context_t *s)
{
vp56_range_coder_t *c = &s->c;
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);
s->coeff_model_dccv[pt][node] = def_prob[node];
} else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
s->coeff_model_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]))
s->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]))
s->coeff_model_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);
s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
} else if (s->frames[VP56_FRAME_CURRENT].key_frame) {
s->coeff_model_ract[pt][ct][cg][node] = def_prob[node];
}
/* coeff_model_dcct is a linear combination of coeff_model_dccv */
for (pt=0; pt<2; pt++)
for (ctx=0; ctx<3; ctx++)
for (node=0; node<5; node++)
s->coeff_model_dcct[pt][ctx][node] = clip(((s->coeff_model_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 *vector)
{
vp56_range_coder_t *c = &s->c;
int comp;
*vector = (vp56_mv_t) {0,0};
if (s->vector_candidate_pos < 2)
*vector = s->vector_candidate[0];
for (comp=0; comp<2; comp++) {
int i, delta = 0;
if (vp56_rac_get_prob(c, s->vector_model_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, s->vector_model_fdv[comp][j])<<j;
}
if (delta & 0xF0)
delta |= vp56_rac_get_prob(c, s->vector_model_fdv[comp][3])<<3;
else
delta |= 8;
} else {
delta = vp56_rac_get_tree(c, vp56_pva_tree,
s->vector_model_pdv[comp]);
}
if (delta && vp56_rac_get_prob(c, s->vector_model_sig[comp]))
delta = -delta;
if (!comp)
vector->x += delta;
else
vector->y += delta;
}
}
static void vp6_parse_coeff(vp56_context_t *s)
{
vp56_range_coder_t *c = &s->c;
uint8_t *permute = s->scantable.permutated;
uint8_t *model, *model2, *model3;
int coeff, sign, coeff_idx;
int b, i, cg, idx, ctx;
int pt = 0; /* plane type (0 for Y, 1 for U or V) */
for (b=0; b<6; b++) {
int ct = 1; /* code type */
int run = 1;
if (b > 3) pt = 1;
ctx = s->left_block[vp56_b6to4[b]].not_null_dc
+ s->above_blocks[s->above_block_idx[b]].not_null_dc;
model = s->coeff_model_dccv[pt];
model2 = s->coeff_model_dcct[pt][ctx];
for (coeff_idx=0; coeff_idx<64; ) {
if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob(c, model2[0])) {
/* parse a coeff */
if (coeff_idx == 0) {
s->left_block[vp56_b6to4[b]].not_null_dc = 1;
s->above_blocks[s->above_block_idx[b]].not_null_dc = 1;
}
if (vp56_rac_get_prob(c, model2[2])) {
if (vp56_rac_get_prob(c, model2[3])) {
idx = vp56_rac_get_tree(c, vp56_pc_tree, model);
coeff = vp56_coeff_bias[idx];
for (i=vp56_coeff_bit_length[idx]; i>=0; i--)
coeff += vp56_rac_get_prob(c, vp56_coeff_parse_table[idx][i]) << i;
} else {
if (vp56_rac_get_prob(c, model2[4]))
coeff = 3 + vp56_rac_get_prob(c, model[5]);
else
coeff = 2;
}
ct = 2;
} else {
ct = 1;
coeff = 1;
}
sign = vp56_rac_get(c);
coeff = (coeff ^ -sign) + sign;
if (coeff_idx)
coeff *= s->dequant_ac;
idx = s->coeff_index_to_pos[coeff_idx];
s->block_coeff[b][permute[idx]] = coeff;
run = 1;
} else {
/* parse a run */
ct = 0;
if (coeff_idx == 0) {
s->left_block[vp56_b6to4[b]].not_null_dc = 0;
s->above_blocks[s->above_block_idx[b]].not_null_dc = 0;
} else {
if (!vp56_rac_get_prob(c, model2[1]))
break;
model3 = s->coeff_model_runv[coeff_idx >= 6];
run = vp56_rac_get_tree(c, vp6_pcr_tree, model3);
if (!run)
for (run=9, i=0; i<6; i++)
run += vp56_rac_get_prob(c, model3[i+8]) << i;
}
}
cg = vp6_coeff_groups[coeff_idx+=run];
model = model2 = s->coeff_model_ract[pt][ct][cg];
}
}
}
static int vp6_adjust(int v, int t)
{
int V = v, s = v >> 31;
V ^= s;
V -= s;
if (V-t-1 >= (unsigned)(t-1))
return v;
V = 2*t - V;
V += s;
V ^= s;
return V;
}
static int vp6_block_variance(uint8_t *src, int stride)
{
int sum = 0, square_sum = 0;
int y, x;
for (y=0; y<8; y+=2) {
for (x=0; x<8; x+=2) {
sum += src[x];
square_sum += src[x]*src[x];
}
src += 2*stride;
}
return (16*square_sum - sum*sum) / (16*16);
}
static void vp6_filter_hv2(vp56_context_t *s, uint8_t *dst, uint8_t *src,
int stride, int delta, int16_t weight)
{
s->dsp.put_pixels_tab[1][0](dst, src, stride, 8);
s->dsp.biweight_h264_pixels_tab[3](dst, src+delta, stride, 2,
8-weight, weight, 0);
}
static void vp6_filter_hv4(uint8_t *dst, uint8_t *src, int stride,
int delta, const int16_t *weights)
{
int x, y;
for (y=0; y<8; y++) {
for (x=0; x<8; x++) {
dst[x] = clip_uint8(( src[x-delta ] * weights[0]
+ src[x ] * weights[1]
+ src[x+delta ] * weights[2]
+ src[x+2*delta] * weights[3] + 64) >> 7);
}
src += stride;
dst += stride;
}
}
static void vp6_filter_diag2(vp56_context_t *s, uint8_t *dst, uint8_t *src,
int stride, int h_weight, int v_weight)
{
uint8_t *tmp = s->edge_emu_buffer+16;
int x, xmax;
s->dsp.put_pixels_tab[1][0](tmp, src, stride, 8);
s->dsp.biweight_h264_pixels_tab[3](tmp, src+1, stride, 2,
8-h_weight, h_weight, 0);
/* we need a 8x9 block to do vertical filter, so compute one more line */
for (x=8*stride, xmax=x+8; x<xmax; x++)
tmp[x] = (src[x]*(8-h_weight) + src[x+1]*h_weight + 4) >> 3;
s->dsp.put_pixels_tab[1][0](dst, tmp, stride, 8);
s->dsp.biweight_h264_pixels_tab[3](dst, tmp+stride, stride, 2,
8-v_weight, v_weight, 0);
}
static void vp6_filter_diag4(uint8_t *dst, uint8_t *src, int stride,
const int16_t *h_weights,const int16_t *v_weights)
{
int x, y;
int tmp[8*11];
int *t = tmp;
src -= stride;
for (y=0; y<11; y++) {
for (x=0; x<8; x++) {
t[x] = clip_uint8(( src[x-1] * h_weights[0]
+ src[x ] * h_weights[1]
+ src[x+1] * h_weights[2]
+ src[x+2] * h_weights[3] + 64) >> 7);
}
src += stride;
t += 8;
}
t = tmp + 8;
for (y=0; y<8; y++) {
for (x=0; x<8; x++) {
dst[x] = clip_uint8(( t[x-8 ] * v_weights[0]
+ t[x ] * v_weights[1]
+ t[x+8 ] * v_weights[2]
+ t[x+16] * v_weights[3] + 64) >> 7);
}
dst += stride;
t += 8;
}
}
static void vp6_filter(vp56_context_t *s, uint8_t *dst, uint8_t *src,
int offset1, int offset2, int stride,
vp56_mv_t mv, int mask, int select, int luma)
{
int filter4 = 0;
int x8 = mv.x & mask;
int y8 = mv.y & mask;
if (luma) {
x8 *= 2;
y8 *= 2;
filter4 = s->filter_mode;
if (filter4 == 2) {
if (s->max_vector_length &&
(ABS(mv.x) > s->max_vector_length ||
ABS(mv.y) > s->max_vector_length)) {
filter4 = 0;
} else if (!s->sample_variance_threshold
|| (vp6_block_variance(src+offset1, stride)
< s->sample_variance_threshold)) {
filter4 = 0;
}
}
}
if ((y8 && (offset2-offset1)*s->flip<0) || (!y8 && offset1 > offset2)) {
offset1 = offset2;
}
if (filter4) {
if (!y8) { /* left or right combine */
vp6_filter_hv4(dst, src+offset1, stride, 1,
vp6_block_copy_filter[select][x8]);
} else if (!x8) { /* above or below combine */
vp6_filter_hv4(dst, src+offset1, stride, stride,
vp6_block_copy_filter[select][y8]);
} else if ((mv.x^mv.y) >> 31) { /* lower-left or upper-right combine */
vp6_filter_diag4(dst, src+offset1-1, stride,
vp6_block_copy_filter[select][x8],
vp6_block_copy_filter[select][y8]);
} else { /* lower-right or upper-left combine */
vp6_filter_diag4(dst, src+offset1, stride,
vp6_block_copy_filter[select][x8],
vp6_block_copy_filter[select][y8]);
}
} else {
if (!y8) { /* left or right combine */
vp6_filter_hv2(s, dst, src+offset1, stride, 1, x8);
} else if (!x8) { /* above or below combine */
vp6_filter_hv2(s, dst, src+offset1, stride, stride, y8);
} else if ((mv.x^mv.y) >> 31) { /* lower-left or upper-right combine */
vp6_filter_diag2(s, dst, src+offset1-1, stride, x8, y8);
} else { /* lower-right or upper-left combine */
vp6_filter_diag2(s, dst, src+offset1, stride, x8, y8);
}
}
}
static int vp6_decode_init(AVCodecContext *avctx)
{
vp56_context_t *s = avctx->priv_data;
vp56_init(s, avctx, avctx->codec->id == CODEC_ID_VP6);
s->vp56_coord_div = vp6_coord_div;
s->parse_vector_adjustment = vp6_parse_vector_adjustment;
s->adjust = vp6_adjust;
s->filter = vp6_filter;
s->parse_coeff = vp6_parse_coeff;
s->default_models_init = vp6_default_models_init;
s->parse_vector_models = vp6_parse_vector_models;
s->parse_coeff_models = vp6_parse_coeff_models;
s->parse_header = vp6_parse_header;
return 0;
}
AVCodec vp6_decoder = {
"vp6",
CODEC_TYPE_VIDEO,
CODEC_ID_VP6,
sizeof(vp56_context_t),
vp6_decode_init,
NULL,
vp56_free,
vp56_decode_frame,
};
/* flash version, not flipped upside-down */
AVCodec vp6f_decoder = {
"vp6f",
CODEC_TYPE_VIDEO,
CODEC_ID_VP6F,
sizeof(vp56_context_t),
vp6_decode_init,
NULL,
vp56_free,
vp56_decode_frame,
};

291
libavcodec/vp6data.h Normal file
View File

@ -0,0 +1,291 @@
/**
* @file vp6data.h
* VP6 compatible video decoder
*
* Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef VP6DATA_H
#define VP6DATA_H
#include <inttypes.h>
#include "vp56data.h"
static const uint8_t vp6_def_fdv_vector_model[2][8] = {
{ 247, 210, 135, 68, 138, 220, 239, 246 },
{ 244, 184, 201, 44, 173, 221, 239, 253 },
};
static const uint8_t vp6_def_pdv_vector_model[2][7] = {
{ 225, 146, 172, 147, 214, 39, 156 },
{ 204, 170, 119, 235, 140, 230, 228 },
};
static const uint8_t vp6_def_coeff_reorder[] = {
0, 0, 1, 1, 1, 2, 2, 2,
2, 2, 2, 3, 3, 4, 4, 4,
5, 5, 5, 5, 6, 6, 7, 7,
7, 7, 7, 8, 8, 9, 9, 9,
9, 9, 9, 10, 10, 11, 11, 11,
11, 11, 11, 12, 12, 12, 12, 12,
12, 13, 13, 13, 13, 13, 14, 14,
14, 14, 15, 15, 15, 15, 15, 15,
};
static const uint8_t vp6_def_runv_coeff_model[2][14] = {
{ 198, 197, 196, 146, 198, 204, 169, 142, 130, 136, 149, 149, 191, 249 },
{ 135, 201, 181, 154, 98, 117, 132, 126, 146, 169, 184, 240, 246, 254 },
};
static const uint8_t vp6_sig_dct_pct[2][2] = {
{ 237, 246 },
{ 231, 243 },
};
static const uint8_t vp6_pdv_pct[2][7] = {
{ 253, 253, 254, 254, 254, 254, 254 },
{ 245, 253, 254, 254, 254, 254, 254 },
};
static const uint8_t vp6_fdv_pct[2][8] = {
{ 254, 254, 254, 254, 254, 250, 250, 252 },
{ 254, 254, 254, 254, 254, 251, 251, 254 },
};
static const uint8_t vp6_dccv_pct[2][11] = {
{ 146, 255, 181, 207, 232, 243, 238, 251, 244, 250, 249 },
{ 179, 255, 214, 240, 250, 255, 244, 255, 255, 255, 255 },
};
static const uint8_t vp6_coeff_reorder_pct[] = {
255, 132, 132, 159, 153, 151, 161, 170,
164, 162, 136, 110, 103, 114, 129, 118,
124, 125, 132, 136, 114, 110, 142, 135,
134, 123, 143, 126, 153, 183, 166, 161,
171, 180, 179, 164, 203, 218, 225, 217,
215, 206, 203, 217, 229, 241, 248, 243,
253, 255, 253, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
};
static const uint8_t vp6_runv_pct[2][14] = {
{ 219, 246, 238, 249, 232, 239, 249, 255, 248, 253, 239, 244, 241, 248 },
{ 198, 232, 251, 253, 219, 241, 253, 255, 248, 249, 244, 238, 251, 255 },
};
static const uint8_t vp6_ract_pct[3][2][6][11] = {
{ { { 227, 246, 230, 247, 244, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 209, 231, 231, 249, 249, 253, 255, 255, 255 },
{ 255, 255, 225, 242, 241, 251, 253, 255, 255, 255, 255 },
{ 255, 255, 241, 253, 252, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } },
{ { 240, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 240, 253, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } } },
{ { { 206, 203, 227, 239, 247, 255, 253, 255, 255, 255, 255 },
{ 207, 199, 220, 236, 243, 252, 252, 255, 255, 255, 255 },
{ 212, 219, 230, 243, 244, 253, 252, 255, 255, 255, 255 },
{ 236, 237, 247, 252, 253, 255, 255, 255, 255, 255, 255 },
{ 240, 240, 248, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } },
{ { 230, 233, 249, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 238, 238, 250, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 248, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } } },
{ { { 225, 239, 227, 231, 244, 253, 243, 255, 255, 253, 255 },
{ 232, 234, 224, 228, 242, 249, 242, 252, 251, 251, 255 },
{ 235, 249, 238, 240, 251, 255, 249, 255, 253, 253, 255 },
{ 249, 253, 251, 250, 255, 255, 255, 255, 255, 255, 255 },
{ 251, 250, 249, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } },
{ { 243, 244, 250, 250, 255, 255, 255, 255, 255, 255, 255 },
{ 249, 248, 250, 253, 255, 255, 255, 255, 255, 255, 255 },
{ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } } }
};
static const int vp6_dccv_lc[3][5][2] = {
{ { 122, 133 }, { 0, 1 }, { 78, 171 }, { 139, 117 }, { 168, 79 } },
{ { 133, 51 }, { 0, 1 }, { 169, 71 }, { 214, 44 }, { 210, 38 } },
{ { 142, -16 }, { 0, 1 }, { 221, -30 }, { 246, -3 }, { 203, 17 } },
};
static const uint8_t vp6_coeff_groups[] = {
0, 0, 1, 1, 1, 2, 2, 2,
2, 2, 2, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
};
static const int16_t vp6_block_copy_filter[16][8][4] = {
{ { 0, 128, 0, 0 }, /* 0 */
{ -3, 122, 9, 0 },
{ -4, 109, 24, -1 },
{ -5, 91, 45, -3 },
{ -4, 68, 68, -4 },
{ -3, 45, 91, -5 },
{ -1, 24, 109, -4 },
{ 0, 9, 122, -3 } },
{ { 0, 128, 0, 0 }, /* 1 */
{ -4, 124, 9, -1 },
{ -5, 110, 25, -2 },
{ -6, 91, 46, -3 },
{ -5, 69, 69, -5 },
{ -3, 46, 91, -6 },
{ -2, 25, 110, -5 },
{ -1, 9, 124, -4 } },
{ { 0, 128, 0, 0 }, /* 2 */
{ -4, 123, 10, -1 },
{ -6, 110, 26, -2 },
{ -7, 92, 47, -4 },
{ -6, 70, 70, -6 },
{ -4, 47, 92, -7 },
{ -2, 26, 110, -6 },
{ -1, 10, 123, -4 } },
{ { 0, 128, 0, 0 }, /* 3 */
{ -5, 124, 10, -1 },
{ -7, 110, 27, -2 },
{ -7, 91, 48, -4 },
{ -6, 70, 70, -6 },
{ -4, 48, 92, -8 },
{ -2, 27, 110, -7 },
{ -1, 10, 124, -5 } },
{ { 0, 128, 0, 0 }, /* 4 */
{ -6, 124, 11, -1 },
{ -8, 111, 28, -3 },
{ -8, 92, 49, -5 },
{ -7, 71, 71, -7 },
{ -5, 49, 92, -8 },
{ -3, 28, 111, -8 },
{ -1, 11, 124, -6 } },
{ { 0, 128, 0, 0 }, /* 5 */
{ -6, 123, 12, -1 },
{ -9, 111, 29, -3 },
{ -9, 93, 50, -6 },
{ -8, 72, 72, -8 },
{ -6, 50, 93, -9 },
{ -3, 29, 111, -9 },
{ -1, 12, 123, -6 } },
{ { 0, 128, 0, 0 }, /* 6 */
{ -7, 124, 12, -1 },
{ -10, 111, 30, -3 },
{ -10, 93, 51, -6 },
{ -9, 73, 73, -9 },
{ -6, 51, 93, -10 },
{ -3, 30, 111, -10 },
{ -1, 12, 124, -7 } },
{ { 0, 128, 0, 0 }, /* 7 */
{ -7, 123, 13, -1 },
{ -11, 112, 31, -4 },
{ -11, 94, 52, -7 },
{ -10, 74, 74, -10 },
{ -7, 52, 94, -11 },
{ -4, 31, 112, -11 },
{ -1, 13, 123, -7 } },
{ { 0, 128, 0, 0 }, /* 8 */
{ -8, 124, 13, -1 },
{ -12, 112, 32, -4 },
{ -12, 94, 53, -7 },
{ -10, 74, 74, -10 },
{ -7, 53, 94, -12 },
{ -4, 32, 112, -12 },
{ -1, 13, 124, -8 } },
{ { 0, 128, 0, 0 }, /* 9 */
{ -9, 124, 14, -1 },
{ -13, 112, 33, -4 },
{ -13, 95, 54, -8 },
{ -11, 75, 75, -11 },
{ -8, 54, 95, -13 },
{ -4, 33, 112, -13 },
{ -1, 14, 124, -9 } },
{ { 0, 128, 0, 0 }, /* 10 */
{ -9, 123, 15, -1 },
{ -14, 113, 34, -5 },
{ -14, 95, 55, -8 },
{ -12, 76, 76, -12 },
{ -8, 55, 95, -14 },
{ -5, 34, 112, -13 },
{ -1, 15, 123, -9 } },
{ { 0, 128, 0, 0 }, /* 11 */
{ -10, 124, 15, -1 },
{ -14, 113, 34, -5 },
{ -15, 96, 56, -9 },
{ -13, 77, 77, -13 },
{ -9, 56, 96, -15 },
{ -5, 34, 113, -14 },
{ -1, 15, 124, -10 } },
{ { 0, 128, 0, 0 }, /* 12 */
{ -10, 123, 16, -1 },
{ -15, 113, 35, -5 },
{ -16, 98, 56, -10 },
{ -14, 78, 78, -14 },
{ -10, 56, 98, -16 },
{ -5, 35, 113, -15 },
{ -1, 16, 123, -10 } },
{ { 0, 128, 0, 0 }, /* 13 */
{ -11, 124, 17, -2 },
{ -16, 113, 36, -5 },
{ -17, 98, 57, -10 },
{ -14, 78, 78, -14 },
{ -10, 57, 98, -17 },
{ -5, 36, 113, -16 },
{ -2, 17, 124, -11 } },
{ { 0, 128, 0, 0 }, /* 14 */
{ -12, 125, 17, -2 },
{ -17, 114, 37, -6 },
{ -18, 99, 58, -11 },
{ -15, 79, 79, -15 },
{ -11, 58, 99, -18 },
{ -6, 37, 114, -17 },
{ -2, 17, 125, -12 } },
{ { 0, 128, 0, 0 }, /* 15 */
{ -12, 124, 18, -2 },
{ -18, 114, 38, -6 },
{ -19, 99, 59, -11 },
{ -16, 80, 80, -16 },
{ -11, 59, 99, -19 },
{ -6, 38, 114, -18 },
{ -2, 18, 124, -12 } },
};
const vp56_tree_t vp6_pcr_tree[] = {
{ 8, 0},
{ 4, 1},
{ 2, 2}, {-1}, {-2},
{ 2, 3}, {-3}, {-4},
{ 8, 4},
{ 4, 5},
{ 2, 6}, {-5}, {-6},
{ 2, 7}, {-7}, {-8},
{-0},
};
static const uint8_t vp6_coord_div[] = { 4, 4, 4, 4, 8, 8 };
#endif /* VP6DATA_H */

View File

@ -184,6 +184,11 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
switch(flags & 0xF){
case 2: st->codec->codec_id = CODEC_ID_FLV1; break;
case 3: st->codec->codec_id = CODEC_ID_FLASHSV; break;
case 4:
st->codec->codec_id = CODEC_ID_VP6F;
get_byte(&s->pb); /* width and height adjustment */
size--;
break;
default:
av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flags & 0xf);
st->codec->codec_tag= flags & 0xF;

View File

@ -182,15 +182,15 @@ static const CodecTag nsv_codec_video_tags[] = {
{ CODEC_ID_VP3, MKTAG('V', 'P', '3', ' ') },
{ CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
{ CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
{ CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
{ CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
{ CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
/*
{ CODEC_ID_VP4, MKTAG('V', 'P', '4', ' ') },
{ CODEC_ID_VP4, MKTAG('V', 'P', '4', '0') },
{ CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
{ CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
{ CODEC_ID_VP6, MKTAG('V', 'P', '6', ' ') },
{ CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
{ CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
{ CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
*/
{ CODEC_ID_XVID, MKTAG('X', 'V', 'I', 'D') }, /* cf sample xvid decoder from nsv_codec_sdk.zip */
{ CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },

View File

@ -114,6 +114,8 @@ const CodecTag codec_bmp_tags[] = {
{ CODEC_ID_INDEO3, MKTAG('I', 'V', '3', '2') },
{ CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
{ CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
{ CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
{ CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
{ CODEC_ID_ASV1, MKTAG('A', 'S', 'V', '1') },
{ CODEC_ID_ASV2, MKTAG('A', 'S', 'V', '2') },
{ CODEC_ID_VCR1, MKTAG('V', 'C', 'R', '1') },

View File

@ -19,6 +19,7 @@
*/
#include "avformat.h"
#include "bitstream.h"
#include "riff.h" /* for CodecTag */
/* should have a generic way to indicate probable size */
#define DUMMY_FILE_SIZE (100 * 1024 * 1024)
@ -45,8 +46,6 @@
#define FLAG_SETFILL0 0x02
#define FLAG_SETFILL1 0x04
#define SWF_VIDEO_CODEC_FLV1 0x02
#define AUDIO_FIFO_SIZE 65536
/* character id used */
@ -80,6 +79,12 @@ typedef struct {
int audio_type;
} SWFContext;
static const CodecTag swf_codec_tags[] = {
{CODEC_ID_FLV1, 0x02},
{CODEC_ID_VP6F, 0x04},
{0, 0},
};
static const int sSampleRates[3][4] = {
{44100, 48000, 32000, 0},
{22050, 24000, 16000, 0},
@ -328,10 +333,12 @@ static int swf_write_header(AVFormatContext *s)
if (enc->codec_type == CODEC_TYPE_AUDIO)
audio_enc = enc;
else {
if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {
if ( enc->codec_id == CODEC_ID_VP6F ||
enc->codec_id == CODEC_ID_FLV1 ||
enc->codec_id == CODEC_ID_MJPEG ) {
video_enc = enc;
} else {
av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");
av_log(enc, AV_LOG_ERROR, "SWF only supports VP6, FLV1 and MJPEG\n");
return -1;
}
}
@ -361,7 +368,9 @@ static int swf_write_header(AVFormatContext *s)
}
put_tag(pb, "FWS");
if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
if ( video_enc && video_enc->codec_id == CODEC_ID_VP6F ) {
put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */
} else if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */
} else {
put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */
@ -375,7 +384,8 @@ static int swf_write_header(AVFormatContext *s)
put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */
/* define a shape with the jpeg inside */
if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {
if ( video_enc && (video_enc->codec_id == CODEC_ID_VP6F ||
video_enc->codec_id == CODEC_ID_FLV1 )) {
} else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {
put_swf_tag(s, TAG_DEFINESHAPE);
@ -512,7 +522,8 @@ retry_swf_audio_packet:
}
}
if ( swf->video_type == CODEC_ID_FLV1 ) {
if ( swf->video_type == CODEC_ID_VP6F ||
swf->video_type == CODEC_ID_FLV1 ) {
if ( swf->video_frame_number == 0 ) {
/* create a new video object */
put_swf_tag(s, TAG_VIDEOSTREAM);
@ -521,7 +532,7 @@ retry_swf_audio_packet:
put_le16(pb, enc->width);
put_le16(pb, enc->height);
put_byte(pb, 0);
put_byte(pb, SWF_VIDEO_CODEC_FLV1);
put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type));
put_swf_end_tag(s);
/* place the video object for the first time */
@ -784,18 +795,20 @@ static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)
return AVERROR_IO;
}
if ( tag == TAG_VIDEOSTREAM && !vst) {
int codec_id;
swf->ch_id = get_le16(pb);
get_le16(pb);
get_le16(pb);
get_le16(pb);
get_byte(pb);
/* Check for FLV1 */
if ( get_byte(pb) == SWF_VIDEO_CODEC_FLV1 ) {
codec_id = codec_get_id(swf_codec_tags, get_byte(pb));
if ( codec_id ) {
vst = av_new_stream(s, 0);
av_set_pts_info(vst, 24, 1, 1000); /* 24 bit pts in ms */
vst->codec->codec_type = CODEC_TYPE_VIDEO;
vst->codec->codec_id = CODEC_ID_FLV1;
vst->codec->codec_id = codec_id;
if ( swf->samples_per_frame ) {
vst->codec->time_base.den = 1000. / swf->ms_per_frame;
vst->codec->time_base.num = 1;