*/
/**
- * @file vp3.c
+ * @file libavcodec/vp3.c
* On2 VP3 Video Decoder
*
* VP3 Video Decoder by Mike Melanson (mike at multimedia.cx)
#include "avcodec.h"
#include "dsputil.h"
-#include "bitstream.h"
+#include "get_bits.h"
#include "vp3data.h"
#include "xiph.h"
int last_quality_index;
int superblock_count;
- int superblock_width;
- int superblock_height;
int y_superblock_width;
int y_superblock_height;
int c_superblock_width;
uint16_t huffman_table[80][32][2];
uint8_t filter_limit_values[64];
- int bounding_values_array[256];
+ DECLARE_ALIGNED_8(int, bounding_values_array[256+2]);
} Vp3DecodeContext;
/************************************************************************
int right_edge = 0;
int bottom_edge = 0;
int superblock_row_inc = 0;
- int *hilbert = NULL;
int mapping_index = 0;
int current_macroblock;
current_height = 0;
superblock_row_inc = s->macroblock_width -
(s->y_superblock_width * 2 - s->macroblock_width);
- hilbert = hilbert_walk_mb;
mapping_index = 0;
current_macroblock = -1;
for (i = 0; i < s->u_superblock_start; i++) {
bounding_values[x] = x;
bounding_values[x + filter_limit] = filter_limit - x;
}
+ bounding_values[129] = bounding_values[130] = filter_limit * 0x02020202;
}
/*
/* is it a custom coding scheme? */
if (scheme == 0) {
+ for (i = 0; i < 8; i++)
+ custom_mode_alphabet[i] = MODE_INTER_NO_MV;
for (i = 0; i < 8; i++)
custom_mode_alphabet[get_bits(gb, 3)] = i;
}
if (s->keyframe)
return 0;
- memset(motion_x, 0, 6 * sizeof(int));
- memset(motion_y, 0, 6 * sizeof(int));
+ memset(motion_x, 0, 6 * sizeof(int));
+ memset(motion_y, 0, 6 * sizeof(int));
- /* coding mode 0 is the VLC scheme; 1 is the fixed code scheme */
- coding_mode = get_bits1(gb);
+ /* coding mode 0 is the VLC scheme; 1 is the fixed code scheme */
+ coding_mode = get_bits1(gb);
- /* iterate through all of the macroblocks that contain 1 or more
- * coded fragments */
- for (i = 0; i < s->u_superblock_start; i++) {
+ /* iterate through all of the macroblocks that contain 1 or more
+ * coded fragments */
+ for (i = 0; i < s->u_superblock_start; i++) {
- for (j = 0; j < 4; j++) {
- current_macroblock = s->superblock_macroblocks[i * 4 + j];
- if ((current_macroblock == -1) ||
- (s->macroblock_coding[current_macroblock] == MODE_COPY))
- continue;
- if (current_macroblock >= s->macroblock_count) {
- av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad macroblock number (%d >= %d)\n",
- current_macroblock, s->macroblock_count);
- return 1;
- }
+ for (j = 0; j < 4; j++) {
+ current_macroblock = s->superblock_macroblocks[i * 4 + j];
+ if ((current_macroblock == -1) ||
+ (s->macroblock_coding[current_macroblock] == MODE_COPY))
+ continue;
+ if (current_macroblock >= s->macroblock_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad macroblock number (%d >= %d)\n",
+ current_macroblock, s->macroblock_count);
+ return 1;
+ }
- current_fragment = s->macroblock_fragments[current_macroblock * 6];
- if (current_fragment >= s->fragment_count) {
- av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad fragment number (%d >= %d\n",
- current_fragment, s->fragment_count);
- return 1;
+ current_fragment = s->macroblock_fragments[current_macroblock * 6];
+ if (current_fragment >= s->fragment_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad fragment number (%d >= %d\n",
+ current_fragment, s->fragment_count);
+ return 1;
+ }
+ switch (s->macroblock_coding[current_macroblock]) {
+
+ case MODE_INTER_PLUS_MV:
+ case MODE_GOLDEN_MV:
+ /* all 6 fragments use the same motion vector */
+ if (coding_mode == 0) {
+ motion_x[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
+ motion_y[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
+ } else {
+ motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)];
+ motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)];
}
- switch (s->macroblock_coding[current_macroblock]) {
-
- case MODE_INTER_PLUS_MV:
- case MODE_GOLDEN_MV:
- /* all 6 fragments use the same motion vector */
- if (coding_mode == 0) {
- motion_x[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
- motion_y[0] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
- } else {
- motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)];
- motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)];
- }
- for (k = 1; k < 6; k++) {
- motion_x[k] = motion_x[0];
- motion_y[k] = motion_y[0];
- }
-
- /* vector maintenance, only on MODE_INTER_PLUS_MV */
- if (s->macroblock_coding[current_macroblock] ==
- MODE_INTER_PLUS_MV) {
- prior_last_motion_x = last_motion_x;
- prior_last_motion_y = last_motion_y;
- last_motion_x = motion_x[0];
- last_motion_y = motion_y[0];
- }
- break;
+ for (k = 1; k < 6; k++) {
+ motion_x[k] = motion_x[0];
+ motion_y[k] = motion_y[0];
+ }
- case MODE_INTER_FOURMV:
- /* vector maintenance */
+ /* vector maintenance, only on MODE_INTER_PLUS_MV */
+ if (s->macroblock_coding[current_macroblock] ==
+ MODE_INTER_PLUS_MV) {
prior_last_motion_x = last_motion_x;
prior_last_motion_y = last_motion_y;
+ last_motion_x = motion_x[0];
+ last_motion_y = motion_y[0];
+ }
+ break;
- /* fetch 4 vectors from the bitstream, one for each
- * Y fragment, then average for the C fragment vectors */
- motion_x[4] = motion_y[4] = 0;
- for (k = 0; k < 4; k++) {
- for (l = 0; l < s->coded_fragment_list_index; l++)
- if (s->coded_fragment_list[l] == s->macroblock_fragments[6*current_macroblock + k])
- break;
- if (l < s->coded_fragment_list_index) {
- if (coding_mode == 0) {
- motion_x[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
- motion_y[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
- } else {
- motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)];
- motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)];
- }
- last_motion_x = motion_x[k];
- last_motion_y = motion_y[k];
+ case MODE_INTER_FOURMV:
+ /* vector maintenance */
+ prior_last_motion_x = last_motion_x;
+ prior_last_motion_y = last_motion_y;
+
+ /* fetch 4 vectors from the bitstream, one for each
+ * Y fragment, then average for the C fragment vectors */
+ motion_x[4] = motion_y[4] = 0;
+ for (k = 0; k < 4; k++) {
+ for (l = 0; l < s->coded_fragment_list_index; l++)
+ if (s->coded_fragment_list[l] == s->macroblock_fragments[6*current_macroblock + k])
+ break;
+ if (l < s->coded_fragment_list_index) {
+ if (coding_mode == 0) {
+ motion_x[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
+ motion_y[k] = motion_vector_table[get_vlc2(gb, s->motion_vector_vlc.table, 6, 2)];
} else {
- motion_x[k] = 0;
- motion_y[k] = 0;
+ motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)];
+ motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)];
}
- motion_x[4] += motion_x[k];
- motion_y[4] += motion_y[k];
+ last_motion_x = motion_x[k];
+ last_motion_y = motion_y[k];
+ } else {
+ motion_x[k] = 0;
+ motion_y[k] = 0;
}
+ motion_x[4] += motion_x[k];
+ motion_y[4] += motion_y[k];
+ }
- motion_x[5]=
- motion_x[4]= RSHIFT(motion_x[4], 2);
- motion_y[5]=
- motion_y[4]= RSHIFT(motion_y[4], 2);
- break;
+ motion_x[5]=
+ motion_x[4]= RSHIFT(motion_x[4], 2);
+ motion_y[5]=
+ motion_y[4]= RSHIFT(motion_y[4], 2);
+ break;
- case MODE_INTER_LAST_MV:
- /* all 6 fragments use the last motion vector */
- motion_x[0] = last_motion_x;
- motion_y[0] = last_motion_y;
- for (k = 1; k < 6; k++) {
- motion_x[k] = motion_x[0];
- motion_y[k] = motion_y[0];
- }
+ case MODE_INTER_LAST_MV:
+ /* all 6 fragments use the last motion vector */
+ motion_x[0] = last_motion_x;
+ motion_y[0] = last_motion_y;
+ for (k = 1; k < 6; k++) {
+ motion_x[k] = motion_x[0];
+ motion_y[k] = motion_y[0];
+ }
- /* no vector maintenance (last vector remains the
- * last vector) */
- break;
+ /* no vector maintenance (last vector remains the
+ * last vector) */
+ break;
- case MODE_INTER_PRIOR_LAST:
- /* all 6 fragments use the motion vector prior to the
- * last motion vector */
- motion_x[0] = prior_last_motion_x;
- motion_y[0] = prior_last_motion_y;
- for (k = 1; k < 6; k++) {
- motion_x[k] = motion_x[0];
- motion_y[k] = motion_y[0];
- }
+ case MODE_INTER_PRIOR_LAST:
+ /* all 6 fragments use the motion vector prior to the
+ * last motion vector */
+ motion_x[0] = prior_last_motion_x;
+ motion_y[0] = prior_last_motion_y;
+ for (k = 1; k < 6; k++) {
+ motion_x[k] = motion_x[0];
+ motion_y[k] = motion_y[0];
+ }
- /* vector maintenance */
- prior_last_motion_x = last_motion_x;
- prior_last_motion_y = last_motion_y;
- last_motion_x = motion_x[0];
- last_motion_y = motion_y[0];
- break;
+ /* vector maintenance */
+ prior_last_motion_x = last_motion_x;
+ prior_last_motion_y = last_motion_y;
+ last_motion_x = motion_x[0];
+ last_motion_y = motion_y[0];
+ break;
- default:
- /* covers intra, inter without MV, golden without MV */
- memset(motion_x, 0, 6 * sizeof(int));
- memset(motion_y, 0, 6 * sizeof(int));
+ default:
+ /* covers intra, inter without MV, golden without MV */
+ memset(motion_x, 0, 6 * sizeof(int));
+ memset(motion_y, 0, 6 * sizeof(int));
- /* no vector maintenance */
- break;
- }
+ /* no vector maintenance */
+ break;
+ }
- /* assign the motion vectors to the correct fragments */
- for (k = 0; k < 6; k++) {
- current_fragment =
- s->macroblock_fragments[current_macroblock * 6 + k];
- if (current_fragment == -1)
- continue;
- if (current_fragment >= s->fragment_count) {
- av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad fragment number (%d >= %d)\n",
- current_fragment, s->fragment_count);
- return 1;
- }
- s->all_fragments[current_fragment].motion_x = motion_x[k];
- s->all_fragments[current_fragment].motion_y = motion_y[k];
+ /* assign the motion vectors to the correct fragments */
+ for (k = 0; k < 6; k++) {
+ current_fragment =
+ s->macroblock_fragments[current_macroblock * 6 + k];
+ if (current_fragment == -1)
+ continue;
+ if (current_fragment >= s->fragment_count) {
+ av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vectors(): bad fragment number (%d >= %d)\n",
+ current_fragment, s->fragment_count);
+ return 1;
}
+ s->all_fragments[current_fragment].motion_x = motion_x[k];
+ s->all_fragments[current_fragment].motion_y = motion_y[k];
}
}
+ }
return 0;
}
}
}
-
-static void horizontal_filter(unsigned char *first_pixel, int stride,
- int *bounding_values);
-static void vertical_filter(unsigned char *first_pixel, int stride,
- int *bounding_values);
-
/*
* Perform the final rendering for a particular slice of data.
* The slice number ranges from 0..(macroblock_height - 1).
/* dequantize the DCT coefficients */
if(s->avctx->idct_algo==FF_IDCT_VP3){
Coeff *coeff= s->coeffs + i;
- memset(block, 0, sizeof(block));
+ s->dsp.clear_block(block);
while(coeff->next){
block[coeff->index]= coeff->coeff * dequantizer[coeff->index];
coeff= coeff->next;
}
}else{
Coeff *coeff= s->coeffs + i;
- memset(block, 0, sizeof(block));
+ s->dsp.clear_block(block);
while(coeff->next){
block[coeff->index]= (coeff->coeff * dequantizer[coeff->index] + 2)>>2;
coeff= coeff->next;
emms_c();
}
-static void horizontal_filter(unsigned char *first_pixel, int stride,
- int *bounding_values)
-{
- unsigned char *end;
- int filter_value;
-
- for (end= first_pixel + 8*stride; first_pixel != end; first_pixel += stride) {
- filter_value =
- (first_pixel[-2] - first_pixel[ 1])
- +3*(first_pixel[ 0] - first_pixel[-1]);
- filter_value = bounding_values[(filter_value + 4) >> 3];
- first_pixel[-1] = av_clip_uint8(first_pixel[-1] + filter_value);
- first_pixel[ 0] = av_clip_uint8(first_pixel[ 0] - filter_value);
- }
-}
-
-static void vertical_filter(unsigned char *first_pixel, int stride,
- int *bounding_values)
-{
- unsigned char *end;
- int filter_value;
- const int nstride= -stride;
-
- for (end= first_pixel + 8; first_pixel < end; first_pixel++) {
- filter_value =
- (first_pixel[2 * nstride] - first_pixel[ stride])
- +3*(first_pixel[0 ] - first_pixel[nstride]);
- filter_value = bounding_values[(filter_value + 4) >> 3];
- first_pixel[nstride] = av_clip_uint8(first_pixel[nstride] + filter_value);
- first_pixel[0] = av_clip_uint8(first_pixel[0] - filter_value);
- }
-}
-
static void apply_loop_filter(Vp3DecodeContext *s)
{
int plane;
/* do not perform left edge filter for left columns frags */
if ((x > 0) &&
(s->all_fragments[fragment].coding_method != MODE_COPY)) {
- horizontal_filter(
+ s->dsp.vp3_h_loop_filter(
plane_data + s->all_fragments[fragment].first_pixel,
stride, bounding_values);
}
/* do not perform top edge filter for top row fragments */
if ((y > 0) &&
(s->all_fragments[fragment].coding_method != MODE_COPY)) {
- vertical_filter(
+ s->dsp.vp3_v_loop_filter(
plane_data + s->all_fragments[fragment].first_pixel,
stride, bounding_values);
}
if ((x < width - 1) &&
(s->all_fragments[fragment].coding_method != MODE_COPY) &&
(s->all_fragments[fragment + 1].coding_method == MODE_COPY)) {
- horizontal_filter(
+ s->dsp.vp3_h_loop_filter(
plane_data + s->all_fragments[fragment + 1].first_pixel,
stride, bounding_values);
}
if ((y < height - 1) &&
(s->all_fragments[fragment].coding_method != MODE_COPY) &&
(s->all_fragments[fragment + width].coding_method == MODE_COPY)) {
- vertical_filter(
+ s->dsp.vp3_v_loop_filter(
plane_data + s->all_fragments[fragment + width].first_pixel,
stride, bounding_values);
}
s->width = (avctx->width + 15) & 0xFFFFFFF0;
s->height = (avctx->height + 15) & 0xFFFFFFF0;
avctx->pix_fmt = PIX_FMT_YUV420P;
+ avctx->chroma_sample_location = AVCHROMA_LOC_CENTER;
if(avctx->idct_algo==FF_IDCT_AUTO)
avctx->idct_algo=FF_IDCT_VP3;
dsputil_init(&s->dsp, avctx);
*/
static int vp3_decode_frame(AVCodecContext *avctx,
void *data, int *data_size,
- const uint8_t *buf, int buf_size)
+ AVPacket *avpkt)
{
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
Vp3DecodeContext *s = avctx->priv_data;
GetBitContext gb;
static int counter = 0;
}
s->huff_code_size++;
s->hbits <<= 1;
- read_huffman_tree(avctx, gb);
+ if (read_huffman_tree(avctx, gb))
+ return -1;
s->hbits |= 1;
- read_huffman_tree(avctx, gb);
+ if (read_huffman_tree(avctx, gb))
+ return -1;
s->hbits >>= 1;
s->huff_code_size--;
}
return 0;
}
-#ifdef CONFIG_THEORA_DECODER
+#if CONFIG_THEORA_DECODER
static int theora_decode_header(AVCodecContext *avctx, GetBitContext *gb)
{
Vp3DecodeContext *s = avctx->priv_data;
s->huff_code_size = 1;
if (!get_bits1(gb)) {
s->hbits = 0;
- read_huffman_tree(avctx, gb);
+ if(read_huffman_tree(avctx, gb))
+ return -1;
s->hbits = 1;
- read_huffman_tree(avctx, gb);
+ if(read_huffman_tree(avctx, gb))
+ return -1;
}
}
return 0;
}
-static int theora_decode_init(AVCodecContext *avctx)
+static av_cold int theora_decode_init(AVCodecContext *avctx)
{
Vp3DecodeContext *s = avctx->priv_data;
GetBitContext gb;
}
// FIXME: Check for this as well.
- skip_bits(&gb, 6*8); /* "theora" */
+ skip_bits_long(&gb, 6*8); /* "theora" */
switch(ptype)
{
// theora_decode_comments(avctx, gb);
break;
case 0x82:
- theora_decode_tables(avctx, &gb);
+ if (theora_decode_tables(avctx, &gb))
+ return -1;
break;
default:
av_log(avctx, AV_LOG_ERROR, "Unknown Theora config packet: %d\n", ptype&~0x80);