mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
add support for VP6 with huffman encoded blocks
closes issue 104 Originally committed as revision 10737 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
437c2079b7
commit
f28b10483a
@ -195,9 +195,9 @@ OBJS-$(CONFIG_VORBIS_DECODER) += vorbis_dec.o vorbis.o vorbis_data.o xi
|
||||
OBJS-$(CONFIG_VORBIS_ENCODER) += vorbis_enc.o vorbis.o vorbis_data.o mdct.o fft.o
|
||||
OBJS-$(CONFIG_VP3_DECODER) += vp3.o vp3dsp.o
|
||||
OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp3dsp.o
|
||||
OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o vp3dsp.o
|
||||
OBJS-$(CONFIG_VP6A_DECODER) += vp6.o vp56.o vp56data.o vp3dsp.o
|
||||
OBJS-$(CONFIG_VP6F_DECODER) += vp6.o vp56.o vp56data.o vp3dsp.o
|
||||
OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o vp3dsp.o huffman.o
|
||||
OBJS-$(CONFIG_VP6A_DECODER) += vp6.o vp56.o vp56data.o vp3dsp.o huffman.o
|
||||
OBJS-$(CONFIG_VP6F_DECODER) += vp6.o vp56.o vp56data.o vp3dsp.o huffman.o
|
||||
OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
|
||||
OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o
|
||||
OBJS-$(CONFIG_WMAV1_DECODER) += wmadec.o wma.o mdct.o fft.o
|
||||
|
@ -205,7 +205,7 @@ static void vp5_parse_coeff(vp56_context_t *s)
|
||||
s->coeff_ctx[vp56_b6to4[b]][coeff_idx] = 4;
|
||||
idx = vp56_rac_get_tree(c, vp56_pc_tree, model1);
|
||||
sign = vp56_rac_get(c);
|
||||
coeff = vp56_coeff_bias[idx];
|
||||
coeff = vp56_coeff_bias[idx+5];
|
||||
for (i=vp56_coeff_bit_length[idx]; i>=0; i--)
|
||||
coeff += vp56_rac_get_prob(c, vp56_coeff_parse_table[idx][i]) << i;
|
||||
} else {
|
||||
|
@ -157,6 +157,14 @@ struct vp56_context {
|
||||
|
||||
vp56_model_t *modelp;
|
||||
vp56_model_t models[2];
|
||||
|
||||
/* huffman decoding */
|
||||
int use_huffman;
|
||||
GetBitContext gb;
|
||||
VLC dccv_vlc[2];
|
||||
VLC runv_vlc[2];
|
||||
VLC ract_vlc[2][3][6];
|
||||
unsigned int nb_null[2][2]; /* number of consecutive NULL DC/AC */
|
||||
};
|
||||
|
||||
|
||||
|
@ -62,5 +62,5 @@ const vp56_tree_t vp56_pc_tree[] = {
|
||||
{ 2,10}, {-4}, {-5},
|
||||
};
|
||||
|
||||
const uint8_t vp56_coeff_bias[] = { 5, 7, 11, 19, 35, 67 };
|
||||
const uint8_t vp56_coeff_bias[] = { 0, 1, 2, 3, 4, 5, 7, 11, 19, 35, 67 };
|
||||
const uint8_t vp56_coeff_bit_length[] = { 0, 1, 2, 3, 4, 10 };
|
||||
|
135
libavcodec/vp6.c
135
libavcodec/vp6.c
@ -30,6 +30,7 @@
|
||||
#include "avcodec.h"
|
||||
#include "dsputil.h"
|
||||
#include "bitstream.h"
|
||||
#include "huffman.h"
|
||||
#include "mpegvideo.h"
|
||||
|
||||
#include "vp56.h"
|
||||
@ -37,6 +38,9 @@
|
||||
#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, uint8_t *buf, int buf_size,
|
||||
int *golden_frame)
|
||||
{
|
||||
@ -126,14 +130,19 @@ static int vp6_parse_header(vp56_context_t *s, uint8_t *buf, int buf_size,
|
||||
s->filter_selection = 16;
|
||||
}
|
||||
|
||||
if (vp56_rac_get(c))
|
||||
av_log(s->avctx, AV_LOG_WARNING,
|
||||
"alternative entropy decoding not supported\n");
|
||||
s->use_huffman = vp56_rac_get(c);
|
||||
|
||||
s->parse_coeff = vp6_parse_coeff;
|
||||
if (coeff_offset) {
|
||||
vp56_init_range_decoder(&s->cc, buf+coeff_offset,
|
||||
buf_size-coeff_offset);
|
||||
s->ccp = &s->cc;
|
||||
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);
|
||||
} else {
|
||||
vp56_init_range_decoder(&s->cc, buf, buf_size);
|
||||
s->ccp = &s->cc;
|
||||
}
|
||||
} else {
|
||||
s->ccp = &s->c;
|
||||
}
|
||||
@ -194,6 +203,31 @@ static void vp6_parse_vector_models(vp56_context_t *s)
|
||||
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;
|
||||
@ -237,11 +271,26 @@ static void vp6_parse_coeff_models(vp56_context_t *s)
|
||||
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)
|
||||
@ -282,6 +331,77 @@ static void vp6_parse_vector_adjustment(vp56_context_t *s, vp56_mv_t *vect)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read number of consecutive blocks with null DC or AC.
|
||||
* This value is < 74.
|
||||
*/
|
||||
static unsigned vp6_get_nb_null(vp56_context_t *s)
|
||||
{
|
||||
unsigned val = get_bits(&s->gb, 2);
|
||||
if (val == 2)
|
||||
val += get_bits(&s->gb, 2);
|
||||
else if (val == 3) {
|
||||
val = get_bits1(&s->gb) << 2;
|
||||
val = 6+val + get_bits(&s->gb, 2+val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void vp6_parse_coeff_huffman(vp56_context_t *s)
|
||||
{
|
||||
vp56_model_t *model = s->modelp;
|
||||
uint8_t *permute = s->scantable.permutated;
|
||||
VLC *vlc_coeff;
|
||||
int coeff, sign, coeff_idx;
|
||||
int b, cg, idx;
|
||||
int pt = 0; /* plane type (0 for Y, 1 for U or V) */
|
||||
|
||||
for (b=0; b<6; b++) {
|
||||
int ct = 0; /* code type */
|
||||
if (b > 3) pt = 1;
|
||||
vlc_coeff = &s->dccv_vlc[pt];
|
||||
|
||||
for (coeff_idx=0; coeff_idx<64; ) {
|
||||
int run = 1;
|
||||
if (coeff_idx<2 && s->nb_null[coeff_idx][pt]) {
|
||||
s->nb_null[coeff_idx][pt]--;
|
||||
if (coeff_idx)
|
||||
break;
|
||||
} else {
|
||||
coeff = get_vlc2(&s->gb, vlc_coeff->table, 9, 3);
|
||||
if (coeff == 0) {
|
||||
if (coeff_idx) {
|
||||
int pt = (coeff_idx >= 6);
|
||||
run += get_vlc2(&s->gb, s->runv_vlc[pt].table, 9, 3);
|
||||
if (run >= 9)
|
||||
run += get_bits(&s->gb, 6);
|
||||
} else
|
||||
s->nb_null[0][pt] = vp6_get_nb_null(s);
|
||||
ct = 0;
|
||||
} else if (coeff == 11) { /* end of block */
|
||||
if (coeff_idx == 1) /* first AC coeff ? */
|
||||
s->nb_null[1][pt] = vp6_get_nb_null(s);
|
||||
break;
|
||||
} else {
|
||||
int coeff2 = vp56_coeff_bias[coeff];
|
||||
if (coeff > 4)
|
||||
coeff2 += get_bits(&s->gb, coeff <= 9 ? coeff - 4 : 11);
|
||||
ct = 1 + (coeff2 > 1);
|
||||
sign = get_bits1(&s->gb);
|
||||
coeff2 = (coeff2 ^ -sign) + sign;
|
||||
if (coeff_idx)
|
||||
coeff2 *= s->dequant_ac;
|
||||
idx = model->coeff_index_to_pos[coeff_idx];
|
||||
s->block_coeff[b][permute[idx]] = coeff2;
|
||||
}
|
||||
}
|
||||
coeff_idx+=run;
|
||||
cg = FFMIN(vp6_coeff_groups[coeff_idx], 3);
|
||||
vlc_coeff = &s->ract_vlc[pt][ct][cg];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void vp6_parse_coeff(vp56_context_t *s)
|
||||
{
|
||||
vp56_range_coder_t *c = s->ccp;
|
||||
@ -309,7 +429,7 @@ static void vp6_parse_coeff(vp56_context_t *s)
|
||||
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, model1);
|
||||
coeff = vp56_coeff_bias[idx];
|
||||
coeff = vp56_coeff_bias[idx+5];
|
||||
for (i=vp56_coeff_bit_length[idx]; i>=0; i--)
|
||||
coeff += vp56_rac_get_prob(c, vp56_coeff_parse_table[idx][i]) << i;
|
||||
} else {
|
||||
@ -500,7 +620,6 @@ static int vp6_decode_init(AVCodecContext *avctx)
|
||||
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;
|
||||
|
@ -297,4 +297,12 @@ static const vp56_tree_t vp6_pcr_tree[] = {
|
||||
|
||||
static const uint8_t vp6_coord_div[] = { 4, 4, 4, 4, 8, 8 };
|
||||
|
||||
static const uint8_t vp6_huff_coeff_map[] = {
|
||||
13, 14, 11, 0, 1, 15, 16, 18, 2, 17, 3, 4, 19, 20, 5, 6, 21, 22, 7, 8, 9, 10
|
||||
};
|
||||
|
||||
static const uint8_t vp6_huff_run_map[] = {
|
||||
10, 13, 11, 12, 0, 1, 2, 3, 14, 8, 15, 16, 4, 5, 6, 7
|
||||
};
|
||||
|
||||
#endif /* VP6DATA_H */
|
||||
|
Loading…
Reference in New Issue
Block a user