#include <string.h>
#include "libavutil/imgutils.h"
+#include "libavutil/mem_internal.h"
#include "avcodec.h"
#include "get_bits.h"
#include "vp3dsp.h"
#include "xiph.h"
+#define VP3_MV_VLC_BITS 6
+#define VP4_MV_VLC_BITS 6
+#define SUPERBLOCK_VLC_BITS 6
+
#define FRAGMENT_PIXELS 8
// FIXME split things out into their own arrays
#define MIN_DEQUANT_VAL 2
+typedef struct HuffEntry {
+ uint8_t len, sym;
+} HuffEntry;
+
+typedef struct HuffTable {
+ HuffEntry entries[32];
+ uint8_t nb_entries;
+} HuffTable;
+
typedef struct Vp3DecodeContext {
AVCodecContext *avctx;
int theora, theora_tables, theora_header;
uint8_t *edge_emu_buffer;
/* Huffman decode */
- int hti;
- unsigned int hbits;
- int entries;
- int huff_code_size;
- uint32_t huffman_table[80][32][2];
+ HuffTable huffman_table[5 * 16];
uint8_t filter_limit_values[64];
DECLARE_ALIGNED(8, int, bounding_values_array)[256 + 2];
bit ^= 1;
current_run = get_vlc2(gb, s->superblock_run_length_vlc.table,
- 6, 2) + 1;
+ SUPERBLOCK_VLC_BITS, 2);
if (current_run == 34)
current_run += get_bits(gb, 12);
bit ^= 1;
current_run = get_vlc2(gb, s->superblock_run_length_vlc.table,
- 6, 2) + 1;
+ SUPERBLOCK_VLC_BITS, 2);
if (current_run == 34)
current_run += get_bits(gb, 12);
static int vp4_get_block_pattern(Vp3DecodeContext *s, GetBitContext *gb, int *next_block_pattern_table)
{
int v = get_vlc2(gb, s->block_pattern_vlc[*next_block_pattern_table].table, 3, 2);
- if (v == -1) {
- av_log(s->avctx, AV_LOG_ERROR, "Invalid block pattern\n");
- *next_block_pattern_table = 0;
- return 0;
- }
*next_block_pattern_table = vp4_block_pattern_table_selector[v];
return v + 1;
}
static int vp4_get_mv(Vp3DecodeContext *s, GetBitContext *gb, int axis, int last_motion)
{
- int v = get_vlc2(gb, s->vp4_mv_vlc[axis][vp4_mv_table_selector[FFABS(last_motion)]].table, 6, 2) - 31;
+ int v = get_vlc2(gb, s->vp4_mv_vlc[axis][vp4_mv_table_selector[FFABS(last_motion)]].table,
+ VP4_MV_VLC_BITS, 2);
return last_motion < 0 ? -v : v;
}
case MODE_INTER_PLUS_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)];
+ motion_x[0] = get_vlc2(gb, s->motion_vector_vlc.table,
+ VP3_MV_VLC_BITS, 2);
+ motion_y[0] = get_vlc2(gb, s->motion_vector_vlc.table,
+ VP3_MV_VLC_BITS, 2);
} else if (coding_mode == 1) {
motion_x[0] = fixed_motion_vector_table[get_bits(gb, 6)];
motion_y[0] = fixed_motion_vector_table[get_bits(gb, 6)];
current_fragment = BLOCK_Y * s->fragment_width[0] + BLOCK_X;
if (s->all_fragments[current_fragment].coding_method != MODE_COPY) {
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)];
+ motion_x[k] = get_vlc2(gb, s->motion_vector_vlc.table,
+ VP3_MV_VLC_BITS, 2);
+ motion_y[k] = get_vlc2(gb, s->motion_vector_vlc.table,
+ VP3_MV_VLC_BITS, 2);
} else if (coding_mode == 1) {
motion_x[k] = fixed_motion_vector_table[get_bits(gb, 6)];
motion_y[k] = fixed_motion_vector_table[get_bits(gb, 6)];
else
bit ^= 1;
- run_length = get_vlc2(gb, s->superblock_run_length_vlc.table, 6, 2) + 1;
+ run_length = get_vlc2(gb, s->superblock_run_length_vlc.table,
+ SUPERBLOCK_VLC_BITS, 2);
if (run_length == 34)
run_length += get_bits(gb, 12);
blocks_decoded += run_length;
/* init VLC tables */
if (s->version < 2) {
for (i = 0; i < FF_ARRAY_ELEMS(s->coeff_vlc); i++) {
- if ((ret = init_vlc(&s->coeff_vlc[i], 11, 32,
- &vp3_bias[i][0][1], 4, 2,
- &vp3_bias[i][0][0], 4, 2, 0)) < 0)
+ ret = ff_init_vlc_from_lengths(&s->coeff_vlc[i], 11, 32,
+ &vp3_bias[i][0][1], 2,
+ &vp3_bias[i][0][0], 2, 1,
+ 0, 0, avctx);
+ if (ret < 0)
return ret;
}
#if CONFIG_VP4_DECODER
} else { /* version >= 2 */
for (i = 0; i < FF_ARRAY_ELEMS(s->coeff_vlc); i++) {
- if ((ret = init_vlc(&s->coeff_vlc[i], 11, 32,
- &vp4_bias[i][0][1], 4, 2,
- &vp4_bias[i][0][0], 4, 2, 0)) < 0)
+ ret = ff_init_vlc_from_lengths(&s->coeff_vlc[i], 11, 32,
+ &vp4_bias[i][0][1], 2,
+ &vp4_bias[i][0][0], 2, 1,
+ 0, 0, avctx);
+ if (ret < 0)
return ret;
}
#endif
}
} else {
for (i = 0; i < FF_ARRAY_ELEMS(s->coeff_vlc); i++) {
- if (init_vlc(&s->coeff_vlc[i], 11, 32,
- &s->huffman_table[i][0][1], 8, 4,
- &s->huffman_table[i][0][0], 8, 4, 0) < 0)
- goto vlc_fail;
+ const HuffTable *tab = &s->huffman_table[i];
+
+ ret = ff_init_vlc_from_lengths(&s->coeff_vlc[i], 11, tab->nb_entries,
+ &tab->entries[0].len, sizeof(*tab->entries),
+ &tab->entries[0].sym, sizeof(*tab->entries), 1,
+ 0, 0, avctx);
+ if (ret < 0)
+ return ret;
}
}
- if ((ret = init_vlc(&s->superblock_run_length_vlc, 6, 34,
- &superblock_run_length_vlc_table[0][1], 4, 2,
- &superblock_run_length_vlc_table[0][0], 4, 2, 0)) < 0)
+ ret = ff_init_vlc_from_lengths(&s->superblock_run_length_vlc, SUPERBLOCK_VLC_BITS, 34,
+ superblock_run_length_vlc_lens, 1,
+ NULL, 0, 0, 1, 0, avctx);
+ if (ret < 0)
return ret;
- if ((ret = init_vlc(&s->fragment_run_length_vlc, 5, 30,
- &fragment_run_length_vlc_table[0][1], 4, 2,
- &fragment_run_length_vlc_table[0][0], 4, 2, 0)) < 0)
+ ret = ff_init_vlc_from_lengths(&s->fragment_run_length_vlc, 5, 30,
+ fragment_run_length_vlc_len, 1,
+ NULL, 0, 0, 0, 0, avctx);
+ if (ret < 0)
return ret;
- if ((ret = init_vlc(&s->mode_code_vlc, 3, 8,
- &mode_code_vlc_table[0][1], 2, 1,
- &mode_code_vlc_table[0][0], 2, 1, 0)) < 0)
+ ret = ff_init_vlc_from_lengths(&s->mode_code_vlc, 3, 8,
+ mode_code_vlc_len, 1,
+ NULL, 0, 0, 0, 0, avctx);
+ if (ret < 0)
return ret;
- if ((ret = init_vlc(&s->motion_vector_vlc, 6, 63,
- &motion_vector_vlc_table[0][1], 2, 1,
- &motion_vector_vlc_table[0][0], 2, 1, 0)) < 0)
+ ret = ff_init_vlc_from_lengths(&s->motion_vector_vlc, VP3_MV_VLC_BITS, 63,
+ &motion_vector_vlc_table[0][1], 2,
+ &motion_vector_vlc_table[0][0], 2, 1,
+ -31, 0, avctx);
+ if (ret < 0)
return ret;
#if CONFIG_VP4_DECODER
for (j = 0; j < 2; j++)
- for (i = 0; i < 7; i++)
- if ((ret = init_vlc(&s->vp4_mv_vlc[j][i], 6, 63,
- &vp4_mv_vlc[j][i][0][1], 4, 2,
- &vp4_mv_vlc[j][i][0][0], 4, 2, 0)) < 0)
+ for (i = 0; i < 7; i++) {
+ ret = ff_init_vlc_from_lengths(&s->vp4_mv_vlc[j][i], VP4_MV_VLC_BITS, 63,
+ &vp4_mv_vlc[j][i][0][1], 2,
+ &vp4_mv_vlc[j][i][0][0], 2, 1, -31,
+ 0, avctx);
+ if (ret < 0)
return ret;
+ }
/* version >= 2 */
for (i = 0; i < 2; i++)
#endif
return allocate_tables(avctx);
-
-vlc_fail:
- av_log(avctx, AV_LOG_FATAL, "Invalid huffman table\n");
- return -1;
}
/// Release and shuffle frames after decode finishes
return ret;
}
-static int read_huffman_tree(AVCodecContext *avctx, GetBitContext *gb)
+static int read_huffman_tree(HuffTable *huff, GetBitContext *gb, int length,
+ AVCodecContext *avctx)
{
- Vp3DecodeContext *s = avctx->priv_data;
-
if (get_bits1(gb)) {
int token;
- if (s->entries >= 32) { /* overflow */
+ if (huff->nb_entries >= 32) { /* overflow */
av_log(avctx, AV_LOG_ERROR, "huffman tree overflow\n");
return -1;
}
token = get_bits(gb, 5);
- ff_dlog(avctx, "hti %d hbits %x token %d entry : %d size %d\n",
- s->hti, s->hbits, token, s->entries, s->huff_code_size);
- s->huffman_table[s->hti][token][0] = s->hbits;
- s->huffman_table[s->hti][token][1] = s->huff_code_size;
- s->entries++;
+ ff_dlog(avctx, "code length %d, curr entry %d, token %d\n",
+ length, huff->nb_entries, token);
+ huff->entries[huff->nb_entries++] = (HuffEntry){ length, token };
} else {
- if (s->huff_code_size >= 32) { /* overflow */
+ /* The following bound follows from the fact that nb_entries <= 32. */
+ if (length >= 31) { /* overflow */
av_log(avctx, AV_LOG_ERROR, "huffman tree overflow\n");
return -1;
}
- s->huff_code_size++;
- s->hbits <<= 1;
- if (read_huffman_tree(avctx, gb))
+ length++;
+ if (read_huffman_tree(huff, gb, length, avctx))
return -1;
- s->hbits |= 1;
- if (read_huffman_tree(avctx, gb))
+ if (read_huffman_tree(huff, gb, length, avctx))
return -1;
- s->hbits >>= 1;
- s->huff_code_size--;
}
return 0;
}
int ret;
AVRational fps, aspect;
+ if (get_bits_left(gb) < 206)
+ return AVERROR_INVALIDDATA;
+
s->theora_header = 0;
s->theora = get_bits(gb, 24);
av_log(avctx, AV_LOG_DEBUG, "Theora bitstream version %X\n", s->theora);
static int theora_decode_tables(AVCodecContext *avctx, GetBitContext *gb)
{
Vp3DecodeContext *s = avctx->priv_data;
- int i, n, matrices, inter, plane;
+ int i, n, matrices, inter, plane, ret;
if (!s->theora_header)
return AVERROR_INVALIDDATA;
}
/* Huffman tables */
- for (s->hti = 0; s->hti < 80; s->hti++) {
- s->entries = 0;
- s->huff_code_size = 1;
- if (!get_bits1(gb)) {
- s->hbits = 0;
- if (read_huffman_tree(avctx, gb))
- return -1;
- s->hbits = 1;
- if (read_huffman_tree(avctx, gb))
- return -1;
- }
+ for (int i = 0; i < FF_ARRAY_ELEMS(s->huffman_table); i++) {
+ s->huffman_table[i].nb_entries = 0;
+ if ((ret = read_huffman_tree(&s->huffman_table[i], gb, 0, avctx)) < 0)
+ return ret;
}
s->theora_tables = 1;
return vp3_decode_init(avctx);
}
-AVCodec ff_theora_decoder = {
+const AVCodec ff_theora_decoder = {
.name = "theora",
.long_name = NULL_IF_CONFIG_SMALL("Theora"),
.type = AVMEDIA_TYPE_VIDEO,
};
#endif
-AVCodec ff_vp3_decoder = {
+const AVCodec ff_vp3_decoder = {
.name = "vp3",
.long_name = NULL_IF_CONFIG_SMALL("On2 VP3"),
.type = AVMEDIA_TYPE_VIDEO,
};
#if CONFIG_VP4_DECODER
-AVCodec ff_vp4_decoder = {
+const AVCodec ff_vp4_decoder = {
.name = "vp4",
.long_name = NULL_IF_CONFIG_SMALL("On2 VP4"),
.type = AVMEDIA_TYPE_VIDEO,