summaryrefslogtreecommitdiff
path: root/vp9/decoder
diff options
context:
space:
mode:
Diffstat (limited to 'vp9/decoder')
-rw-r--r--vp9/decoder/vp9_decodframe.c194
-rw-r--r--vp9/decoder/vp9_detokenize.c4
-rw-r--r--vp9/decoder/vp9_read_bit_buffer.h50
3 files changed, 149 insertions, 99 deletions
diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c
index 70e0c8759..a4a8226a0 100644
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -10,29 +10,30 @@
#include <assert.h>
-#include "vp9/decoder/vp9_onyxd_int.h"
+#include "./vp9_rtcd.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_scale/vpx_scale.h"
+
+#include "vp9/common/vp9_extend.h"
+#include "vp9/common/vp9_modecont.h"
#include "vp9/common/vp9_common.h"
-#include "vp9/common/vp9_header.h"
#include "vp9/common/vp9_reconintra.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/common/vp9_entropy.h"
-#include "vp9/decoder/vp9_decodframe.h"
-#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/common/vp9_invtrans.h"
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_quant_common.h"
-#include "vpx_scale/vpx_scale.h"
+#include "vp9/common/vp9_seg_common.h"
+#include "vp9/common/vp9_tile_common.h"
-#include "vp9/decoder/vp9_decodemv.h"
-#include "vp9/common/vp9_extend.h"
-#include "vp9/common/vp9_modecont.h"
-#include "vpx_mem/vpx_mem.h"
#include "vp9/decoder/vp9_dboolhuff.h"
+#include "vp9/decoder/vp9_decodframe.h"
+#include "vp9/decoder/vp9_detokenize.h"
+#include "vp9/decoder/vp9_decodemv.h"
+#include "vp9/decoder/vp9_onyxd_int.h"
+#include "vp9/decoder/vp9_read_bit_buffer.h"
-#include "vp9/common/vp9_seg_common.h"
-#include "vp9/common/vp9_tile_common.h"
-#include "./vp9_rtcd.h"
// #define DEC_DEBUG
#ifdef DEC_DEBUG
@@ -743,32 +744,24 @@ static INTERPOLATIONFILTERTYPE read_mcomp_filter_type(vp9_reader *r) {
: vp9_read_literal(r, 2);
}
-static const uint8_t *read_frame_size(VP9_COMMON *const pc, const uint8_t *data,
- const uint8_t *data_end,
- int *width, int *height) {
- if (data + 4 < data_end) {
- const int w = read_le16(data);
- const int h = read_le16(data + 2);
- if (w <= 0)
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Invalid frame width");
-
- if (h <= 0)
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Invalid frame height");
- *width = w;
- *height = h;
- data += 4;
- } else {
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Failed to read frame size");
- }
- return data;
+static void read_frame_size(VP9_COMMON *cm,
+ struct vp9_read_bit_buffer *rb,
+ int *width, int *height) {
+ const int w = vp9_rb_read_literal(rb, 16);
+ const int h = vp9_rb_read_literal(rb, 16);
+ if (w <= 0)
+ vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
+ "Invalid frame width");
+
+ if (h <= 0)
+ vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,
+ "Invalid frame height");
+ *width = w;
+ *height = h;
}
-static const uint8_t *setup_frame_size(VP9D_COMP *pbi, int scaling_active,
- const uint8_t *data,
- const uint8_t *data_end) {
+static void setup_frame_size(VP9D_COMP *pbi, int scaling_active,
+ struct vp9_read_bit_buffer *rb) {
// If error concealment is enabled we should only parse the new size
// if we have enough data. Otherwise we will end up with the wrong size.
VP9_COMMON *const pc = &pbi->common;
@@ -778,9 +771,9 @@ static const uint8_t *setup_frame_size(VP9D_COMP *pbi, int scaling_active,
int height = pc->height;
if (scaling_active)
- data = read_frame_size(pc, data, data_end, &display_width, &display_height);
+ read_frame_size(pc, rb, &display_width, &display_height);
- data = read_frame_size(pc, data, data_end, &width, &height);
+ read_frame_size(pc, rb, &width, &height);
if (pc->width != width || pc->height != height) {
if (!pbi->initial_width || !pbi->initial_height) {
@@ -806,8 +799,6 @@ static const uint8_t *setup_frame_size(VP9D_COMP *pbi, int scaling_active,
vp9_update_frame_size(pc);
}
-
- return data;
}
static void update_frame_context(FRAME_CONTEXT *fc) {
@@ -937,59 +928,78 @@ static void decode_tiles(VP9D_COMP *pbi,
}
}
-int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
- vp9_reader header_bc, residual_bc;
- VP9_COMMON *const pc = &pbi->common;
- MACROBLOCKD *const xd = &pbi->mb;
- const uint8_t *data = pbi->source;
- const uint8_t *data_end = data + pbi->source_sz;
- size_t first_partition_size = 0;
- YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
- int i;
- xd->corrupted = 0; // start with no corruption of current frame
- new_fb->corrupted = 0;
+static void error_handler(void *data, int bit_offset) {
+ VP9_COMMON *const cm = (VP9_COMMON *)data;
+ vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet");
+}
+
+size_t read_uncompressed_header(VP9D_COMP *pbi,
+ struct vp9_read_bit_buffer *rb) {
+ VP9_COMMON *const cm = &pbi->common;
+
+ int scaling_active;
+ cm->last_frame_type = cm->frame_type;
+ cm->frame_type = (FRAME_TYPE) vp9_rb_read_bit(rb);
+ cm->version = vp9_rb_read_literal(rb, 3);
+ cm->show_frame = vp9_rb_read_bit(rb);
+ scaling_active = vp9_rb_read_bit(rb);
+ cm->subsampling_x = vp9_rb_read_bit(rb);
+ cm->subsampling_y = vp9_rb_read_bit(rb);
+
+ if (cm->frame_type == KEY_FRAME) {
+ if (vp9_rb_read_literal(rb, 8) != SYNC_CODE_0 ||
+ vp9_rb_read_literal(rb, 8) != SYNC_CODE_1 ||
+ vp9_rb_read_literal(rb, 8) != SYNC_CODE_2) {
+ vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
+ "Invalid frame sync code");
+ }
+ }
+ setup_frame_size(pbi, scaling_active, rb);
- if (data_end - data < 3) {
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet");
+ cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
+ cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);
+
+ cm->error_resilient_mode = vp9_rb_read_bit(rb);
+ if (!cm->error_resilient_mode) {
+ cm->refresh_frame_context = vp9_rb_read_bit(rb);
+ cm->frame_parallel_decoding_mode = vp9_rb_read_bit(rb);
} else {
- int scaling_active;
- pc->last_frame_type = pc->frame_type;
- pc->frame_type = (FRAME_TYPE)(data[0] & 1);
- pc->version = (data[0] >> 1) & 7;
- pc->show_frame = (data[0] >> 4) & 1;
- scaling_active = (data[0] >> 5) & 1;
- pc->subsampling_x = (data[0] >> 6) & 1;
- pc->subsampling_y = (data[0] >> 7) & 1;
- first_partition_size = read_le16(data + 1);
-
- if (!read_is_valid(data, first_partition_size, data_end))
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Truncated packet or corrupt partition 0 length");
+ cm->refresh_frame_context = 0;
+ cm->frame_parallel_decoding_mode = 1;
+ }
- data += 3;
+ return vp9_rb_read_literal(rb, 16);
+}
- vp9_setup_version(pc);
+int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
+ int i;
+ vp9_reader header_bc, residual_bc;
+ VP9_COMMON *const pc = &pbi->common;
+ MACROBLOCKD *const xd = &pbi->mb;
+ YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
+ const uint8_t *data = pbi->source;
+ const uint8_t *data_end = pbi->source + pbi->source_sz;
- if (pc->frame_type == KEY_FRAME) {
- // When error concealment is enabled we should only check the sync
- // code if we have enough bits available
- if (data + 3 < data_end) {
- if (data[0] != 0x49 || data[1] != 0x83 || data[2] != 0x42)
- vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
- "Invalid frame sync code");
- }
- data += 3;
- }
+ struct vp9_read_bit_buffer rb = { data, data_end, 0,
+ pc, error_handler };
+ const size_t first_partition_size = read_uncompressed_header(pbi, &rb);
+ const int keyframe = pc->frame_type == KEY_FRAME;
- data = setup_frame_size(pbi, scaling_active, data, data_end);
- }
+ data += vp9_rb_bytes_read(&rb);
+ xd->corrupted = 0;
+ new_fb->corrupted = 0;
- if ((!pbi->decoded_key_frame && pc->frame_type != KEY_FRAME) ||
+ if ((!pbi->decoded_key_frame && !keyframe) ||
pc->width == 0 || pc->height == 0) {
return -1;
}
+ vp9_setup_version(pc);
+ if (!read_is_valid(data, first_partition_size, data_end))
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated packet or corrupt partition 0 length");
+
init_frame(pbi);
// Reset the frame pointers to the current frame size
@@ -1001,9 +1011,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder 0");
- pc->clr_type = (YUV_TYPE)vp9_read_bit(&header_bc);
- pc->error_resilient_mode = vp9_read_bit(&header_bc);
-
setup_loopfilter(pc, xd, &header_bc);
setup_quantization(pbi, &header_bc);
@@ -1025,7 +1032,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
// Determine if the golden frame or ARF buffer should be updated and how.
// For all non key frames the GF and ARF refresh flags and sign bias
// flags must be set explicitly.
- if (pc->frame_type == KEY_FRAME) {
+ if (keyframe) {
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
pc->active_ref_idx[i] = pc->new_fb_idx;
} else {
@@ -1050,15 +1057,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
}
- if (!pc->error_resilient_mode) {
- pc->refresh_frame_context = vp9_read_bit(&header_bc);
- pc->frame_parallel_decoding_mode = vp9_read_bit(&header_bc);
- } else {
- pc->refresh_frame_context = 0;
- pc->frame_parallel_decoding_mode = 1;
- }
-
- pc->frame_context_idx = vp9_read_literal(&header_bc, NUM_FRAME_CONTEXTS_LG2);
pc->fc = pc->frame_contexts[pc->frame_context_idx];
setup_segmentation(pc, xd, &header_bc);
@@ -1068,7 +1066,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
setup_txfm_mode(pc, xd->lossless, &header_bc);
// Read inter mode probability context updates
- if (pc->frame_type != KEY_FRAME) {
+ if (!keyframe) {
int i, j;
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
for (j = 0; j < 4; ++j)
@@ -1076,7 +1074,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
pc->fc.vp9_mode_contexts[i][j] = vp9_read_prob(&header_bc);
}
// Is this needed ?
- if (pc->frame_type == KEY_FRAME)
+ if (keyframe)
vp9_default_coef_probs(pc);
update_frame_context(&pc->fc);
@@ -1109,7 +1107,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
new_fb->corrupted = vp9_reader_has_error(&header_bc) | xd->corrupted;
if (!pbi->decoded_key_frame) {
- if (pc->frame_type == KEY_FRAME && !new_fb->corrupted)
+ if (keyframe && !new_fb->corrupted)
pbi->decoded_key_frame = 1;
else
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
@@ -1120,7 +1118,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
if (!pc->error_resilient_mode && !pc->frame_parallel_decoding_mode) {
vp9_adapt_coef_probs(pc);
- if (pc->frame_type != KEY_FRAME) {
+ if (!keyframe) {
vp9_adapt_mode_probs(pc);
vp9_adapt_mode_context(pc);
vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv);
diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c
index 02900c08c..890d5d0d6 100644
--- a/vp9/decoder/vp9_detokenize.c
+++ b/vp9/decoder/vp9_detokenize.c
@@ -58,13 +58,15 @@ static const vp9_prob cat6_prob[15] = {
254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0
};
+DECLARE_ALIGNED(16, extern const uint8_t,
+ vp9_pt_energy_class[MAX_ENTROPY_TOKENS]);
#define INCREMENT_COUNT(token) \
do { \
coef_counts[type][ref][band][pt] \
[token >= TWO_TOKEN ? \
(token == DCT_EOB_TOKEN ? DCT_EOB_MODEL_TOKEN : TWO_TOKEN) : \
token]++; \
- token_cache[scan[c]] = token; \
+ token_cache[scan[c]] = vp9_pt_energy_class[token]; \
} while (0)
#define WRITE_COEF_CONTINUE(val, token) \
diff --git a/vp9/decoder/vp9_read_bit_buffer.h b/vp9/decoder/vp9_read_bit_buffer.h
new file mode 100644
index 000000000..fa2dbee8d
--- /dev/null
+++ b/vp9/decoder/vp9_read_bit_buffer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VP9_READ_BIT_BUFFER_
+#define VP9_READ_BIT_BUFFER_
+
+typedef void (*vp9_rb_error_handler)(void *data, int bit_offset);
+
+struct vp9_read_bit_buffer {
+ const uint8_t *bit_buffer;
+ const uint8_t *bit_buffer_end;
+ size_t bit_offset;
+
+ void *error_handler_data;
+ vp9_rb_error_handler error_handler;
+};
+
+static size_t vp9_rb_bytes_read(struct vp9_read_bit_buffer *rb) {
+ return rb->bit_offset / CHAR_BIT + (rb->bit_offset % CHAR_BIT > 0);
+}
+
+static int vp9_rb_read_bit(struct vp9_read_bit_buffer *rb) {
+ const int off = rb->bit_offset;
+ const int p = off / CHAR_BIT;
+ const int q = CHAR_BIT - 1 - off % CHAR_BIT;
+ if (rb->bit_buffer + p >= rb->bit_buffer_end) {
+ rb->error_handler(rb->error_handler_data, rb->bit_offset);
+ return 0;
+ } else {
+ const int bit = (rb->bit_buffer[p] & (1 << q)) >> q;
+ rb->bit_offset = off + 1;
+ return bit;
+ }
+}
+
+static int vp9_rb_read_literal(struct vp9_read_bit_buffer *rb, int bits) {
+ int value = 0, bit;
+ for (bit = bits - 1; bit >= 0; bit--)
+ value |= vp9_rb_read_bit(rb) << bit;
+ return value;
+}
+
+#endif // VP9_READ_BIT_BUFFER_