From 91037db265ecdd914a26e056cf69207b4f50924e Mon Sep 17 00:00:00 2001 From: hkuang Date: Thu, 25 Jul 2013 11:11:39 -0700 Subject: Roll latest libvpx into Android. Make the VP9 decoding 2X faster than the old one. Checkout is from master branch(hash:242157c756314827ad9244952c7253e8900b9626). Change-Id: Ibe67b3ee19f82b87df2416826b63a67f7f79b63a --- .../arm/neon/vp9_add_constant_residual_neon.asm | 230 +++++ libvpx/vp9/decoder/vp9_asm_dec_offsets.c | 20 - libvpx/vp9/decoder/vp9_dboolhuff.c | 23 + libvpx/vp9/decoder/vp9_dboolhuff.h | 23 +- libvpx/vp9/decoder/vp9_decodemv.c | 943 +++++++++------------ libvpx/vp9/decoder/vp9_decodemv.h | 9 +- libvpx/vp9/decoder/vp9_decodframe.c | 781 +++++++---------- libvpx/vp9/decoder/vp9_decodframe.h | 1 - libvpx/vp9/decoder/vp9_detokenize.c | 78 +- libvpx/vp9/decoder/vp9_dsubexp.c | 106 +++ libvpx/vp9/decoder/vp9_dsubexp.h | 19 + libvpx/vp9/decoder/vp9_idct_blk.c | 2 +- libvpx/vp9/decoder/vp9_onyxd_if.c | 15 +- libvpx/vp9/decoder/vp9_onyxd_int.h | 31 +- libvpx/vp9/decoder/vp9_read_bit_buffer.h | 6 + 15 files changed, 1124 insertions(+), 1163 deletions(-) create mode 100644 libvpx/vp9/decoder/arm/neon/vp9_add_constant_residual_neon.asm delete mode 100644 libvpx/vp9/decoder/vp9_asm_dec_offsets.c create mode 100644 libvpx/vp9/decoder/vp9_dsubexp.c create mode 100644 libvpx/vp9/decoder/vp9_dsubexp.h (limited to 'libvpx/vp9/decoder') diff --git a/libvpx/vp9/decoder/arm/neon/vp9_add_constant_residual_neon.asm b/libvpx/vp9/decoder/arm/neon/vp9_add_constant_residual_neon.asm new file mode 100644 index 0000000..174e747 --- /dev/null +++ b/libvpx/vp9/decoder/arm/neon/vp9_add_constant_residual_neon.asm @@ -0,0 +1,230 @@ +; +; 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. +; + + EXPORT |vp9_add_constant_residual_8x8_neon| + EXPORT |vp9_add_constant_residual_16x16_neon| + EXPORT |vp9_add_constant_residual_32x32_neon| + ARM + + AREA ||.text||, CODE, READONLY, ALIGN=2 + + MACRO + LD_16x8 $src, $stride + vld1.8 {q8}, [$src], $stride + vld1.8 {q9}, [$src], $stride + vld1.8 {q10}, [$src], $stride + vld1.8 {q11}, [$src], $stride + vld1.8 {q12}, [$src], $stride + vld1.8 {q13}, [$src], $stride + vld1.8 {q14}, [$src], $stride + vld1.8 {q15}, [$src], $stride + MEND + + MACRO + ADD_DIFF_16x8 $diff + vqadd.u8 q8, q8, $diff + vqadd.u8 q9, q9, $diff + vqadd.u8 q10, q10, $diff + vqadd.u8 q11, q11, $diff + vqadd.u8 q12, q12, $diff + vqadd.u8 q13, q13, $diff + vqadd.u8 q14, q14, $diff + vqadd.u8 q15, q15, $diff + MEND + + MACRO + SUB_DIFF_16x8 $diff + vqsub.u8 q8, q8, $diff + vqsub.u8 q9, q9, $diff + vqsub.u8 q10, q10, $diff + vqsub.u8 q11, q11, $diff + vqsub.u8 q12, q12, $diff + vqsub.u8 q13, q13, $diff + vqsub.u8 q14, q14, $diff + vqsub.u8 q15, q15, $diff + MEND + + MACRO + ST_16x8 $dst, $stride + vst1.8 {q8}, [$dst], $stride + vst1.8 {q9}, [$dst], $stride + vst1.8 {q10}, [$dst], $stride + vst1.8 {q11}, [$dst], $stride + vst1.8 {q12}, [$dst], $stride + vst1.8 {q13}, [$dst], $stride + vst1.8 {q14}, [$dst], $stride + vst1.8 {q15}, [$dst], $stride + MEND + +; void add_constant_residual(const int16_t diff, uint8_t *dest, int stride, +; int width, int height) { +; int r, c; +; +; for (r = 0; r < height; r++) { +; for (c = 0; c < width; c++) +; dest[c] = clip_pixel(diff + dest[c]); +; +; dest += stride; +; } +;} +;void vp9_add_constant_residual_8x8_c(const int16_t diff, uint8_t *dest, +; int stride) { +; add_constant_residual(diff, dest, stride, 8, 8); +;} +; r0 : const int16_t diff +; r1 : const uint8_t *dest +; r2 : int stride +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +|vp9_add_constant_residual_8x8_neon| PROC + mov r3, r1 ; r3: save dest to r3 + vld1.8 {d0}, [r1], r2 + vld1.8 {d1}, [r1], r2 + vld1.8 {d2}, [r1], r2 + vld1.8 {d3}, [r1], r2 + vld1.8 {d4}, [r1], r2 + vld1.8 {d5}, [r1], r2 + vld1.8 {d6}, [r1], r2 + vld1.8 {d7}, [r1], r2 + cmp r0, #0 + bge DIFF_POSITIVE_8x8 + +DIFF_NEGATIVE_8x8 ; diff < 0 + neg r0, r0 + usat r0, #8, r0 + vdup.u8 q8, r0 + + vqsub.u8 q0, q0, q8 + vqsub.u8 q1, q1, q8 + vqsub.u8 q2, q2, q8 + vqsub.u8 q3, q3, q8 + b DIFF_SAVE_8x8 + +DIFF_POSITIVE_8x8 ; diff >= 0 + usat r0, #8, r0 + vdup.u8 q8, r0 + + vqadd.u8 q0, q0, q8 + vqadd.u8 q1, q1, q8 + vqadd.u8 q2, q2, q8 + vqadd.u8 q3, q3, q8 + +DIFF_SAVE_8x8 + vst1.8 {d0}, [r3], r2 + vst1.8 {d1}, [r3], r2 + vst1.8 {d2}, [r3], r2 + vst1.8 {d3}, [r3], r2 + vst1.8 {d4}, [r3], r2 + vst1.8 {d5}, [r3], r2 + vst1.8 {d6}, [r3], r2 + vst1.8 {d7}, [r3], r2 + + bx lr + ENDP + +;void vp9_add_constant_residual_16x16_c(const int16_t diff, uint8_t *dest, +; int stride) { +; add_constant_residual(diff, dest, stride, 16, 16); +;} +; r0 : const int16_t diff +; r1 : const uint8_t *dest +; r2 : int stride +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +|vp9_add_constant_residual_16x16_neon| PROC + mov r3, r1 + LD_16x8 r1, r2 + cmp r0, #0 + bge DIFF_POSITIVE_16x16 + +|DIFF_NEGATIVE_16x16| + neg r0, r0 + usat r0, #8, r0 + vdup.u8 q0, r0 + + SUB_DIFF_16x8 q0 + ST_16x8 r3, r2 + LD_16x8 r1, r2 + SUB_DIFF_16x8 q0 + b DIFF_SAVE_16x16 + +|DIFF_POSITIVE_16x16| + usat r0, #8, r0 + vdup.u8 q0, r0 + + ADD_DIFF_16x8 q0 + ST_16x8 r3, r2 + LD_16x8 r1, r2 + ADD_DIFF_16x8 q0 + +|DIFF_SAVE_16x16| + ST_16x8 r3, r2 + bx lr + ENDP + +;void vp9_add_constant_residual_32x32_c(const int16_t diff, uint8_t *dest, +; int stride) { +; add_constant_residual(diff, dest, stride, 32, 32); +;} +; r0 : const int16_t diff +; r1 : const uint8_t *dest +; r2 : int stride +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +|vp9_add_constant_residual_32x32_neon| PROC + push {r4,lr} + pld [r1] + mov r3, r1 + add r4, r1, #16 ; r4 dest + 16 for second loop + cmp r0, #0 + bge DIFF_POSITIVE_32x32 + +|DIFF_NEGATIVE_32x32| + neg r0, r0 + usat r0, #8, r0 + vdup.u8 q0, r0 + mov r0, #4 + +|DIFF_NEGATIVE_32x32_LOOP| + sub r0, #1 + LD_16x8 r1, r2 + SUB_DIFF_16x8 q0 + ST_16x8 r3, r2 + + LD_16x8 r1, r2 + SUB_DIFF_16x8 q0 + ST_16x8 r3, r2 + cmp r0, #2 + moveq r1, r4 + moveq r3, r4 + cmp r0, #0 + bne DIFF_NEGATIVE_32x32_LOOP + pop {r4,pc} + +|DIFF_POSITIVE_32x32| + usat r0, #8, r0 + vdup.u8 q0, r0 + mov r0, #4 + +|DIFF_POSITIVE_32x32_LOOP| + sub r0, #1 + LD_16x8 r1, r2 + ADD_DIFF_16x8 q0 + ST_16x8 r3, r2 + + LD_16x8 r1, r2 + ADD_DIFF_16x8 q0 + ST_16x8 r3, r2 + cmp r0, #2 + moveq r1, r4 + moveq r3, r4 + cmp r0, #0 + bne DIFF_POSITIVE_32x32_LOOP + pop {r4,pc} + ENDP + + END diff --git a/libvpx/vp9/decoder/vp9_asm_dec_offsets.c b/libvpx/vp9/decoder/vp9_asm_dec_offsets.c deleted file mode 100644 index e4b9c97..0000000 --- a/libvpx/vp9/decoder/vp9_asm_dec_offsets.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - - -#include "vpx_ports/asm_offsets.h" -#include "vp9/decoder/vp9_onyxd_int.h" - -BEGIN - -END - -/* add asserts for any offset that is not supported by assembly code */ -/* add asserts for any size that is not supported by assembly code */ diff --git a/libvpx/vp9/decoder/vp9_dboolhuff.c b/libvpx/vp9/decoder/vp9_dboolhuff.c index df77d65..31b1ae2 100644 --- a/libvpx/vp9/decoder/vp9_dboolhuff.c +++ b/libvpx/vp9/decoder/vp9_dboolhuff.c @@ -13,6 +13,12 @@ #include "vp9/decoder/vp9_dboolhuff.h" +// This is meant to be a large, positive constant that can still be efficiently +// loaded as an immediate (on platforms like ARM, for example). +// Even relatively modest values like 100 would work fine. +#define VP9_LOTS_OF_BITS 0x40000000 + + int vp9_reader_init(vp9_reader *r, const uint8_t *buffer, size_t size) { int marker_bit; @@ -67,3 +73,20 @@ const uint8_t *vp9_reader_find_end(vp9_reader *r) { return r->buffer; } +int vp9_reader_has_error(vp9_reader *r) { + // Check if we have reached the end of the buffer. + // + // Variable 'count' stores the number of bits in the 'value' buffer, minus + // 8. The top byte is part of the algorithm, and the remainder is buffered + // to be shifted into it. So if count == 8, the top 16 bits of 'value' are + // occupied, 8 for the algorithm and 8 in the buffer. + // + // When reading a byte from the user's buffer, count is filled with 8 and + // one byte is filled into the value buffer. When we reach the end of the + // data, count is additionally filled with VP9_LOTS_OF_BITS. So when + // count == VP9_LOTS_OF_BITS - 1, the user's data has been exhausted. + // + // 1 if we have tried to decode bits after the end of stream was encountered. + // 0 No error. + return r->count > VP9_BD_VALUE_SIZE && r->count < VP9_LOTS_OF_BITS; +} diff --git a/libvpx/vp9/decoder/vp9_dboolhuff.h b/libvpx/vp9/decoder/vp9_dboolhuff.h index b50aa35..c46dd73 100644 --- a/libvpx/vp9/decoder/vp9_dboolhuff.h +++ b/libvpx/vp9/decoder/vp9_dboolhuff.h @@ -22,11 +22,6 @@ typedef size_t VP9_BD_VALUE; #define VP9_BD_VALUE_SIZE ((int)sizeof(VP9_BD_VALUE)*CHAR_BIT) -// This is meant to be a large, positive constant that can still be efficiently -// loaded as an immediate (on platforms like ARM, for example). -// Even relatively modest values like 100 would work fine. -#define VP9_LOTS_OF_BITS 0x40000000 - typedef struct { const uint8_t *buffer_end; const uint8_t *buffer; @@ -93,22 +88,6 @@ static int vp9_read_literal(vp9_reader *br, int bits) { return z; } -static int vp9_reader_has_error(vp9_reader *r) { - // Check if we have reached the end of the buffer. - // - // Variable 'count' stores the number of bits in the 'value' buffer, minus - // 8. The top byte is part of the algorithm, and the remainder is buffered - // to be shifted into it. So if count == 8, the top 16 bits of 'value' are - // occupied, 8 for the algorithm and 8 in the buffer. - // - // When reading a byte from the user's buffer, count is filled with 8 and - // one byte is filled into the value buffer. When we reach the end of the - // data, count is additionally filled with VP9_LOTS_OF_BITS. So when - // count == VP9_LOTS_OF_BITS - 1, the user's data has been exhausted. - // - // 1 if we have tried to decode bits after the end of stream was encountered. - // 0 No error. - return r->count > VP9_BD_VALUE_SIZE && r->count < VP9_LOTS_OF_BITS; -} +int vp9_reader_has_error(vp9_reader *r); #endif // VP9_DECODER_VP9_DBOOLHUFF_H_ diff --git a/libvpx/vp9/decoder/vp9_decodemv.c b/libvpx/vp9/decoder/vp9_decodemv.c index b3d41be..6f0044a 100644 --- a/libvpx/vp9/decoder/vp9_decodemv.c +++ b/libvpx/vp9/decoder/vp9_decodemv.c @@ -8,151 +8,188 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include -#include "vp9/decoder/vp9_treereader.h" -#include "vp9/common/vp9_entropymv.h" +#include "vp9/common/vp9_common.h" +#include "vp9/common/vp9_entropy.h" #include "vp9/common/vp9_entropymode.h" -#include "vp9/common/vp9_reconinter.h" -#include "vp9/decoder/vp9_onyxd_int.h" +#include "vp9/common/vp9_entropymv.h" #include "vp9/common/vp9_findnearmv.h" -#include "vp9/common/vp9_common.h" -#include "vp9/common/vp9_seg_common.h" +#include "vp9/common/vp9_mvref_common.h" #include "vp9/common/vp9_pred_common.h" -#include "vp9/common/vp9_entropy.h" +#include "vp9/common/vp9_reconinter.h" +#include "vp9/common/vp9_seg_common.h" + #include "vp9/decoder/vp9_decodemv.h" #include "vp9/decoder/vp9_decodframe.h" -#include "vp9/common/vp9_mvref_common.h" -#if CONFIG_DEBUG -#include -#endif +#include "vp9/decoder/vp9_onyxd_int.h" +#include "vp9/decoder/vp9_dsubexp.h" +#include "vp9/decoder/vp9_treereader.h" + +static MB_PREDICTION_MODE read_intra_mode(vp9_reader *r, const vp9_prob *p) { + return (MB_PREDICTION_MODE)treed_read(r, vp9_intra_mode_tree, p); +} -// #define DEBUG_DEC_MV -#ifdef DEBUG_DEC_MV -int dec_mvcount = 0; -#endif +static MB_PREDICTION_MODE read_inter_mode(vp9_reader *r, const vp9_prob *p) { + return (MB_PREDICTION_MODE)treed_read(r, vp9_inter_mode_tree, p); +} -// #define DEC_DEBUG -#ifdef DEC_DEBUG -extern int dec_debug; -#endif +static int read_segment_id(vp9_reader *r, const struct segmentation *seg) { + return treed_read(r, vp9_segment_tree, seg->tree_probs); +} -static MB_PREDICTION_MODE read_intra_mode(vp9_reader *r, const vp9_prob *p) { - MB_PREDICTION_MODE m = treed_read(r, vp9_intra_mode_tree, p); - return m; +static TX_SIZE read_selected_tx_size(VP9_COMMON *cm, MACROBLOCKD *xd, + BLOCK_SIZE_TYPE bsize, vp9_reader *r) { + const uint8_t context = vp9_get_pred_context_tx_size(xd); + const vp9_prob *tx_probs = get_tx_probs(bsize, context, &cm->fc.tx_probs); + TX_SIZE tx_size = vp9_read(r, tx_probs[0]); + if (tx_size != TX_4X4 && bsize >= BLOCK_SIZE_MB16X16) { + tx_size += vp9_read(r, tx_probs[1]); + if (tx_size != TX_8X8 && bsize >= BLOCK_SIZE_SB32X32) + tx_size += vp9_read(r, tx_probs[2]); + } + + update_tx_counts(bsize, context, tx_size, &cm->counts.tx); + return tx_size; } -static int read_mb_segid(vp9_reader *r, MACROBLOCKD *xd) { - return treed_read(r, vp9_segment_tree, xd->mb_segment_tree_probs); +static TX_SIZE read_tx_size(VP9D_COMP *pbi, TX_MODE tx_mode, + BLOCK_SIZE_TYPE bsize, int select_cond, + vp9_reader *r) { + VP9_COMMON *const cm = &pbi->common; + MACROBLOCKD *const xd = &pbi->mb; + + if (tx_mode == TX_MODE_SELECT && bsize >= BLOCK_SIZE_SB8X8 && select_cond) + return read_selected_tx_size(cm, xd, bsize, r); + else if (tx_mode >= ALLOW_32X32 && bsize >= BLOCK_SIZE_SB32X32) + return TX_32X32; + else if (tx_mode >= ALLOW_16X16 && bsize >= BLOCK_SIZE_MB16X16) + return TX_16X16; + else if (tx_mode >= ALLOW_8X8 && bsize >= BLOCK_SIZE_SB8X8) + return TX_8X8; + else + return TX_4X4; } -static void set_segment_id(VP9_COMMON *cm, MB_MODE_INFO *mbmi, +static void set_segment_id(VP9_COMMON *cm, BLOCK_SIZE_TYPE bsize, int mi_row, int mi_col, int segment_id) { - const int mi_index = mi_row * cm->mi_cols + mi_col; - const BLOCK_SIZE_TYPE sb_type = mbmi->sb_type; - const int bw = 1 << mi_width_log2(sb_type); - const int bh = 1 << mi_height_log2(sb_type); - const int ymis = MIN(cm->mi_rows - mi_row, bh); + const int mi_offset = mi_row * cm->mi_cols + mi_col; + const int bw = 1 << mi_width_log2(bsize); + const int bh = 1 << mi_height_log2(bsize); const int xmis = MIN(cm->mi_cols - mi_col, bw); + const int ymis = MIN(cm->mi_rows - mi_row, bh); int x, y; - for (y = 0; y < ymis; y++) { - for (x = 0; x < xmis; x++) { - const int index = mi_index + (y * cm->mi_cols + x); - cm->last_frame_seg_map[index] = segment_id; - } - } -} + assert(segment_id >= 0 && segment_id < MAX_SEGMENTS); -static TX_SIZE select_txfm_size(VP9_COMMON *cm, MACROBLOCKD *xd, - vp9_reader *r, BLOCK_SIZE_TYPE bsize) { - const int context = vp9_get_pred_context(cm, xd, PRED_TX_SIZE); - const vp9_prob *tx_probs = vp9_get_pred_probs(cm, xd, PRED_TX_SIZE); - TX_SIZE txfm_size = vp9_read(r, tx_probs[0]); - if (txfm_size != TX_4X4 && bsize >= BLOCK_SIZE_MB16X16) { - txfm_size += vp9_read(r, tx_probs[1]); - if (txfm_size != TX_8X8 && bsize >= BLOCK_SIZE_SB32X32) - txfm_size += vp9_read(r, tx_probs[2]); - } - if (bsize >= BLOCK_SIZE_SB32X32) { - cm->fc.tx_count_32x32p[context][txfm_size]++; - } else if (bsize >= BLOCK_SIZE_MB16X16) { - cm->fc.tx_count_16x16p[context][txfm_size]++; - } else { - cm->fc.tx_count_8x8p[context][txfm_size]++; - } - return txfm_size; + for (y = 0; y < ymis; y++) + for (x = 0; x < xmis; x++) + cm->last_frame_seg_map[mi_offset + y * cm->mi_cols + x] = segment_id; } +static int read_intra_segment_id(VP9D_COMP *pbi, int mi_row, int mi_col, + vp9_reader *r) { + MACROBLOCKD *const xd = &pbi->mb; + struct segmentation *const seg = &xd->seg; + const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type; + int segment_id; + + if (!seg->enabled) + return 0; // Default for disabled segmentation + + if (!seg->update_map) + return 0; -static void kfread_modes(VP9D_COMP *pbi, MODE_INFO *m, - int mi_row, int mi_col, - vp9_reader *r) { + segment_id = read_segment_id(r, seg); + set_segment_id(&pbi->common, bsize, mi_row, mi_col, segment_id); + return segment_id; +} + +static int read_inter_segment_id(VP9D_COMP *pbi, int mi_row, int mi_col, + vp9_reader *r) { VP9_COMMON *const cm = &pbi->common; MACROBLOCKD *const xd = &pbi->mb; - const int mis = cm->mode_info_stride; + struct segmentation *const seg = &xd->seg; + const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type; + int pred_segment_id, segment_id; - // Read segmentation map if it is being updated explicitly this frame - m->mbmi.segment_id = 0; - if (xd->segmentation_enabled && xd->update_mb_segmentation_map) { - m->mbmi.segment_id = read_mb_segid(r, xd); - set_segment_id(cm, &m->mbmi, mi_row, mi_col, m->mbmi.segment_id); - } + if (!seg->enabled) + return 0; // Default for disabled segmentation - m->mbmi.mb_skip_coeff = vp9_segfeature_active(xd, m->mbmi.segment_id, - SEG_LVL_SKIP); - if (!m->mbmi.mb_skip_coeff) { - m->mbmi.mb_skip_coeff = vp9_read(r, vp9_get_pred_prob(cm, xd, PRED_MBSKIP)); - cm->fc.mbskip_count[vp9_get_pred_context(cm, xd, PRED_MBSKIP)] - [m->mbmi.mb_skip_coeff]++; + pred_segment_id = vp9_get_segment_id(cm, cm->last_frame_seg_map, + bsize, mi_row, mi_col); + if (!seg->update_map) + return pred_segment_id; + + if (seg->temporal_update) { + const vp9_prob pred_prob = vp9_get_pred_prob_seg_id(xd); + const int pred_flag = vp9_read(r, pred_prob); + vp9_set_pred_flag_seg_id(cm, bsize, mi_row, mi_col, pred_flag); + segment_id = pred_flag ? pred_segment_id + : read_segment_id(r, seg); + } else { + segment_id = read_segment_id(r, seg); } + set_segment_id(cm, bsize, mi_row, mi_col, segment_id); + return segment_id; +} - if (cm->txfm_mode == TX_MODE_SELECT && - m->mbmi.sb_type >= BLOCK_SIZE_SB8X8) { - m->mbmi.txfm_size = select_txfm_size(cm, xd, r, m->mbmi.sb_type); - } else if (cm->txfm_mode >= ALLOW_32X32 && - m->mbmi.sb_type >= BLOCK_SIZE_SB32X32) { - m->mbmi.txfm_size = TX_32X32; - } else if (cm->txfm_mode >= ALLOW_16X16 && - m->mbmi.sb_type >= BLOCK_SIZE_MB16X16) { - m->mbmi.txfm_size = TX_16X16; - } else if (cm->txfm_mode >= ALLOW_8X8 && - m->mbmi.sb_type >= BLOCK_SIZE_SB8X8) { - m->mbmi.txfm_size = TX_8X8; - } else { - m->mbmi.txfm_size = TX_4X4; +static uint8_t read_skip_coeff(VP9D_COMP *pbi, int segment_id, vp9_reader *r) { + VP9_COMMON *const cm = &pbi->common; + MACROBLOCKD *const xd = &pbi->mb; + int skip_coeff = vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP); + if (!skip_coeff) { + const int ctx = vp9_get_pred_context_mbskip(xd); + skip_coeff = vp9_read(r, vp9_get_pred_prob_mbskip(cm, xd)); + cm->counts.mbskip[ctx][skip_coeff]++; } + return skip_coeff; +} - // luma mode - m->mbmi.ref_frame[0] = INTRA_FRAME; - if (m->mbmi.sb_type >= BLOCK_SIZE_SB8X8) { +static void read_intra_mode_info(VP9D_COMP *pbi, MODE_INFO *m, + int mi_row, int mi_col, vp9_reader *r) { + VP9_COMMON *const cm = &pbi->common; + MACROBLOCKD *const xd = &pbi->mb; + MB_MODE_INFO *const mbmi = &m->mbmi; + const BLOCK_SIZE_TYPE bsize = mbmi->sb_type; + const int mis = cm->mode_info_stride; + + mbmi->segment_id = read_intra_segment_id(pbi, mi_row, mi_col, r); + mbmi->mb_skip_coeff = read_skip_coeff(pbi, mbmi->segment_id, r); + mbmi->txfm_size = read_tx_size(pbi, cm->tx_mode, bsize, 1, r); + mbmi->ref_frame[0] = INTRA_FRAME; + + if (bsize >= BLOCK_SIZE_SB8X8) { const MB_PREDICTION_MODE A = above_block_mode(m, 0, mis); const MB_PREDICTION_MODE L = xd->left_available ? left_block_mode(m, 0) : DC_PRED; - m->mbmi.mode = read_intra_mode(r, cm->kf_y_mode_prob[A][L]); + mbmi->mode = read_intra_mode(r, vp9_kf_y_mode_prob[A][L]); } else { + // Only 4x4, 4x8, 8x4 blocks + const int bw = 1 << b_width_log2(bsize); + const int bh = 1 << b_height_log2(bsize); int idx, idy; - int bw = 1 << b_width_log2(m->mbmi.sb_type); - int bh = 1 << b_height_log2(m->mbmi.sb_type); for (idy = 0; idy < 2; idy += bh) { for (idx = 0; idx < 2; idx += bw) { - int ib = idy * 2 + idx; - int k; + const int ib = idy * 2 + idx; const MB_PREDICTION_MODE A = above_block_mode(m, ib, mis); const MB_PREDICTION_MODE L = (xd->left_available || idx) ? left_block_mode(m, ib) : DC_PRED; - m->bmi[ib].as_mode.first = - read_intra_mode(r, cm->kf_y_mode_prob[A][L]); - for (k = 1; k < bh; ++k) - m->bmi[ib + k * 2].as_mode.first = m->bmi[ib].as_mode.first; - for (k = 1; k < bw; ++k) - m->bmi[ib + k].as_mode.first = m->bmi[ib].as_mode.first; + const MB_PREDICTION_MODE b_mode = read_intra_mode(r, + vp9_kf_y_mode_prob[A][L]); + m->bmi[ib].as_mode = b_mode; + if (bh == 2) + m->bmi[ib + 2].as_mode = b_mode; + if (bw == 2) + m->bmi[ib + 1].as_mode = b_mode; } } - m->mbmi.mode = m->bmi[3].as_mode.first; + + mbmi->mode = m->bmi[3].as_mode; } - m->mbmi.uv_mode = read_intra_mode(r, cm->kf_uv_mode_prob[m->mbmi.mode]); + mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]); } static int read_mv_component(vp9_reader *r, @@ -161,9 +198,10 @@ static int read_mv_component(vp9_reader *r, int mag, d, fr, hp; const int sign = vp9_read(r, mvcomp->sign); const int mv_class = treed_read(r, vp9_mv_class_tree, mvcomp->classes); + const int class0 = mv_class == MV_CLASS_0; // Integer part - if (mv_class == MV_CLASS_0) { + if (class0) { d = treed_read(r, vp9_mv_class0_tree, mvcomp->class0); } else { int i; @@ -176,66 +214,77 @@ static int read_mv_component(vp9_reader *r, // Fractional part fr = treed_read(r, vp9_mv_fp_tree, - mv_class == MV_CLASS_0 ? mvcomp->class0_fp[d] : mvcomp->fp); + class0 ? mvcomp->class0_fp[d] : mvcomp->fp); // High precision part (if hp is not used, the default value of the hp is 1) - hp = usehp ? vp9_read(r, - mv_class == MV_CLASS_0 ? mvcomp->class0_hp : mvcomp->hp) + hp = usehp ? vp9_read(r, class0 ? mvcomp->class0_hp : mvcomp->hp) : 1; - // result + // Result mag = vp9_get_mv_mag(mv_class, (d << 3) | (fr << 1) | hp) + 1; return sign ? -mag : mag; } -static void update_nmv(vp9_reader *r, vp9_prob *const p, - const vp9_prob upd_p) { - if (vp9_read(r, upd_p)) { -#ifdef LOW_PRECISION_MV_UPDATE +static INLINE void read_mv(vp9_reader *r, MV *mv, const MV *ref, + const nmv_context *ctx, + nmv_context_counts *counts, int usehp) { + const MV_JOINT_TYPE j = treed_read(r, vp9_mv_joint_tree, ctx->joints); + MV diff = {0, 0}; + + usehp = usehp && vp9_use_mv_hp(ref); + if (mv_joint_vertical(j)) + diff.row = read_mv_component(r, &ctx->comps[0], usehp); + + if (mv_joint_horizontal(j)) + diff.col = read_mv_component(r, &ctx->comps[1], usehp); + + vp9_inc_mv(&diff, counts); + + mv->row = ref->row + diff.row; + mv->col = ref->col + diff.col; +} + +static void update_mv(vp9_reader *r, vp9_prob *p, vp9_prob upd_p) { + if (vp9_read(r, upd_p)) *p = (vp9_read_literal(r, 7) << 1) | 1; -#else - *p = (vp9_read_literal(r, 8)); -#endif - } } -static void read_nmvprobs(vp9_reader *r, nmv_context *mvctx, - int usehp) { +static void read_mv_probs(vp9_reader *r, nmv_context *mvc, int usehp) { int i, j, k; -#ifdef MV_GROUP_UPDATE - if (!vp9_read_bit(r)) - return; -#endif for (j = 0; j < MV_JOINTS - 1; ++j) - update_nmv(r, &mvctx->joints[j], VP9_NMV_UPDATE_PROB); + update_mv(r, &mvc->joints[j], VP9_NMV_UPDATE_PROB); for (i = 0; i < 2; ++i) { - update_nmv(r, &mvctx->comps[i].sign, VP9_NMV_UPDATE_PROB); + nmv_component *const comp = &mvc->comps[i]; + + update_mv(r, &comp->sign, VP9_NMV_UPDATE_PROB); for (j = 0; j < MV_CLASSES - 1; ++j) - update_nmv(r, &mvctx->comps[i].classes[j], VP9_NMV_UPDATE_PROB); + update_mv(r, &comp->classes[j], VP9_NMV_UPDATE_PROB); for (j = 0; j < CLASS0_SIZE - 1; ++j) - update_nmv(r, &mvctx->comps[i].class0[j], VP9_NMV_UPDATE_PROB); + update_mv(r, &comp->class0[j], VP9_NMV_UPDATE_PROB); for (j = 0; j < MV_OFFSET_BITS; ++j) - update_nmv(r, &mvctx->comps[i].bits[j], VP9_NMV_UPDATE_PROB); + update_mv(r, &comp->bits[j], VP9_NMV_UPDATE_PROB); } for (i = 0; i < 2; ++i) { + nmv_component *const comp = &mvc->comps[i]; + for (j = 0; j < CLASS0_SIZE; ++j) for (k = 0; k < 3; ++k) - update_nmv(r, &mvctx->comps[i].class0_fp[j][k], VP9_NMV_UPDATE_PROB); + update_mv(r, &comp->class0_fp[j][k], VP9_NMV_UPDATE_PROB); for (j = 0; j < 3; ++j) - update_nmv(r, &mvctx->comps[i].fp[j], VP9_NMV_UPDATE_PROB); + update_mv(r, &comp->fp[j], VP9_NMV_UPDATE_PROB); } if (usehp) { for (i = 0; i < 2; ++i) { - update_nmv(r, &mvctx->comps[i].class0_hp, VP9_NMV_UPDATE_PROB); - update_nmv(r, &mvctx->comps[i].hp, VP9_NMV_UPDATE_PROB); + update_mv(r, &mvc->comps[i].class0_hp, VP9_NMV_UPDATE_PROB); + update_mv(r, &mvc->comps[i].hp, VP9_NMV_UPDATE_PROB); } } } @@ -245,205 +294,71 @@ static void read_ref_frame(VP9D_COMP *pbi, vp9_reader *r, int segment_id, MV_REFERENCE_FRAME ref_frame[2]) { VP9_COMMON *const cm = &pbi->common; MACROBLOCKD *const xd = &pbi->mb; - const int seg_ref_active = vp9_segfeature_active(xd, segment_id, - SEG_LVL_REF_FRAME); + FRAME_CONTEXT *const fc = &cm->fc; + FRAME_COUNTS *const counts = &cm->counts; - // Segment reference frame features not available. - if (!seg_ref_active) { + if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME)) { + ref_frame[0] = vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_REF_FRAME); + ref_frame[1] = NONE; + } else { + const int comp_ctx = vp9_get_pred_context_comp_inter_inter(cm, xd); int is_comp; - int comp_ctx = vp9_get_pred_context(cm, xd, PRED_COMP_INTER_INTER); if (cm->comp_pred_mode == HYBRID_PREDICTION) { - is_comp = vp9_read(r, cm->fc.comp_inter_prob[comp_ctx]); - cm->fc.comp_inter_count[comp_ctx][is_comp]++; + is_comp = vp9_read(r, fc->comp_inter_prob[comp_ctx]); + counts->comp_inter[comp_ctx][is_comp]++; } else { is_comp = cm->comp_pred_mode == COMP_PREDICTION_ONLY; } // FIXME(rbultje) I'm pretty sure this breaks segmentation ref frame coding if (is_comp) { - int b, fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref]; - int ref_ctx = vp9_get_pred_context(cm, xd, PRED_COMP_REF_P); - - ref_frame[fix_ref_idx] = cm->comp_fixed_ref; - b = vp9_read(r, cm->fc.comp_ref_prob[ref_ctx]); - cm->fc.comp_ref_count[ref_ctx][b]++; + const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref]; + const int ref_ctx = vp9_get_pred_context_comp_ref_p(cm, xd); + const int b = vp9_read(r, fc->comp_ref_prob[ref_ctx]); + counts->comp_ref[ref_ctx][b]++; + ref_frame[fix_ref_idx] = cm->comp_fixed_ref; ref_frame[!fix_ref_idx] = cm->comp_var_ref[b]; } else { - int ref1_ctx = vp9_get_pred_context(cm, xd, PRED_SINGLE_REF_P1); + const int ref1_ctx = vp9_get_pred_context_single_ref_p1(xd); ref_frame[1] = NONE; - if (vp9_read(r, cm->fc.single_ref_prob[ref1_ctx][0])) { - int ref2_ctx = vp9_get_pred_context(cm, xd, PRED_SINGLE_REF_P2); - int b2 = vp9_read(r, cm->fc.single_ref_prob[ref2_ctx][1]); - ref_frame[0] = b2 ? ALTREF_FRAME : GOLDEN_FRAME; - cm->fc.single_ref_count[ref1_ctx][0][1]++; - cm->fc.single_ref_count[ref2_ctx][1][b2]++; + if (vp9_read(r, fc->single_ref_prob[ref1_ctx][0])) { + const int ref2_ctx = vp9_get_pred_context_single_ref_p2(xd); + const int b = vp9_read(r, fc->single_ref_prob[ref2_ctx][1]); + ref_frame[0] = b ? ALTREF_FRAME : GOLDEN_FRAME; + counts->single_ref[ref1_ctx][0][1]++; + counts->single_ref[ref2_ctx][1][b]++; } else { ref_frame[0] = LAST_FRAME; - cm->fc.single_ref_count[ref1_ctx][0][0]++; + counts->single_ref[ref1_ctx][0][0]++; } } - } else { - ref_frame[0] = vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME); - ref_frame[1] = NONE; } } -static MB_PREDICTION_MODE read_sb_mv_ref(vp9_reader *r, const vp9_prob *p) { - return (MB_PREDICTION_MODE) treed_read(r, vp9_sb_mv_ref_tree, p); -} - -#ifdef VPX_MODE_COUNT -unsigned int vp9_mv_cont_count[5][4] = { - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 } -}; -#endif - -static void read_switchable_interp_probs(VP9_COMMON* const cm, vp9_reader *r) { +static void read_switchable_interp_probs(FRAME_CONTEXT *fc, vp9_reader *r) { int i, j; - for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j) - for (i = 0; i < VP9_SWITCHABLE_FILTERS - 1; ++i) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) { - cm->fc.switchable_interp_prob[j][i] = - // vp9_read_prob(r); - vp9_read_prob_diff_update(r, cm->fc.switchable_interp_prob[j][i]); - } - } + for (j = 0; j < VP9_SWITCHABLE_FILTERS + 1; ++j) + for (i = 0; i < VP9_SWITCHABLE_FILTERS - 1; ++i) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &fc->switchable_interp_prob[j][i]); } -static void read_inter_mode_probs(VP9_COMMON *const cm, vp9_reader *r) { +static void read_inter_mode_probs(FRAME_CONTEXT *fc, vp9_reader *r) { int i, j; for (i = 0; i < INTER_MODE_CONTEXTS; ++i) - for (j = 0; j < VP9_INTER_MODES - 1; ++j) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) { - // cm->fc.inter_mode_probs[i][j] = vp9_read_prob(r); - cm->fc.inter_mode_probs[i][j] = - vp9_read_prob_diff_update(r, cm->fc.inter_mode_probs[i][j]); - } - } + for (j = 0; j < VP9_INTER_MODES - 1; ++j) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &fc->inter_mode_probs[i][j]); } static INLINE COMPPREDMODE_TYPE read_comp_pred_mode(vp9_reader *r) { COMPPREDMODE_TYPE mode = vp9_read_bit(r); if (mode) - mode += vp9_read_bit(r); + mode += vp9_read_bit(r); return mode; } -static void mb_mode_mv_init(VP9D_COMP *pbi, vp9_reader *r) { - VP9_COMMON *const cm = &pbi->common; - - if ((cm->frame_type != KEY_FRAME) && (!cm->intra_only)) { - nmv_context *const nmvc = &pbi->common.fc.nmvc; - MACROBLOCKD *const xd = &pbi->mb; - int i, j; - - read_inter_mode_probs(cm, r); - - if (cm->mcomp_filter_type == SWITCHABLE) - read_switchable_interp_probs(cm, r); - - for (i = 0; i < INTRA_INTER_CONTEXTS; i++) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) - cm->fc.intra_inter_prob[i] = - vp9_read_prob_diff_update(r, cm->fc.intra_inter_prob[i]); - } - - if (cm->allow_comp_inter_inter) { - cm->comp_pred_mode = read_comp_pred_mode(r); - if (cm->comp_pred_mode == HYBRID_PREDICTION) - for (i = 0; i < COMP_INTER_CONTEXTS; i++) - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) - cm->fc.comp_inter_prob[i] = - vp9_read_prob_diff_update(r, cm->fc.comp_inter_prob[i]); - } else { - cm->comp_pred_mode = SINGLE_PREDICTION_ONLY; - } - - if (cm->comp_pred_mode != COMP_PREDICTION_ONLY) - for (i = 0; i < REF_CONTEXTS; i++) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) - cm->fc.single_ref_prob[i][0] = - vp9_read_prob_diff_update(r, cm->fc.single_ref_prob[i][0]); - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) - cm->fc.single_ref_prob[i][1] = - vp9_read_prob_diff_update(r, cm->fc.single_ref_prob[i][1]); - } - - if (cm->comp_pred_mode != SINGLE_PREDICTION_ONLY) - for (i = 0; i < REF_CONTEXTS; i++) - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) - cm->fc.comp_ref_prob[i] = - vp9_read_prob_diff_update(r, cm->fc.comp_ref_prob[i]); - - // VP9_INTRA_MODES - for (j = 0; j < BLOCK_SIZE_GROUPS; j++) { - for (i = 0; i < VP9_INTRA_MODES - 1; ++i) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) { - cm->fc.y_mode_prob[j][i] = - vp9_read_prob_diff_update(r, cm->fc.y_mode_prob[j][i]); - } - } - } - for (j = 0; j < NUM_PARTITION_CONTEXTS; ++j) { - for (i = 0; i < PARTITION_TYPES - 1; ++i) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) { - cm->fc.partition_prob[INTER_FRAME][j][i] = - vp9_read_prob_diff_update(r, - cm->fc.partition_prob[INTER_FRAME][j][i]); - } - } - } - - read_nmvprobs(r, nmvc, xd->allow_high_precision_mv); - } -} - -// This function either reads the segment id for the current macroblock from -// the bitstream or if the value is temporally predicted asserts the predicted -// value -static int read_mb_segment_id(VP9D_COMP *pbi, int mi_row, int mi_col, - vp9_reader *r) { - VP9_COMMON *const cm = &pbi->common; - MACROBLOCKD *const xd = &pbi->mb; - MODE_INFO *const mi = xd->mode_info_context; - MB_MODE_INFO *const mbmi = &mi->mbmi; - - if (!xd->segmentation_enabled) - return 0; // Default for disabled segmentation - - if (xd->update_mb_segmentation_map) { - int segment_id; - - if (cm->temporal_update) { - // Temporal coding of the segment id for this mb is enabled. - // Get the context based probability for reading the - // prediction status flag - const vp9_prob pred_prob = vp9_get_pred_prob(cm, xd, PRED_SEG_ID); - const int pred_flag = vp9_read(r, pred_prob); - vp9_set_pred_flag(xd, PRED_SEG_ID, pred_flag); - - // If the value is flagged as correctly predicted - // then use the predicted value, otherwise decode it explicitly - segment_id = pred_flag ? vp9_get_pred_mi_segid(cm, mbmi->sb_type, - mi_row, mi_col) - : read_mb_segid(r, xd); - } else { - segment_id = read_mb_segid(r, xd); // Normal unpredicted coding mode - } - - set_segment_id(cm, mbmi, mi_row, mi_col, segment_id); // Side effect - return segment_id; - } else { - return vp9_get_pred_mi_segid(cm, mbmi->sb_type, mi_row, mi_col); - } -} - - static INLINE void assign_and_clamp_mv(int_mv *dst, const int_mv *src, int mb_to_left_edge, int mb_to_right_edge, @@ -454,242 +369,188 @@ static INLINE void assign_and_clamp_mv(int_mv *dst, const int_mv *src, mb_to_bottom_edge); } -static INLINE void decode_mv(vp9_reader *r, MV *mv, const MV *ref, - const nmv_context *ctx, - nmv_context_counts *counts, - int usehp) { - const MV_JOINT_TYPE j = treed_read(r, vp9_mv_joint_tree, ctx->joints); - MV diff = {0, 0}; - - usehp = usehp && vp9_use_nmv_hp(ref); - if (mv_joint_vertical(j)) - diff.row = read_mv_component(r, &ctx->comps[0], usehp); +static INLINE INTERPOLATIONFILTERTYPE read_switchable_filter_type( + VP9D_COMP *pbi, vp9_reader *r) { + VP9_COMMON *const cm = &pbi->common; + MACROBLOCKD *const xd = &pbi->mb; + const vp9_prob *probs = vp9_get_pred_probs_switchable_interp(cm, xd); + const int index = treed_read(r, vp9_switchable_interp_tree, probs); + const int ctx = vp9_get_pred_context_switchable_interp(xd); + ++cm->counts.switchable_interp[ctx][index]; + return vp9_switchable_interp[index]; +} - if (mv_joint_horizontal(j)) - diff.col = read_mv_component(r, &ctx->comps[1], usehp); +static void read_intra_block_modes(VP9D_COMP *pbi, MODE_INFO *mi, + vp9_reader *r) { + VP9_COMMON *const cm = &pbi->common; + MB_MODE_INFO *const mbmi = &mi->mbmi; + const BLOCK_SIZE_TYPE bsize = mi->mbmi.sb_type; + const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize); - vp9_increment_nmv(&diff, ref, counts, usehp); + if (bsize >= BLOCK_SIZE_SB8X8) { + const int size_group = MIN(3, MIN(bwl, bhl)); + mbmi->mode = read_intra_mode(r, cm->fc.y_mode_prob[size_group]); + cm->counts.y_mode[size_group][mbmi->mode]++; + } else { + // Only 4x4, 4x8, 8x4 blocks + const int bw = 1 << bwl, bh = 1 << bhl; + int idx, idy; + + for (idy = 0; idy < 2; idy += bh) { + for (idx = 0; idx < 2; idx += bw) { + const int ib = idy * 2 + idx; + const int b_mode = read_intra_mode(r, cm->fc.y_mode_prob[0]); + mi->bmi[ib].as_mode = b_mode; + cm->counts.y_mode[0][b_mode]++; + + if (bh == 2) + mi->bmi[ib + 2].as_mode = b_mode; + if (bw == 2) + mi->bmi[ib + 1].as_mode = b_mode; + } + } + mbmi->mode = mi->bmi[3].as_mode; + } - mv->row = diff.row + ref->row; - mv->col = diff.col + ref->col; + mbmi->uv_mode = read_intra_mode(r, cm->fc.uv_mode_prob[mbmi->mode]); + cm->counts.uv_mode[mbmi->mode][mbmi->uv_mode]++; } -static INLINE INTERPOLATIONFILTERTYPE read_switchable_filter_type( - VP9D_COMP *pbi, vp9_reader *r) { - const int index = treed_read(r, vp9_switchable_interp_tree, - vp9_get_pred_probs(&pbi->common, &pbi->mb, - PRED_SWITCHABLE_INTERP)); - ++pbi->common.fc.switchable_interp_count - [vp9_get_pred_context( - &pbi->common, &pbi->mb, PRED_SWITCHABLE_INTERP)][index]; - return vp9_switchable_interp[index]; +static MV_REFERENCE_FRAME read_reference_frame(VP9D_COMP *pbi, int segment_id, + vp9_reader *r) { + VP9_COMMON *const cm = &pbi->common; + MACROBLOCKD *const xd = &pbi->mb; + + MV_REFERENCE_FRAME ref; + if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME)) { + const int ctx = vp9_get_pred_context_intra_inter(xd); + ref = (MV_REFERENCE_FRAME) + vp9_read(r, vp9_get_pred_prob_intra_inter(cm, xd)); + cm->counts.intra_inter[ctx][ref != INTRA_FRAME]++; + } else { + ref = (MV_REFERENCE_FRAME) vp9_get_segdata(&xd->seg, segment_id, + SEG_LVL_REF_FRAME) != INTRA_FRAME; + } + return ref; } -static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, - int mi_row, int mi_col, - vp9_reader *r) { +static void read_inter_mode_info(VP9D_COMP *pbi, MODE_INFO *mi, + int mi_row, int mi_col, vp9_reader *r) { VP9_COMMON *const cm = &pbi->common; - nmv_context *const nmvc = &cm->fc.nmvc; MACROBLOCKD *const xd = &pbi->mb; + nmv_context *const nmvc = &cm->fc.nmvc; + MB_MODE_INFO *const mbmi = &mi->mbmi; int_mv *const mv0 = &mbmi->mv[0]; int_mv *const mv1 = &mbmi->mv[1]; - BLOCK_SIZE_TYPE bsize = mi->mbmi.sb_type; - int bw = 1 << b_width_log2(bsize); - int bh = 1 << b_height_log2(bsize); + const BLOCK_SIZE_TYPE bsize = mi->mbmi.sb_type; + const int bw = 1 << b_width_log2(bsize); + const int bh = 1 << b_height_log2(bsize); - int mb_to_left_edge, mb_to_right_edge, mb_to_top_edge, mb_to_bottom_edge; - int j, idx, idy; + int idx, idy; + mbmi->segment_id = read_inter_segment_id(pbi, mi_row, mi_col, r); + mbmi->mb_skip_coeff = read_skip_coeff(pbi, mbmi->segment_id, r); + mbmi->ref_frame[0] = read_reference_frame(pbi, mbmi->segment_id, r); mbmi->ref_frame[1] = NONE; + mbmi->txfm_size = read_tx_size(pbi, cm->tx_mode, bsize, + (!mbmi->mb_skip_coeff || mbmi->ref_frame[0] == INTRA_FRAME), r); - // Make sure the MACROBLOCKD mode info pointer is pointed at the - // correct entry for the current macroblock. - xd->mode_info_context = mi; - - // Distance of Mb to the various image edges. - // These specified to 8th pel as they are always compared to MV values - // that are in 1/8th pel units - set_mi_row_col(cm, xd, mi_row, 1 << mi_height_log2(bsize), - mi_col, 1 << mi_width_log2(bsize)); - - mb_to_top_edge = xd->mb_to_top_edge - LEFT_TOP_MARGIN; - mb_to_bottom_edge = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN; - mb_to_left_edge = xd->mb_to_left_edge - LEFT_TOP_MARGIN; - mb_to_right_edge = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN; - - // Read the macroblock segment id. - mbmi->segment_id = read_mb_segment_id(pbi, mi_row, mi_col, r); - - mbmi->mb_skip_coeff = vp9_segfeature_active(xd, mbmi->segment_id, - SEG_LVL_SKIP); - if (!mbmi->mb_skip_coeff) { - mbmi->mb_skip_coeff = vp9_read(r, vp9_get_pred_prob(cm, xd, PRED_MBSKIP)); - cm->fc.mbskip_count[vp9_get_pred_context(cm, xd, PRED_MBSKIP)] - [mbmi->mb_skip_coeff]++; - } - - // Read the reference frame - if (!vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_REF_FRAME)) { - mbmi->ref_frame[0] = - vp9_read(r, vp9_get_pred_prob(cm, xd, PRED_INTRA_INTER)); - cm->fc.intra_inter_count[vp9_get_pred_context(cm, xd, PRED_INTRA_INTER)] - [mbmi->ref_frame[0] != INTRA_FRAME]++; - } else { - mbmi->ref_frame[0] = - vp9_get_segdata(xd, mbmi->segment_id, SEG_LVL_REF_FRAME) != INTRA_FRAME; - } - - if (cm->txfm_mode == TX_MODE_SELECT && - (mbmi->mb_skip_coeff == 0 || mbmi->ref_frame[0] == INTRA_FRAME) && - bsize >= BLOCK_SIZE_SB8X8) { - mbmi->txfm_size = select_txfm_size(cm, xd, r, bsize); - } else if (bsize >= BLOCK_SIZE_SB32X32 && - cm->txfm_mode >= ALLOW_32X32) { - mbmi->txfm_size = TX_32X32; - } else if (cm->txfm_mode >= ALLOW_16X16 && - bsize >= BLOCK_SIZE_MB16X16) { - mbmi->txfm_size = TX_16X16; - } else if (cm->txfm_mode >= ALLOW_8X8 && (bsize >= BLOCK_SIZE_SB8X8)) { - mbmi->txfm_size = TX_8X8; - } else { - mbmi->txfm_size = TX_4X4; - } - - // If reference frame is an Inter frame if (mbmi->ref_frame[0] != INTRA_FRAME) { int_mv nearest, nearby, best_mv; int_mv nearest_second, nearby_second, best_mv_second; vp9_prob *mv_ref_p; + MV_REFERENCE_FRAME ref0, ref1; read_ref_frame(pbi, r, mbmi->segment_id, mbmi->ref_frame); + ref0 = mbmi->ref_frame[0]; + ref1 = mbmi->ref_frame[1]; - { -#ifdef DEC_DEBUG - if (dec_debug) - printf("%d %d\n", xd->mode_info_context->mbmi.mv[0].as_mv.row, - xd->mode_info_context->mbmi.mv[0].as_mv.col); -#endif - vp9_find_mv_refs(cm, xd, mi, xd->prev_mode_info_context, - mbmi->ref_frame[0], mbmi->ref_mvs[mbmi->ref_frame[0]], - cm->ref_frame_sign_bias); - - mv_ref_p = cm->fc.inter_mode_probs[ - mbmi->mb_mode_context[mbmi->ref_frame[0]]]; - - // If the segment level skip mode enabled - if (vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP)) { - mbmi->mode = ZEROMV; - } else if (bsize >= BLOCK_SIZE_SB8X8) { - mbmi->mode = read_sb_mv_ref(r, mv_ref_p); - vp9_accum_mv_refs(cm, mbmi->mode, - mbmi->mb_mode_context[mbmi->ref_frame[0]]); - } + vp9_find_mv_refs(cm, xd, mi, xd->prev_mode_info_context, + ref0, mbmi->ref_mvs[ref0], cm->ref_frame_sign_bias); - if (bsize < BLOCK_SIZE_SB8X8 || mbmi->mode != ZEROMV) { - vp9_find_best_ref_mvs(xd, - mbmi->ref_mvs[mbmi->ref_frame[0]], - &nearest, &nearby); + mv_ref_p = cm->fc.inter_mode_probs[mbmi->mb_mode_context[ref0]]; - best_mv.as_int = mbmi->ref_mvs[mbmi->ref_frame[0]][0].as_int; - } + if (vp9_segfeature_active(&xd->seg, mbmi->segment_id, SEG_LVL_SKIP)) { + mbmi->mode = ZEROMV; + } else if (bsize >= BLOCK_SIZE_SB8X8) { + mbmi->mode = read_inter_mode(r, mv_ref_p); + vp9_accum_mv_refs(cm, mbmi->mode, mbmi->mb_mode_context[ref0]); + } + mbmi->uv_mode = DC_PRED; -#ifdef DEC_DEBUG - if (dec_debug) - printf("[D %d %d] %d %d %d %d\n", ref_frame, - mbmi->mb_mode_context[ref_frame], - mv_ref_p[0], mv_ref_p[1], mv_ref_p[2], mv_ref_p[3]); -#endif + // nearest, nearby + if (bsize < BLOCK_SIZE_SB8X8 || mbmi->mode != ZEROMV) { + vp9_find_best_ref_mvs(xd, mbmi->ref_mvs[ref0], &nearest, &nearby); + best_mv.as_int = mbmi->ref_mvs[ref0][0].as_int; } mbmi->interp_filter = cm->mcomp_filter_type == SWITCHABLE ? read_switchable_filter_type(pbi, r) : cm->mcomp_filter_type; - if (mbmi->ref_frame[1] > INTRA_FRAME) { + if (ref1 > INTRA_FRAME) { vp9_find_mv_refs(cm, xd, mi, xd->prev_mode_info_context, - mbmi->ref_frame[1], - mbmi->ref_mvs[mbmi->ref_frame[1]], - cm->ref_frame_sign_bias); + ref1, mbmi->ref_mvs[ref1], cm->ref_frame_sign_bias); if (bsize < BLOCK_SIZE_SB8X8 || mbmi->mode != ZEROMV) { - vp9_find_best_ref_mvs(xd, - mbmi->ref_mvs[mbmi->ref_frame[1]], - &nearest_second, - &nearby_second); - best_mv_second.as_int = mbmi->ref_mvs[mbmi->ref_frame[1]][0].as_int; + vp9_find_best_ref_mvs(xd, mbmi->ref_mvs[ref1], + &nearest_second, &nearby_second); + best_mv_second.as_int = mbmi->ref_mvs[ref1][0].as_int; } } - mbmi->uv_mode = DC_PRED; + if (mbmi->sb_type < BLOCK_SIZE_SB8X8) { for (idy = 0; idy < 2; idy += bh) { for (idx = 0; idx < 2; idx += bw) { int_mv blockmv, secondmv; - int blockmode; - int i; - j = idy * 2 + idx; + const int j = idy * 2 + idx; + const int blockmode = read_inter_mode(r, mv_ref_p); - blockmode = read_sb_mv_ref(r, mv_ref_p); - vp9_accum_mv_refs(cm, blockmode, - mbmi->mb_mode_context[mbmi->ref_frame[0]]); + vp9_accum_mv_refs(cm, blockmode, mbmi->mb_mode_context[ref0]); if (blockmode == NEARESTMV || blockmode == NEARMV) { - MV_REFERENCE_FRAME rf2 = mbmi->ref_frame[1]; vp9_append_sub8x8_mvs_for_idx(cm, xd, &nearest, &nearby, j, 0); - if (rf2 > 0) { + if (ref1 > 0) vp9_append_sub8x8_mvs_for_idx(cm, xd, &nearest_second, &nearby_second, j, 1); - } } switch (blockmode) { case NEWMV: - decode_mv(r, &blockmv.as_mv, &best_mv.as_mv, nmvc, - &cm->fc.NMVcount, xd->allow_high_precision_mv); + read_mv(r, &blockmv.as_mv, &best_mv.as_mv, nmvc, + &cm->counts.mv, xd->allow_high_precision_mv); - if (mbmi->ref_frame[1] > 0) - decode_mv(r, &secondmv.as_mv, &best_mv_second.as_mv, nmvc, - &cm->fc.NMVcount, xd->allow_high_precision_mv); - -#ifdef VPX_MODE_COUNT - vp9_mv_cont_count[mv_contz][3]++; -#endif + if (ref1 > 0) + read_mv(r, &secondmv.as_mv, &best_mv_second.as_mv, nmvc, + &cm->counts.mv, xd->allow_high_precision_mv); break; case NEARESTMV: blockmv.as_int = nearest.as_int; - if (mbmi->ref_frame[1] > 0) + if (ref1 > 0) secondmv.as_int = nearest_second.as_int; -#ifdef VPX_MODE_COUNT - vp9_mv_cont_count[mv_contz][0]++; -#endif break; case NEARMV: blockmv.as_int = nearby.as_int; - if (mbmi->ref_frame[1] > 0) + if (ref1 > 0) secondmv.as_int = nearby_second.as_int; -#ifdef VPX_MODE_COUNT - vp9_mv_cont_count[mv_contz][1]++; -#endif break; case ZEROMV: blockmv.as_int = 0; - if (mbmi->ref_frame[1] > 0) + if (ref1 > 0) secondmv.as_int = 0; -#ifdef VPX_MODE_COUNT - vp9_mv_cont_count[mv_contz][2]++; -#endif break; default: - break; + assert(!"Invalid inter mode value"); } mi->bmi[j].as_mv[0].as_int = blockmv.as_int; - if (mbmi->ref_frame[1] > 0) + if (ref1 > 0) mi->bmi[j].as_mv[1].as_int = secondmv.as_int; - for (i = 1; i < bh; ++i) - vpx_memcpy(&mi->bmi[j + i * 2], &mi->bmi[j], sizeof(mi->bmi[j])); - for (i = 1; i < bw; ++i) - vpx_memcpy(&mi->bmi[j + i], &mi->bmi[j], sizeof(mi->bmi[j])); + if (bh == 2) + mi->bmi[j + 2] = mi->bmi[j]; + if (bw == 2) + mi->bmi[j + 1] = mi->bmi[j]; mi->mbmi.mode = blockmode; } } @@ -697,6 +558,11 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mv0->as_int = mi->bmi[3].as_mv[0].as_int; mv1->as_int = mi->bmi[3].as_mv[1].as_int; } else { + const int mb_to_top_edge = xd->mb_to_top_edge - LEFT_TOP_MARGIN; + const int mb_to_bottom_edge = xd->mb_to_bottom_edge + RIGHT_BOTTOM_MARGIN; + const int mb_to_left_edge = xd->mb_to_left_edge - LEFT_TOP_MARGIN; + const int mb_to_right_edge = xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN; + switch (mbmi->mode) { case NEARMV: // Clip "next_nearest" so that it does not extend to far out of image @@ -704,7 +570,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mb_to_right_edge, mb_to_top_edge, mb_to_bottom_edge); - if (mbmi->ref_frame[1] > 0) + if (ref1 > 0) assign_and_clamp_mv(mv1, &nearby_second, mb_to_left_edge, mb_to_right_edge, mb_to_top_edge, @@ -717,7 +583,7 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mb_to_right_edge, mb_to_top_edge, mb_to_bottom_edge); - if (mbmi->ref_frame[1] > 0) + if (ref1 > 0) assign_and_clamp_mv(mv1, &nearest_second, mb_to_left_edge, mb_to_right_edge, mb_to_top_edge, @@ -726,98 +592,109 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, case ZEROMV: mv0->as_int = 0; - if (mbmi->ref_frame[1] > 0) + if (ref1 > 0) mv1->as_int = 0; break; case NEWMV: - decode_mv(r, &mv0->as_mv, &best_mv.as_mv, nmvc, &cm->fc.NMVcount, - xd->allow_high_precision_mv); - if (mbmi->ref_frame[1] > 0) - decode_mv(r, &mv1->as_mv, &best_mv_second.as_mv, nmvc, - &cm->fc.NMVcount, xd->allow_high_precision_mv); + read_mv(r, &mv0->as_mv, &best_mv.as_mv, nmvc, &cm->counts.mv, + xd->allow_high_precision_mv); + if (ref1 > 0) + read_mv(r, &mv1->as_mv, &best_mv_second.as_mv, nmvc, + &cm->counts.mv, xd->allow_high_precision_mv); break; default: -#if CONFIG_DEBUG - assert(0); -#endif - break; + assert(!"Invalid inter mode value"); } } } else { - // required for left and above block mv - mv0->as_int = 0; - - if (bsize >= BLOCK_SIZE_SB8X8) { - const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type; - const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize); - const int bsl = MIN(bwl, bhl); - mbmi->mode = read_intra_mode(r, cm->fc.y_mode_prob[MIN(3, bsl)]); - cm->fc.y_mode_counts[MIN(3, bsl)][mbmi->mode]++; - } else { - int idx, idy; - for (idy = 0; idy < 2; idy += bh) { - for (idx = 0; idx < 2; idx += bw) { - int ib = idy * 2 + idx, k; - int m = read_intra_mode(r, cm->fc.y_mode_prob[0]); - mi->bmi[ib].as_mode.first = m; - cm->fc.y_mode_counts[0][m]++; - for (k = 1; k < bh; ++k) - mi->bmi[ib + k * 2].as_mode.first = m; - for (k = 1; k < bw; ++k) - mi->bmi[ib + k].as_mode.first = m; - } - } - mbmi->mode = mi->bmi[3].as_mode.first; + mv0->as_int = 0; // required for left and above block mv + read_intra_block_modes(pbi, mi, r); + } +} + +static void read_comp_pred(VP9_COMMON *cm, vp9_reader *r) { + int i; + + cm->comp_pred_mode = cm->allow_comp_inter_inter ? read_comp_pred_mode(r) + : SINGLE_PREDICTION_ONLY; + + if (cm->comp_pred_mode == HYBRID_PREDICTION) + for (i = 0; i < COMP_INTER_CONTEXTS; i++) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &cm->fc.comp_inter_prob[i]); + + if (cm->comp_pred_mode != COMP_PREDICTION_ONLY) + for (i = 0; i < REF_CONTEXTS; i++) { + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &cm->fc.single_ref_prob[i][0]); + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &cm->fc.single_ref_prob[i][1]); } - mbmi->uv_mode = read_intra_mode(r, cm->fc.uv_mode_prob[mbmi->mode]); - cm->fc.uv_mode_counts[mbmi->mode][mbmi->uv_mode]++; - } + if (cm->comp_pred_mode != SINGLE_PREDICTION_ONLY) + for (i = 0; i < REF_CONTEXTS; i++) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &cm->fc.comp_ref_prob[i]); } -void vp9_decode_mode_mvs_init(VP9D_COMP* const pbi, vp9_reader *r) { - VP9_COMMON *cm = &pbi->common; +void vp9_prepare_read_mode_info(VP9D_COMP* pbi, vp9_reader *r) { + VP9_COMMON *const cm = &pbi->common; int k; // TODO(jkoleszar): does this clear more than MBSKIP_CONTEXTS? Maybe remove. // vpx_memset(cm->fc.mbskip_probs, 0, sizeof(cm->fc.mbskip_probs)); - for (k = 0; k < MBSKIP_CONTEXTS; ++k) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) { - cm->fc.mbskip_probs[k] = - vp9_read_prob_diff_update(r, cm->fc.mbskip_probs[k]); - } - // cm->fc.mbskip_probs[k] = vp9_read_prob(r); - } + for (k = 0; k < MBSKIP_CONTEXTS; ++k) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &cm->fc.mbskip_probs[k]); + + if (cm->frame_type != KEY_FRAME && !cm->intra_only) { + nmv_context *const nmvc = &pbi->common.fc.nmvc; + MACROBLOCKD *const xd = &pbi->mb; + int i, j; + + read_inter_mode_probs(&cm->fc, r); - mb_mode_mv_init(pbi, r); + if (cm->mcomp_filter_type == SWITCHABLE) + read_switchable_interp_probs(&cm->fc, r); + + for (i = 0; i < INTRA_INTER_CONTEXTS; i++) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &cm->fc.intra_inter_prob[i]); + + read_comp_pred(cm, r); + + for (j = 0; j < BLOCK_SIZE_GROUPS; j++) + for (i = 0; i < VP9_INTRA_MODES - 1; ++i) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &cm->fc.y_mode_prob[j][i]); + + for (j = 0; j < NUM_PARTITION_CONTEXTS; ++j) + for (i = 0; i < PARTITION_TYPES - 1; ++i) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &cm->fc.partition_prob[INTER_FRAME][j][i]); + + read_mv_probs(r, nmvc, xd->allow_high_precision_mv); + } } -void vp9_decode_mb_mode_mv(VP9D_COMP* const pbi, - MACROBLOCKD* const xd, - int mi_row, - int mi_col, - vp9_reader *r) { +void vp9_read_mode_info(VP9D_COMP* pbi, int mi_row, int mi_col, vp9_reader *r) { VP9_COMMON *const cm = &pbi->common; + MACROBLOCKD *const xd = &pbi->mb; MODE_INFO *mi = xd->mode_info_context; - MB_MODE_INFO *const mbmi = &mi->mbmi; + const BLOCK_SIZE_TYPE bsize = mi->mbmi.sb_type; + const int bw = 1 << mi_width_log2(bsize); + const int bh = 1 << mi_height_log2(bsize); + const int y_mis = MIN(bh, cm->mi_rows - mi_row); + const int x_mis = MIN(bw, cm->mi_cols - mi_col); + int x, y; - if ((cm->frame_type == KEY_FRAME) || cm->intra_only) { - kfread_modes(pbi, mi, mi_row, mi_col, r); - } else { - read_mb_modes_mv(pbi, mi, &mi->mbmi, mi_row, mi_col, r); - } + if (cm->frame_type == KEY_FRAME || cm->intra_only) + read_intra_mode_info(pbi, mi, mi_row, mi_col, r); + else + read_inter_mode_info(pbi, mi, mi_row, mi_col, r); - if (1) { - const int bw = 1 << mi_width_log2(mbmi->sb_type); - const int bh = 1 << mi_height_log2(mbmi->sb_type); - const int y_mis = MIN(bh, cm->mi_rows - mi_row); - const int x_mis = MIN(bw, cm->mi_cols - mi_col); - const int mis = cm->mode_info_stride; - int x, y; - - for (y = 0; y < y_mis; y++) - for (x = !y; x < x_mis; x++) - mi[y * mis + x] = *mi; - } + for (y = 0; y < y_mis; y++) + for (x = !y; x < x_mis; x++) + mi[y * cm->mode_info_stride + x] = *mi; } diff --git a/libvpx/vp9/decoder/vp9_decodemv.h b/libvpx/vp9/decoder/vp9_decodemv.h index bf5e83c..4073d9e 100644 --- a/libvpx/vp9/decoder/vp9_decodemv.h +++ b/libvpx/vp9/decoder/vp9_decodemv.h @@ -13,11 +13,8 @@ #include "vp9/decoder/vp9_onyxd_int.h" -void vp9_decode_mb_mode_mv(VP9D_COMP* const pbi, - MACROBLOCKD* const xd, - int mb_row, - int mb_col, - vp9_reader *r); -void vp9_decode_mode_mvs_init(VP9D_COMP* const pbi, vp9_reader *r); +void vp9_prepare_read_mode_info(VP9D_COMP* pbi, vp9_reader *r); + +void vp9_read_mode_info(VP9D_COMP* pbi, int mi_row, int mi_col, vp9_reader *r); #endif // VP9_DECODER_VP9_DECODEMV_H_ diff --git a/libvpx/vp9/decoder/vp9_decodframe.c b/libvpx/vp9/decoder/vp9_decodframe.c index 49b181d..ffec8ea 100644 --- a/libvpx/vp9/decoder/vp9_decodframe.c +++ b/libvpx/vp9/decoder/vp9_decodframe.c @@ -14,15 +14,15 @@ #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_alloccommon.h" #include "vp9/common/vp9_common.h" -#include "vp9/common/vp9_reconintra.h" -#include "vp9/common/vp9_reconinter.h" #include "vp9/common/vp9_entropy.h" -#include "vp9/common/vp9_alloccommon.h" #include "vp9/common/vp9_entropymode.h" +#include "vp9/common/vp9_extend.h" +#include "vp9/common/vp9_pred_common.h" #include "vp9/common/vp9_quant_common.h" +#include "vp9/common/vp9_reconintra.h" +#include "vp9/common/vp9_reconinter.h" #include "vp9/common/vp9_seg_common.h" #include "vp9/common/vp9_tile_common.h" @@ -30,169 +30,58 @@ #include "vp9/decoder/vp9_decodframe.h" #include "vp9/decoder/vp9_detokenize.h" #include "vp9/decoder/vp9_decodemv.h" +#include "vp9/decoder/vp9_dsubexp.h" #include "vp9/decoder/vp9_onyxd_int.h" #include "vp9/decoder/vp9_read_bit_buffer.h" - -// #define DEC_DEBUG -#ifdef DEC_DEBUG -int dec_debug = 0; -#endif - static int read_be32(const uint8_t *p) { return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; } // len == 0 is not allowed -static int read_is_valid(const uint8_t *start, size_t len, - const uint8_t *end) { +static int read_is_valid(const uint8_t *start, size_t len, const uint8_t *end) { return start + len > start && start + len <= end; } -static void setup_txfm_mode(VP9_COMMON *pc, int lossless, vp9_reader *r) { - if (lossless) { - pc->txfm_mode = ONLY_4X4; - } else { - pc->txfm_mode = vp9_read_literal(r, 2); - if (pc->txfm_mode == ALLOW_32X32) - pc->txfm_mode += vp9_read_bit(r); - if (pc->txfm_mode == TX_MODE_SELECT) { - int i, j; - for (i = 0; i < TX_SIZE_CONTEXTS; ++i) { - for (j = 0; j < TX_SIZE_MAX_SB - 3; ++j) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) - pc->fc.tx_probs_8x8p[i][j] = - vp9_read_prob_diff_update(r, pc->fc.tx_probs_8x8p[i][j]); - } - } - for (i = 0; i < TX_SIZE_CONTEXTS; ++i) { - for (j = 0; j < TX_SIZE_MAX_SB - 2; ++j) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) - pc->fc.tx_probs_16x16p[i][j] = - vp9_read_prob_diff_update(r, pc->fc.tx_probs_16x16p[i][j]); - } - } - for (i = 0; i < TX_SIZE_CONTEXTS; ++i) { - for (j = 0; j < TX_SIZE_MAX_SB - 1; ++j) { - if (vp9_read(r, VP9_MODE_UPDATE_PROB)) - pc->fc.tx_probs_32x32p[i][j] = - vp9_read_prob_diff_update(r, pc->fc.tx_probs_32x32p[i][j]); - } - } - } - } -} - -static int get_unsigned_bits(unsigned int num_values) { - int cat = 0; - if (num_values <= 1) - return 0; - num_values--; - while (num_values > 0) { - cat++; - num_values >>= 1; - } - return cat; -} - -static int inv_recenter_nonneg(int v, int m) { - if (v > 2 * m) - return v; - - return v % 2 ? m - (v + 1) / 2 : m + v / 2; -} - -static int decode_uniform(vp9_reader *r, int n) { - int v; - const int l = get_unsigned_bits(n); - const int m = (1 << l) - n; - if (!l) - return 0; - - v = vp9_read_literal(r, l - 1); - return v < m ? v : (v << 1) - m + vp9_read_bit(r); -} - -static int decode_term_subexp(vp9_reader *r, int k, int num_syms) { - int i = 0, mk = 0, word; - while (1) { - const int b = i ? k + i - 1 : k; - const int a = 1 << b; - if (num_syms <= mk + 3 * a) { - word = decode_uniform(r, num_syms - mk) + mk; - break; - } else { - if (vp9_read_bit(r)) { - i++; - mk += a; - } else { - word = vp9_read_literal(r, b) + mk; - break; - } - } - } - return word; -} - static int decode_unsigned_max(struct vp9_read_bit_buffer *rb, int max) { const int data = vp9_rb_read_literal(rb, get_unsigned_bits(max)); return data > max ? max : data; } -static int merge_index(int v, int n, int modulus) { - int max1 = (n - 1 - modulus / 2) / modulus + 1; - if (v < max1) { - v = v * modulus + modulus / 2; - } else { - int w; - v -= max1; - w = v; - v += (v + modulus - modulus / 2) / modulus; - while (v % modulus == modulus / 2 || - w != v - (v + modulus - modulus / 2) / modulus) v++; - } - return v; -} - -static int inv_remap_prob(int v, int m) { - const int n = 255; - - v = merge_index(v, n - 1, MODULUS_PARAM); - m--; - if ((m << 1) <= n) { - return 1 + inv_recenter_nonneg(v + 1, m); - } else { - return n - inv_recenter_nonneg(v + 1, n - 1 - m); - } +static TX_MODE read_tx_mode(vp9_reader *r) { + TX_MODE tx_mode = vp9_read_literal(r, 2); + if (tx_mode == ALLOW_32X32) + tx_mode += vp9_read_bit(r); + return tx_mode; } -vp9_prob vp9_read_prob_diff_update(vp9_reader *r, int oldp) { - int delp = decode_term_subexp(r, SUBEXP_PARAM, 255); - return (vp9_prob)inv_remap_prob(delp, oldp); -} +static void read_tx_probs(struct tx_probs *tx_probs, vp9_reader *r) { + int i, j; -void vp9_init_dequantizer(VP9_COMMON *pc) { - int q; + for (i = 0; i < TX_SIZE_CONTEXTS; ++i) + for (j = 0; j < TX_SIZE_MAX_SB - 3; ++j) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &tx_probs->p8x8[i][j]); - for (q = 0; q < QINDEX_RANGE; q++) { - // DC value - pc->y_dequant[q][0] = vp9_dc_quant(q, pc->y_dc_delta_q); - pc->uv_dequant[q][0] = vp9_dc_quant(q, pc->uv_dc_delta_q); + for (i = 0; i < TX_SIZE_CONTEXTS; ++i) + for (j = 0; j < TX_SIZE_MAX_SB - 2; ++j) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &tx_probs->p16x16[i][j]); - // AC values - pc->y_dequant[q][1] = vp9_ac_quant(q, 0); - pc->uv_dequant[q][1] = vp9_ac_quant(q, pc->uv_ac_delta_q); - } + for (i = 0; i < TX_SIZE_CONTEXTS; ++i) + for (j = 0; j < TX_SIZE_MAX_SB - 1; ++j) + if (vp9_read(r, VP9_MODE_UPDATE_PROB)) + vp9_diff_update_prob(r, &tx_probs->p32x32[i][j]); } -static void mb_init_dequantizer(VP9_COMMON *pc, MACROBLOCKD *xd) { +static void init_dequantizer(VP9_COMMON *cm, MACROBLOCKD *xd) { int i; const int segment_id = xd->mode_info_context->mbmi.segment_id; - xd->q_index = vp9_get_qindex(xd, segment_id, pc->base_qindex); + xd->q_index = vp9_get_qindex(xd, segment_id, cm->base_qindex); - xd->plane[0].dequant = pc->y_dequant[xd->q_index]; + xd->plane[0].dequant = cm->y_dequant[xd->q_index]; for (i = 1; i < MAX_MB_PLANE; i++) - xd->plane[i].dequant = pc->uv_dequant[xd->q_index]; + xd->plane[i].dequant = cm->uv_dequant[xd->q_index]; } static void decode_block(int plane, int block, BLOCK_SIZE_TYPE bsize, @@ -201,32 +90,32 @@ static void decode_block(int plane, int block, BLOCK_SIZE_TYPE bsize, struct macroblockd_plane *pd = &xd->plane[plane]; int16_t* const qcoeff = BLOCK_OFFSET(pd->qcoeff, block, 16); const int stride = pd->dst.stride; + const int eob = pd->eobs[block]; const int raster_block = txfrm_block_to_raster_block(xd, bsize, plane, block, ss_txfrm_size); uint8_t* const dst = raster_block_offset_uint8(xd, bsize, plane, raster_block, pd->dst.buf, stride); - TX_TYPE tx_type; - switch (ss_txfrm_size / 2) { - case TX_4X4: - tx_type = plane == 0 ? get_tx_type_4x4(xd, raster_block) : DCT_DCT; + case TX_4X4: { + const TX_TYPE tx_type = get_tx_type_4x4(pd->plane_type, xd, raster_block); if (tx_type == DCT_DCT) - xd->itxm_add(qcoeff, dst, stride, pd->eobs[block]); + xd->itxm_add(qcoeff, dst, stride, eob); else - vp9_iht_add_c(tx_type, qcoeff, dst, stride, pd->eobs[block]); + vp9_iht_add_c(tx_type, qcoeff, dst, stride, eob); break; + } case TX_8X8: - tx_type = plane == 0 ? get_tx_type_8x8(xd, raster_block) : DCT_DCT; - vp9_iht_add_8x8_c(tx_type, qcoeff, dst, stride, pd->eobs[block]); + vp9_iht_add_8x8_c(get_tx_type_8x8(pd->plane_type, xd), qcoeff, dst, + stride, eob); break; case TX_16X16: - tx_type = plane == 0 ? get_tx_type_16x16(xd, raster_block) : DCT_DCT; - vp9_iht_add_16x16_c(tx_type, qcoeff, dst, stride, pd->eobs[block]); + vp9_iht_add_16x16_c(get_tx_type_16x16(pd->plane_type, xd), qcoeff, dst, + stride, eob); break; case TX_32X32: - vp9_idct_add_32x32(qcoeff, dst, stride, pd->eobs[block]); + vp9_idct_add_32x32(qcoeff, dst, stride, eob); break; } } @@ -235,6 +124,7 @@ static void decode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize, int ss_txfrm_size, void *arg) { MACROBLOCKD* const xd = arg; struct macroblockd_plane *pd = &xd->plane[plane]; + MODE_INFO *const mi = xd->mode_info_context; const int raster_block = txfrm_block_to_raster_block(xd, bsize, plane, block, ss_txfrm_size); @@ -245,13 +135,12 @@ static void decode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize, int b_mode; int plane_b_size; const int tx_ib = raster_block >> tx_size; - const int mode = plane == 0 ? xd->mode_info_context->mbmi.mode - : xd->mode_info_context->mbmi.uv_mode; + const int mode = plane == 0 ? mi->mbmi.mode + : mi->mbmi.uv_mode; - - if (plane == 0 && xd->mode_info_context->mbmi.sb_type < BLOCK_SIZE_SB8X8) { + if (plane == 0 && mi->mbmi.sb_type < BLOCK_SIZE_SB8X8) { assert(bsize == BLOCK_SIZE_SB8X8); - b_mode = xd->mode_info_context->bmi[raster_block].as_mode.first; + b_mode = mi->bmi[raster_block].as_mode; } else { b_mode = mode; } @@ -261,97 +150,28 @@ static void decode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize, plane_b_size = b_width_log2(bsize) - pd->subsampling_x; vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size, b_mode, + dst, pd->dst.stride, dst, pd->dst.stride); // Early exit if there are no coefficients - if (xd->mode_info_context->mbmi.mb_skip_coeff) + if (mi->mbmi.mb_skip_coeff) return; decode_block(plane, block, bsize, ss_txfrm_size, arg); } -static void decode_atom(VP9D_COMP *pbi, MACROBLOCKD *xd, - int mi_row, int mi_col, - vp9_reader *r, BLOCK_SIZE_TYPE bsize) { - MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi; - - assert(mbmi->ref_frame[0] != INTRA_FRAME); - - if ((pbi->common.frame_type != KEY_FRAME) && (!pbi->common.intra_only)) - vp9_setup_interp_filters(xd, mbmi->interp_filter, &pbi->common); - - // prediction - vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize); - - if (mbmi->mb_skip_coeff) { - vp9_reset_sb_tokens_context(xd, bsize); - } else { - if (xd->segmentation_enabled) - mb_init_dequantizer(&pbi->common, xd); - - if (!vp9_reader_has_error(r)) - vp9_decode_tokens(pbi, r, bsize); - - foreach_transformed_block(xd, bsize, decode_block, xd); - } -} +static int decode_tokens(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize, vp9_reader *r) { + MACROBLOCKD *const xd = &pbi->mb; -static void decode_sb_intra(VP9D_COMP *pbi, MACROBLOCKD *xd, - int mi_row, int mi_col, - vp9_reader *r, BLOCK_SIZE_TYPE bsize) { - MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi; - if (mbmi->mb_skip_coeff) { + if (xd->mode_info_context->mbmi.mb_skip_coeff) { vp9_reset_sb_tokens_context(xd, bsize); + return -1; } else { - if (xd->segmentation_enabled) - mb_init_dequantizer(&pbi->common, xd); - - if (!vp9_reader_has_error(r)) - vp9_decode_tokens(pbi, r, bsize); - } + if (xd->seg.enabled) + init_dequantizer(&pbi->common, xd); - foreach_transformed_block(xd, bsize, decode_block_intra, xd); -} - - -static void decode_sb(VP9D_COMP *pbi, MACROBLOCKD *xd, int mi_row, int mi_col, - vp9_reader *r, BLOCK_SIZE_TYPE bsize) { - const int bwl = mi_width_log2(bsize), bhl = mi_height_log2(bsize); - const int bw = 1 << bwl, bh = 1 << bhl; - int n, eobtotal; - VP9_COMMON *const pc = &pbi->common; - MODE_INFO *const mi = xd->mode_info_context; - MB_MODE_INFO *const mbmi = &mi->mbmi; - const int mis = pc->mode_info_stride; - - assert(mbmi->sb_type == bsize); - assert(mbmi->ref_frame[0] != INTRA_FRAME); - - if (pbi->common.frame_type != KEY_FRAME) - vp9_setup_interp_filters(xd, mbmi->interp_filter, pc); - - // generate prediction - vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize); - - if (mbmi->mb_skip_coeff) { - vp9_reset_sb_tokens_context(xd, bsize); - } else { - // re-initialize macroblock dequantizer before detokenization - if (xd->segmentation_enabled) - mb_init_dequantizer(pc, xd); - - // dequantization and idct - eobtotal = vp9_decode_tokens(pbi, r, bsize); - if (eobtotal == 0) { // skip loopfilter - for (n = 0; n < bw * bh; n++) { - const int x_idx = n & (bw - 1), y_idx = n >> bwl; - - if (mi_col + x_idx < pc->mi_cols && mi_row + y_idx < pc->mi_rows) - mi[y_idx * mis + x_idx].mbmi.mb_skip_coeff = 1; - } - } else { - foreach_transformed_block(xd, bsize, decode_block, xd); - } + // TODO(dkovalev) if (!vp9_reader_has_error(r)) + return vp9_decode_tokens(pbi, r, bsize); } } @@ -377,8 +197,8 @@ static void set_offsets(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize, pd->left_context = cm->left_context[i] + (((mi_row * 2) & 15) >> pd->subsampling_y); } - xd->above_seg_context = cm->above_seg_context + mi_col; - xd->left_seg_context = cm->left_seg_context + (mi_row & MI_MASK); + + set_partition_seg_context(cm, xd, mi_row, mi_col); // Distance of Mb to the various image edges. These are specified to 8th pel // as they are always compared to values that are in 1/8th pel units @@ -387,53 +207,65 @@ static void set_offsets(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize, setup_dst_planes(xd, &cm->yv12_fb[cm->new_fb_idx], mi_row, mi_col); } -static void set_refs(VP9D_COMP *pbi, int mi_row, int mi_col) { +static void set_ref(VP9D_COMP *pbi, int i, int mi_row, int mi_col) { VP9_COMMON *const cm = &pbi->common; MACROBLOCKD *const xd = &pbi->mb; MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi; + const int ref = mbmi->ref_frame[i] - 1; - if (mbmi->ref_frame[0] > INTRA_FRAME) { - // Select the appropriate reference frame for this MB - const int fb_idx = cm->active_ref_idx[mbmi->ref_frame[0] - 1]; - const YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[fb_idx]; - xd->scale_factor[0] = cm->active_ref_scale[mbmi->ref_frame[0] - 1]; - xd->scale_factor_uv[0] = cm->active_ref_scale[mbmi->ref_frame[0] - 1]; - setup_pre_planes(xd, cfg, NULL, mi_row, mi_col, - xd->scale_factor, xd->scale_factor_uv); - xd->corrupted |= cfg->corrupted; - - if (mbmi->ref_frame[1] > INTRA_FRAME) { - // Select the appropriate reference frame for this MB - const int second_fb_idx = cm->active_ref_idx[mbmi->ref_frame[1] - 1]; - const YV12_BUFFER_CONFIG *second_cfg = &cm->yv12_fb[second_fb_idx]; - xd->scale_factor[1] = cm->active_ref_scale[mbmi->ref_frame[1] - 1]; - xd->scale_factor_uv[1] = cm->active_ref_scale[mbmi->ref_frame[1] - 1]; - setup_pre_planes(xd, NULL, second_cfg, mi_row, mi_col, - xd->scale_factor, xd->scale_factor_uv); - xd->corrupted |= second_cfg->corrupted; - } - } + const YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->active_ref_idx[ref]]; + xd->scale_factor[i] = cm->active_ref_scale[ref]; + setup_pre_planes(xd, i, cfg, mi_row, mi_col, &xd->scale_factor[i]); + xd->corrupted |= cfg->corrupted; } static void decode_modes_b(VP9D_COMP *pbi, int mi_row, int mi_col, vp9_reader *r, BLOCK_SIZE_TYPE bsize) { + VP9_COMMON *const cm = &pbi->common; MACROBLOCKD *const xd = &pbi->mb; + const int less8x8 = bsize < BLOCK_SIZE_SB8X8; + MB_MODE_INFO *mbmi; - if (bsize < BLOCK_SIZE_SB8X8) + if (less8x8) if (xd->ab_index > 0) return; + set_offsets(pbi, bsize, mi_row, mi_col); - vp9_decode_mb_mode_mv(pbi, xd, mi_row, mi_col, r); - set_refs(pbi, mi_row, mi_col); + vp9_read_mode_info(pbi, mi_row, mi_col, r); - if (xd->mode_info_context->mbmi.ref_frame[0] == INTRA_FRAME) - decode_sb_intra(pbi, xd, mi_row, mi_col, r, (bsize < BLOCK_SIZE_SB8X8) ? - BLOCK_SIZE_SB8X8 : bsize); - else if (bsize < BLOCK_SIZE_SB8X8) - decode_atom(pbi, xd, mi_row, mi_col, r, BLOCK_SIZE_SB8X8); - else - decode_sb(pbi, xd, mi_row, mi_col, r, bsize); + if (less8x8) + bsize = BLOCK_SIZE_SB8X8; + // Has to be called after set_offsets + mbmi = &xd->mode_info_context->mbmi; + + if (mbmi->ref_frame[0] == INTRA_FRAME) { + // Intra reconstruction + decode_tokens(pbi, bsize, r); + foreach_transformed_block(xd, bsize, decode_block_intra, xd); + } else { + // Inter reconstruction + int eobtotal; + + set_ref(pbi, 0, mi_row, mi_col); + if (mbmi->ref_frame[1] > INTRA_FRAME) + set_ref(pbi, 1, mi_row, mi_col); + + vp9_setup_interp_filters(xd, mbmi->interp_filter, cm); + vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize); + eobtotal = decode_tokens(pbi, bsize, r); + if (less8x8) { + if (eobtotal >= 0) + foreach_transformed_block(xd, bsize, decode_block, xd); + } else { + assert(mbmi->sb_type == bsize); + if (eobtotal == 0) + // skip loopfilter + vp9_set_pred_flag_mbskip(cm, bsize, mi_row, mi_col, 1); + else if (eobtotal > 0) + foreach_transformed_block(xd, bsize, decode_block, xd); + } + } xd->corrupted |= vp9_reader_has_error(r); } @@ -448,16 +280,13 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mi_row, int mi_col, if (mi_row >= pc->mi_rows || mi_col >= pc->mi_cols) return; - if (bsize < BLOCK_SIZE_SB8X8) + if (bsize < BLOCK_SIZE_SB8X8) { if (xd->ab_index != 0) return; - - if (bsize >= BLOCK_SIZE_SB8X8) { + } else { int pl; - int idx = check_bsize_coverage(pc, xd, mi_row, mi_col, bsize); - // read the partition information - xd->left_seg_context = pc->left_seg_context + (mi_row & MI_MASK); - xd->above_seg_context = pc->above_seg_context + mi_col; + const int idx = check_bsize_coverage(pc, xd, mi_row, mi_col, bsize); + set_partition_seg_context(pc, xd, mi_row, mi_col); pl = partition_plane_context(xd, bsize); if (idx == 0) @@ -469,7 +298,7 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mi_row, int mi_col, else partition = PARTITION_SPLIT; - pc->fc.partition_counts[pl][partition]++; + pc->counts.partition[pl][partition]++; } subsize = get_subsize(bsize, partition); @@ -499,8 +328,9 @@ static void decode_modes_sb(VP9D_COMP *pbi, int mi_row, int mi_col, } break; default: - assert(0); + assert(!"Invalid partition type"); } + // update partition context if (bsize >= BLOCK_SIZE_SB8X8 && (bsize == BLOCK_SIZE_SB8X8 || partition != PARTITION_SPLIT)) { @@ -527,142 +357,118 @@ static void setup_token_decoder(VP9D_COMP *pbi, "Failed to allocate bool decoder %d", 1); } -static void read_coef_probs_common(FRAME_CONTEXT *fc, TX_SIZE tx_size, +static void read_coef_probs_common(vp9_coeff_probs_model *coef_probs, vp9_reader *r) { - vp9_coeff_probs_model *coef_probs = fc->coef_probs[tx_size]; - - if (vp9_read_bit(r)) { - int i, j, k, l, m; - for (i = 0; i < BLOCK_TYPES; i++) { - for (j = 0; j < REF_TYPES; j++) { - for (k = 0; k < COEF_BANDS; k++) { - for (l = 0; l < PREV_COEF_CONTEXTS; l++) { - if (l >= 3 && k == 0) - continue; - - for (m = 0; m < UNCONSTRAINED_NODES; m++) { - vp9_prob *const p = coef_probs[i][j][k][l] + m; - - if (vp9_read(r, VP9_COEF_UPDATE_PROB)) - *p = vp9_read_prob_diff_update(r, *p); - } - } - } - } - } - } -} + int i, j, k, l, m; -static void read_coef_probs(VP9D_COMP *pbi, vp9_reader *r) { - const TXFM_MODE txfm_mode = pbi->common.txfm_mode; - FRAME_CONTEXT *const fc = &pbi->common.fc; + if (vp9_read_bit(r)) + for (i = 0; i < BLOCK_TYPES; i++) + for (j = 0; j < REF_TYPES; j++) + for (k = 0; k < COEF_BANDS; k++) + for (l = 0; l < PREV_COEF_CONTEXTS; l++) + if (k > 0 || l < 3) + for (m = 0; m < UNCONSTRAINED_NODES; m++) + if (vp9_read(r, VP9_COEF_UPDATE_PROB)) + vp9_diff_update_prob(r, &coef_probs[i][j][k][l][m]); +} - read_coef_probs_common(fc, TX_4X4, r); +static void read_coef_probs(FRAME_CONTEXT *fc, TX_MODE tx_mode, + vp9_reader *r) { + read_coef_probs_common(fc->coef_probs[TX_4X4], r); - if (txfm_mode > ONLY_4X4) - read_coef_probs_common(fc, TX_8X8, r); + if (tx_mode > ONLY_4X4) + read_coef_probs_common(fc->coef_probs[TX_8X8], r); - if (txfm_mode > ALLOW_8X8) - read_coef_probs_common(fc, TX_16X16, r); + if (tx_mode > ALLOW_8X8) + read_coef_probs_common(fc->coef_probs[TX_16X16], r); - if (txfm_mode > ALLOW_16X16) - read_coef_probs_common(fc, TX_32X32, r); + if (tx_mode > ALLOW_16X16) + read_coef_probs_common(fc->coef_probs[TX_32X32], r); } -static void setup_segmentation(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) { +static void setup_segmentation(struct segmentation *seg, + struct vp9_read_bit_buffer *rb) { int i, j; - VP9_COMMON *const cm = &pbi->common; - MACROBLOCKD *const xd = &pbi->mb; - - xd->update_mb_segmentation_map = 0; - xd->update_mb_segmentation_data = 0; + seg->update_map = 0; + seg->update_data = 0; - xd->segmentation_enabled = vp9_rb_read_bit(rb); - if (!xd->segmentation_enabled) + seg->enabled = vp9_rb_read_bit(rb); + if (!seg->enabled) return; // Segmentation map update - xd->update_mb_segmentation_map = vp9_rb_read_bit(rb); - if (xd->update_mb_segmentation_map) { - for (i = 0; i < MB_SEG_TREE_PROBS; i++) - xd->mb_segment_tree_probs[i] = vp9_rb_read_bit(rb) ? - vp9_rb_read_literal(rb, 8) : MAX_PROB; - - cm->temporal_update = vp9_rb_read_bit(rb); - if (cm->temporal_update) { + seg->update_map = vp9_rb_read_bit(rb); + if (seg->update_map) { + for (i = 0; i < SEG_TREE_PROBS; i++) + seg->tree_probs[i] = vp9_rb_read_bit(rb) ? vp9_rb_read_literal(rb, 8) + : MAX_PROB; + + seg->temporal_update = vp9_rb_read_bit(rb); + if (seg->temporal_update) { for (i = 0; i < PREDICTION_PROBS; i++) - cm->segment_pred_probs[i] = vp9_rb_read_bit(rb) ? - vp9_rb_read_literal(rb, 8) : MAX_PROB; + seg->pred_probs[i] = vp9_rb_read_bit(rb) ? vp9_rb_read_literal(rb, 8) + : MAX_PROB; } else { for (i = 0; i < PREDICTION_PROBS; i++) - cm->segment_pred_probs[i] = MAX_PROB; + seg->pred_probs[i] = MAX_PROB; } } // Segmentation data update - xd->update_mb_segmentation_data = vp9_rb_read_bit(rb); - if (xd->update_mb_segmentation_data) { - xd->mb_segment_abs_delta = vp9_rb_read_bit(rb); + seg->update_data = vp9_rb_read_bit(rb); + if (seg->update_data) { + seg->abs_delta = vp9_rb_read_bit(rb); - vp9_clearall_segfeatures(xd); + vp9_clearall_segfeatures(seg); - for (i = 0; i < MAX_MB_SEGMENTS; i++) { + for (i = 0; i < MAX_SEGMENTS; i++) { for (j = 0; j < SEG_LVL_MAX; j++) { int data = 0; const int feature_enabled = vp9_rb_read_bit(rb); if (feature_enabled) { - vp9_enable_segfeature(xd, i, j); + vp9_enable_segfeature(seg, i, j); data = decode_unsigned_max(rb, vp9_seg_feature_data_max(j)); if (vp9_is_segfeature_signed(j)) data = vp9_rb_read_bit(rb) ? -data : data; } - vp9_set_segdata(xd, i, j, data); + vp9_set_segdata(seg, i, j, data); } } } } -static void setup_loopfilter(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) { - VP9_COMMON *const cm = &pbi->common; - MACROBLOCKD *const xd = &pbi->mb; +static void setup_loopfilter(struct loopfilter *lf, + struct vp9_read_bit_buffer *rb) { - cm->filter_level = vp9_rb_read_literal(rb, 6); - cm->sharpness_level = vp9_rb_read_literal(rb, 3); + lf->filter_level = vp9_rb_read_literal(rb, 6); + lf->sharpness_level = vp9_rb_read_literal(rb, 3); // Read in loop filter deltas applied at the MB level based on mode or ref // frame. - xd->mode_ref_lf_delta_update = 0; + lf->mode_ref_delta_update = 0; - xd->mode_ref_lf_delta_enabled = vp9_rb_read_bit(rb); - if (xd->mode_ref_lf_delta_enabled) { - xd->mode_ref_lf_delta_update = vp9_rb_read_bit(rb); - if (xd->mode_ref_lf_delta_update) { + lf->mode_ref_delta_enabled = vp9_rb_read_bit(rb); + if (lf->mode_ref_delta_enabled) { + lf->mode_ref_delta_update = vp9_rb_read_bit(rb); + if (lf->mode_ref_delta_update) { int i; - for (i = 0; i < MAX_REF_LF_DELTAS; i++) { - if (vp9_rb_read_bit(rb)) { - const int value = vp9_rb_read_literal(rb, 6); - xd->ref_lf_deltas[i] = vp9_rb_read_bit(rb) ? -value : value; - } - } + for (i = 0; i < MAX_REF_LF_DELTAS; i++) + if (vp9_rb_read_bit(rb)) + lf->ref_deltas[i] = vp9_rb_read_signed_literal(rb, 6); - for (i = 0; i < MAX_MODE_LF_DELTAS; i++) { - if (vp9_rb_read_bit(rb)) { - const int value = vp9_rb_read_literal(rb, 6); - xd->mode_lf_deltas[i] = vp9_rb_read_bit(rb) ? -value : value; - } - } + for (i = 0; i < MAX_MODE_LF_DELTAS; i++) + if (vp9_rb_read_bit(rb)) + lf->mode_deltas[i] = vp9_rb_read_signed_literal(rb, 6); } } } static int read_delta_q(struct vp9_read_bit_buffer *rb, int *delta_q) { const int old = *delta_q; - if (vp9_rb_read_bit(rb)) { - const int value = vp9_rb_read_literal(rb, 4); - *delta_q = vp9_rb_read_bit(rb) ? -value : value; - } + if (vp9_rb_read_bit(rb)) + *delta_q = vp9_rb_read_signed_literal(rb, 4); return old != *delta_q; } @@ -682,11 +488,9 @@ static void setup_quantization(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) { cm->y_dc_delta_q == 0 && cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0; - if (xd->lossless) { - xd->itxm_add = vp9_idct_add_lossless_c; - } else { - xd->itxm_add = vp9_idct_add; - } + + xd->itxm_add = xd->lossless ? vp9_idct_add_lossless_c + : vp9_idct_add; } static INTERPOLATIONFILTERTYPE read_interp_filter_type( @@ -778,108 +582,90 @@ static void setup_frame_size_with_refs(VP9D_COMP *pbi, apply_frame_size(pbi, width, height); } -static void update_frame_context(FRAME_CONTEXT *fc) { - vp9_copy(fc->pre_coef_probs, fc->coef_probs); - vp9_copy(fc->pre_y_mode_prob, fc->y_mode_prob); - vp9_copy(fc->pre_uv_mode_prob, fc->uv_mode_prob); - vp9_copy(fc->pre_partition_prob, fc->partition_prob[1]); - vp9_copy(fc->pre_intra_inter_prob, fc->intra_inter_prob); - vp9_copy(fc->pre_comp_inter_prob, fc->comp_inter_prob); - vp9_copy(fc->pre_single_ref_prob, fc->single_ref_prob); - vp9_copy(fc->pre_comp_ref_prob, fc->comp_ref_prob); - fc->pre_nmvc = fc->nmvc; - vp9_copy(fc->pre_switchable_interp_prob, fc->switchable_interp_prob); - vp9_copy(fc->pre_inter_mode_probs, fc->inter_mode_probs); - vp9_copy(fc->pre_tx_probs_8x8p, fc->tx_probs_8x8p); - vp9_copy(fc->pre_tx_probs_16x16p, fc->tx_probs_16x16p); - vp9_copy(fc->pre_tx_probs_32x32p, fc->tx_probs_32x32p); - vp9_copy(fc->pre_mbskip_probs, fc->mbskip_probs); - - vp9_zero(fc->coef_counts); - vp9_zero(fc->eob_branch_counts); - vp9_zero(fc->y_mode_counts); - vp9_zero(fc->uv_mode_counts); - vp9_zero(fc->NMVcount); - vp9_zero(fc->inter_mode_counts); - vp9_zero(fc->partition_counts); - vp9_zero(fc->switchable_interp_count); - vp9_zero(fc->intra_inter_count); - vp9_zero(fc->comp_inter_count); - vp9_zero(fc->single_ref_count); - vp9_zero(fc->comp_ref_count); - vp9_zero(fc->tx_count_8x8p); - vp9_zero(fc->tx_count_16x16p); - vp9_zero(fc->tx_count_32x32p); - vp9_zero(fc->mbskip_count); -} - static void decode_tile(VP9D_COMP *pbi, vp9_reader *r) { VP9_COMMON *const pc = &pbi->common; int mi_row, mi_col; - for (mi_row = pc->cur_tile_mi_row_start; - mi_row < pc->cur_tile_mi_row_end; mi_row += 64 / MI_SIZE) { + if (pbi->do_loopfilter_inline) { + vp9_loop_filter_frame_init(pc, &pbi->mb, pbi->mb.lf.filter_level); + } + + for (mi_row = pc->cur_tile_mi_row_start; mi_row < pc->cur_tile_mi_row_end; + mi_row += MI_BLOCK_SIZE) { // For a SB there are 2 left contexts, each pertaining to a MB row within vpx_memset(&pc->left_context, 0, sizeof(pc->left_context)); vpx_memset(pc->left_seg_context, 0, sizeof(pc->left_seg_context)); - for (mi_col = pc->cur_tile_mi_col_start; - mi_col < pc->cur_tile_mi_col_end; mi_col += 64 / MI_SIZE) + for (mi_col = pc->cur_tile_mi_col_start; mi_col < pc->cur_tile_mi_col_end; + mi_col += MI_BLOCK_SIZE) { decode_modes_sb(pbi, mi_row, mi_col, r, BLOCK_SIZE_SB64X64); + } + + if (pbi->do_loopfilter_inline) { + YV12_BUFFER_CONFIG *const fb = + &pbi->common.yv12_fb[pbi->common.new_fb_idx]; + // delay the loopfilter by 1 macroblock row. + const int lf_start = mi_row - MI_BLOCK_SIZE; + if (lf_start < 0) continue; + vp9_loop_filter_rows(fb, pc, &pbi->mb, lf_start, mi_row, 0); + } + } + + if (pbi->do_loopfilter_inline) { + YV12_BUFFER_CONFIG *const fb = &pbi->common.yv12_fb[pbi->common.new_fb_idx]; + vp9_loop_filter_rows(fb, pc, &pbi->mb, + mi_row - MI_BLOCK_SIZE, pc->mi_rows, 0); } } static void setup_tile_info(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) { - int delta_log2_tiles; + int min_log2_tile_cols, max_log2_tile_cols, max_ones; + vp9_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols); - vp9_get_tile_n_bits(cm, &cm->log2_tile_columns, &delta_log2_tiles); - while (delta_log2_tiles--) { - if (vp9_rb_read_bit(rb)) { - cm->log2_tile_columns++; - } else { - break; - } - } + // columns + max_ones = max_log2_tile_cols - min_log2_tile_cols; + cm->log2_tile_cols = min_log2_tile_cols; + while (max_ones-- && vp9_rb_read_bit(rb)) + cm->log2_tile_cols++; + // rows cm->log2_tile_rows = vp9_rb_read_bit(rb); if (cm->log2_tile_rows) cm->log2_tile_rows += vp9_rb_read_bit(rb); - - cm->tile_columns = 1 << cm->log2_tile_columns; - cm->tile_rows = 1 << cm->log2_tile_rows; } -static void decode_tiles(VP9D_COMP *pbi, - const uint8_t *data, size_t first_partition_size, - vp9_reader *residual_bc) { +static const uint8_t *decode_tiles(VP9D_COMP *pbi, const uint8_t *data) { + vp9_reader residual_bc; + VP9_COMMON *const pc = &pbi->common; - const uint8_t *data_ptr = data + first_partition_size; - const uint8_t* const data_end = pbi->source + pbi->source_sz; + const uint8_t *const data_end = pbi->source + pbi->source_sz; + const int aligned_mi_cols = mi_cols_aligned_to_sb(pc->mi_cols); + const int tile_cols = 1 << pc->log2_tile_cols; + const int tile_rows = 1 << pc->log2_tile_rows; int tile_row, tile_col; // Note: this memset assumes above_context[0], [1] and [2] // are allocated as part of the same buffer. - vpx_memset(pc->above_context[0], 0, sizeof(ENTROPY_CONTEXT) * 2 * - MAX_MB_PLANE * mi_cols_aligned_to_sb(pc)); + vpx_memset(pc->above_context[0], 0, + sizeof(ENTROPY_CONTEXT) * 2 * MAX_MB_PLANE * aligned_mi_cols); - vpx_memset(pc->above_seg_context, 0, sizeof(PARTITION_CONTEXT) * - mi_cols_aligned_to_sb(pc)); + vpx_memset(pc->above_seg_context, 0, + sizeof(PARTITION_CONTEXT) * aligned_mi_cols); if (pbi->oxcf.inv_tile_order) { - const int n_cols = pc->tile_columns; const uint8_t *data_ptr2[4][1 << 6]; vp9_reader bc_bak = {0}; // pre-initialize the offsets, we're going to read in inverse order - data_ptr2[0][0] = data_ptr; - for (tile_row = 0; tile_row < pc->tile_rows; tile_row++) { + data_ptr2[0][0] = data; + for (tile_row = 0; tile_row < tile_rows; tile_row++) { if (tile_row) { - const int size = read_be32(data_ptr2[tile_row - 1][n_cols - 1]); - data_ptr2[tile_row - 1][n_cols - 1] += 4; - data_ptr2[tile_row][0] = data_ptr2[tile_row - 1][n_cols - 1] + size; + const int size = read_be32(data_ptr2[tile_row - 1][tile_cols - 1]); + data_ptr2[tile_row - 1][tile_cols - 1] += 4; + data_ptr2[tile_row][0] = data_ptr2[tile_row - 1][tile_cols - 1] + size; } - for (tile_col = 1; tile_col < n_cols; tile_col++) { + for (tile_col = 1; tile_col < tile_cols; tile_col++) { const int size = read_be32(data_ptr2[tile_row][tile_col - 1]); data_ptr2[tile_row][tile_col - 1] += 4; data_ptr2[tile_row][tile_col] = @@ -887,48 +673,49 @@ static void decode_tiles(VP9D_COMP *pbi, } } - for (tile_row = 0; tile_row < pc->tile_rows; tile_row++) { + for (tile_row = 0; tile_row < tile_rows; tile_row++) { vp9_get_tile_row_offsets(pc, tile_row); - for (tile_col = n_cols - 1; tile_col >= 0; tile_col--) { + for (tile_col = tile_cols - 1; tile_col >= 0; tile_col--) { vp9_get_tile_col_offsets(pc, tile_col); setup_token_decoder(pbi, data_ptr2[tile_row][tile_col], data_end - data_ptr2[tile_row][tile_col], - residual_bc); - decode_tile(pbi, residual_bc); - if (tile_row == pc->tile_rows - 1 && tile_col == n_cols - 1) - bc_bak = *residual_bc; + &residual_bc); + decode_tile(pbi, &residual_bc); + if (tile_row == tile_rows - 1 && tile_col == tile_cols - 1) + bc_bak = residual_bc; } } - *residual_bc = bc_bak; + residual_bc = bc_bak; } else { int has_more; - for (tile_row = 0; tile_row < pc->tile_rows; tile_row++) { + for (tile_row = 0; tile_row < tile_rows; tile_row++) { vp9_get_tile_row_offsets(pc, tile_row); - for (tile_col = 0; tile_col < pc->tile_columns; tile_col++) { + for (tile_col = 0; tile_col < tile_cols; tile_col++) { size_t size; vp9_get_tile_col_offsets(pc, tile_col); - has_more = tile_col < pc->tile_columns - 1 || - tile_row < pc->tile_rows - 1; + has_more = tile_col < tile_cols - 1 || tile_row < tile_rows - 1; if (has_more) { - if (!read_is_valid(data_ptr, 4, data_end)) + if (!read_is_valid(data, 4, data_end)) vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet or corrupt tile length"); - size = read_be32(data_ptr); - data_ptr += 4; + size = read_be32(data); + data += 4; } else { - size = data_end - data_ptr; + size = data_end - data; } - setup_token_decoder(pbi, data_ptr, size, residual_bc); - decode_tile(pbi, residual_bc); - data_ptr += size; + setup_token_decoder(pbi, data, size, &residual_bc); + decode_tile(pbi, &residual_bc); + data += size; } } } + + return vp9_reader_find_end(&residual_bc); } static void check_sync_code(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) { @@ -949,10 +736,9 @@ static void setup_inter_inter(VP9_COMMON *cm) { int i; cm->allow_comp_inter_inter = 0; - for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) { - cm->allow_comp_inter_inter |= i > 0 && + for (i = 1; i < ALLOWED_REFS_PER_FRAME; ++i) + cm->allow_comp_inter_inter |= cm->ref_frame_sign_bias[i + 1] != cm->ref_frame_sign_bias[1]; - } if (cm->allow_comp_inter_inter) { // which one is always-on in comp inter-inter? @@ -999,7 +785,7 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)]; ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->new_fb_idx, frame_to_show); pbi->refresh_frame_flags = 0; - cm->filter_level = 0; + xd->lf.filter_level = 0; return 0; } @@ -1053,7 +839,7 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, pbi->refresh_frame_flags = vp9_rb_read_literal(rb, NUM_REF_FRAMES); for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) { - const int ref = vp9_rb_read_literal(rb, NUM_REF_FRAMES_LG2); + const int ref = vp9_rb_read_literal(rb, NUM_REF_FRAMES_LOG2); cm->active_ref_idx[i] = cm->ref_frame_map[ref]; cm->ref_frame_sign_bias[LAST_FRAME + i] = vp9_rb_read_bit(rb); } @@ -1078,23 +864,54 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, cm->frame_parallel_decoding_mode = 1; } - cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2); + cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LOG2); if (cm->frame_type == KEY_FRAME || cm->error_resilient_mode || cm->intra_only) vp9_setup_past_independence(cm, xd); - setup_loopfilter(pbi, rb); + setup_loopfilter(&xd->lf, rb); setup_quantization(pbi, rb); - setup_segmentation(pbi, rb); + setup_segmentation(&xd->seg, rb); setup_tile_info(cm, rb); return vp9_rb_read_literal(rb, 16); } +static int read_compressed_header(VP9D_COMP *pbi, const uint8_t *data, + size_t partition_size) { + VP9_COMMON *const cm = &pbi->common; + MACROBLOCKD *const xd = &pbi->mb; + vp9_reader r; + + if (vp9_reader_init(&r, data, partition_size)) + vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, + "Failed to allocate bool decoder 0"); + + cm->tx_mode = xd->lossless ? ONLY_4X4 : read_tx_mode(&r); + if (cm->tx_mode == TX_MODE_SELECT) + read_tx_probs(&cm->fc.tx_probs, &r); + read_coef_probs(&cm->fc, cm->tx_mode, &r); + + vp9_prepare_read_mode_info(pbi, &r); + + return vp9_reader_has_error(&r); +} + +void vp9_init_dequantizer(VP9_COMMON *cm) { + int q; + + for (q = 0; q < QINDEX_RANGE; q++) { + cm->y_dequant[q][0] = vp9_dc_quant(q, cm->y_dc_delta_q); + cm->y_dequant[q][1] = vp9_ac_quant(q, 0); + + cm->uv_dequant[q][0] = vp9_dc_quant(q, cm->uv_dc_delta_q); + cm->uv_dequant[q][1] = vp9_ac_quant(q, cm->uv_ac_delta_q); + } +} + 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; @@ -1115,6 +932,8 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { data += vp9_rb_bytes_read(&rb); xd->corrupted = 0; new_fb->corrupted = 0; + pbi->do_loopfilter_inline = + (pc->log2_tile_rows | pc->log2_tile_cols) == 0 && pbi->mb.lf.filter_level; if (!pbi->decoded_key_frame && !keyframe) return -1; @@ -1125,37 +944,29 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { xd->mode_info_context = pc->mi; xd->prev_mode_info_context = pc->prev_mi; - xd->frame_type = pc->frame_type; xd->mode_info_stride = pc->mode_info_stride; - if (vp9_reader_init(&header_bc, data, first_partition_size)) - vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, - "Failed to allocate bool decoder 0"); - - mb_init_dequantizer(pc, &pbi->mb); // MB level dequantizer setup + init_dequantizer(pc, &pbi->mb); if (!keyframe) vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc); pc->fc = pc->frame_contexts[pc->frame_context_idx]; - update_frame_context(&pc->fc); - - setup_txfm_mode(pc, xd->lossless, &header_bc); - - read_coef_probs(pbi, &header_bc); + vp9_zero(pc->counts); // Initialize xd pointers. Any reference should do for xd->pre, so use 0. - setup_pre_planes(xd, &pc->yv12_fb[pc->active_ref_idx[0]], NULL, - 0, 0, NULL, NULL); + setup_pre_planes(xd, 0, &pc->yv12_fb[pc->active_ref_idx[0]], 0, 0, NULL); setup_dst_planes(xd, new_fb, 0, 0); + new_fb->corrupted |= read_compressed_header(pbi, data, first_partition_size); + // Create the segmentation map structure and set to 0 if (!pc->last_frame_seg_map) - CHECK_MEM_ERROR(pc->last_frame_seg_map, + CHECK_MEM_ERROR(pc, pc->last_frame_seg_map, vpx_calloc((pc->mi_rows * pc->mi_cols), 1)); - vp9_setup_block_dptrs(xd, pc->subsampling_x, pc->subsampling_y); + setup_block_dptrs(xd, pc->subsampling_x, pc->subsampling_y); // clear out the coeff buffer for (i = 0; i < MAX_MB_PLANE; ++i) @@ -1163,14 +974,12 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { set_prev_mi(pc); - vp9_decode_mode_mvs_init(pbi, &header_bc); - - decode_tiles(pbi, data, first_partition_size, &residual_bc); + *p_data_end = decode_tiles(pbi, data + first_partition_size); pc->last_width = pc->width; pc->last_height = pc->height; - new_fb->corrupted = vp9_reader_has_error(&header_bc) | xd->corrupted; + new_fb->corrupted |= xd->corrupted; if (!pbi->decoded_key_frame) { if (keyframe && !new_fb->corrupted) @@ -1180,20 +989,18 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { "A stream must start with a complete key frame"); } - // Adaptation if (!pc->error_resilient_mode && !pc->frame_parallel_decoding_mode) { vp9_adapt_coef_probs(pc); - if ((!keyframe) && (!pc->intra_only)) { + if (!keyframe && !pc->intra_only) { vp9_adapt_mode_probs(pc); vp9_adapt_mode_context(pc); - vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv); + vp9_adapt_mv_probs(pc, xd->allow_high_precision_mv); } } if (pc->refresh_frame_context) pc->frame_contexts[pc->frame_context_idx] = pc->fc; - *p_data_end = vp9_reader_find_end(&residual_bc); return 0; } diff --git a/libvpx/vp9/decoder/vp9_decodframe.h b/libvpx/vp9/decoder/vp9_decodframe.h index 66e951d..00b6d67 100644 --- a/libvpx/vp9/decoder/vp9_decodframe.h +++ b/libvpx/vp9/decoder/vp9_decodframe.h @@ -17,6 +17,5 @@ struct VP9Decompressor; void vp9_init_dequantizer(struct VP9Common *pc); int vp9_decode_frame(struct VP9Decompressor *cpi, const uint8_t **p_data_end); -vp9_prob vp9_read_prob_diff_update(vp9_reader *r, int oldp); #endif // VP9_DECODER_VP9_DECODFRAME_H_ diff --git a/libvpx/vp9/decoder/vp9_detokenize.c b/libvpx/vp9/decoder/vp9_detokenize.c index 3bbb212..01c1db0 100644 --- a/libvpx/vp9/decoder/vp9_detokenize.c +++ b/libvpx/vp9/decoder/vp9_detokenize.c @@ -18,14 +18,8 @@ #include "vp9/decoder/vp9_detokenize.h" #include "vp9/decoder/vp9_onyxd_int.h" -#if CONFIG_BALANCED_COEFTREE -#define ZERO_CONTEXT_NODE 0 -#define EOB_CONTEXT_NODE 1 -#else #define EOB_CONTEXT_NODE 0 #define ZERO_CONTEXT_NODE 1 -#endif - #define ONE_CONTEXT_NODE 2 #define LOW_VAL_CONTEXT_NODE 3 #define TWO_CONTEXT_NODE 4 @@ -91,13 +85,15 @@ DECLARE_ALIGNED(16, extern const uint8_t, val += 1 << bits_count; \ } while (0); -static int decode_coefs(FRAME_CONTEXT *fc, const MACROBLOCKD *xd, +static int decode_coefs(VP9_COMMON *cm, const MACROBLOCKD *xd, vp9_reader *r, int block_idx, PLANE_TYPE type, int seg_eob, int16_t *qcoeff_ptr, TX_SIZE txfm_size, const int16_t *dq, ENTROPY_CONTEXT *A, ENTROPY_CONTEXT *L) { + FRAME_CONTEXT *const fc = &cm->fc; + FRAME_COUNTS *const counts = &cm->counts; ENTROPY_CONTEXT above_ec, left_ec; - int pt, c = 0, pad, default_eob; + int pt, c = 0; int band; vp9_prob (*coef_probs)[PREV_COEF_CONTEXTS][UNCONSTRAINED_NODES]; vp9_prob coef_probs_full[COEF_BANDS][PREV_COEF_CONTEXTS][ENTROPY_NODES]; @@ -113,53 +109,31 @@ static int decode_coefs(FRAME_CONTEXT *fc, const MACROBLOCKD *xd, vp9_prob *prob; vp9_coeff_count_model *coef_counts; const int ref = xd->mode_info_context->mbmi.ref_frame[0] != INTRA_FRAME; - TX_TYPE tx_type = DCT_DCT; - const int *scan, *nb; + const int16_t *scan, *nb; uint8_t token_cache[1024]; const uint8_t * band_translate; -#if CONFIG_BALANCED_COEFTREE - int skip_eob_node = 0; -#endif - coef_probs = fc->coef_probs[txfm_size][type][ref]; - coef_counts = fc->coef_counts[txfm_size]; + coef_counts = counts->coef[txfm_size]; switch (txfm_size) { default: case TX_4X4: { - tx_type = (type == PLANE_TYPE_Y_WITH_DC) ? - get_tx_type_4x4(xd, block_idx) : DCT_DCT; - scan = get_scan_4x4(tx_type); + scan = get_scan_4x4(get_tx_type_4x4(type, xd, block_idx)); above_ec = A[0] != 0; left_ec = L[0] != 0; - default_eob = 16; band_translate = vp9_coefband_trans_4x4; break; } case TX_8X8: { - const BLOCK_SIZE_TYPE sb_type = xd->mode_info_context->mbmi.sb_type; - const int sz = 1 + b_width_log2(sb_type); - const int x = block_idx & ((1 << sz) - 1); - const int y = block_idx - x; - tx_type = (type == PLANE_TYPE_Y_WITH_DC) ? - get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT; - scan = get_scan_8x8(tx_type); + scan = get_scan_8x8(get_tx_type_8x8(type, xd)); above_ec = (A[0] + A[1]) != 0; left_ec = (L[0] + L[1]) != 0; - default_eob = 64; band_translate = vp9_coefband_trans_8x8plus; break; } case TX_16X16: { - const BLOCK_SIZE_TYPE sb_type = xd->mode_info_context->mbmi.sb_type; - const int sz = 2 + b_width_log2(sb_type); - const int x = block_idx & ((1 << sz) - 1); - const int y = block_idx - x; - tx_type = (type == PLANE_TYPE_Y_WITH_DC) ? - get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT; - scan = get_scan_16x16(tx_type); + scan = get_scan_16x16(get_tx_type_16x16(type, xd)); above_ec = (A[0] + A[1] + A[2] + A[3]) != 0; left_ec = (L[0] + L[1] + L[2] + L[3]) != 0; - default_eob = 256; band_translate = vp9_coefband_trans_8x8plus; break; } @@ -167,13 +141,12 @@ static int decode_coefs(FRAME_CONTEXT *fc, const MACROBLOCKD *xd, scan = vp9_default_scan_32x32; above_ec = (A[0] + A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7]) != 0; left_ec = (L[0] + L[1] + L[2] + L[3] + L[4] + L[5] + L[6] + L[7]) != 0; - default_eob = 1024; band_translate = vp9_coefband_trans_8x8plus; break; } pt = combine_entropy_contexts(above_ec, left_ec); - nb = vp9_get_coef_neighbors_handle(scan, &pad); + nb = vp9_get_coef_neighbors_handle(scan); while (1) { int val; @@ -181,43 +154,26 @@ static int decode_coefs(FRAME_CONTEXT *fc, const MACROBLOCKD *xd, if (c >= seg_eob) break; if (c) - pt = vp9_get_coef_context(scan, nb, pad, token_cache, - c, default_eob); + pt = get_coef_context(nb, token_cache, c); band = get_coef_band(band_translate, c); prob = coef_probs[band][pt]; -#if !CONFIG_BALANCED_COEFTREE - fc->eob_branch_counts[txfm_size][type][ref][band][pt]++; + counts->eob_branch[txfm_size][type][ref][band][pt]++; if (!vp9_read(r, prob[EOB_CONTEXT_NODE])) break; SKIP_START: -#endif if (c >= seg_eob) break; if (c) - pt = vp9_get_coef_context(scan, nb, pad, token_cache, - c, default_eob); + pt = get_coef_context(nb, token_cache, c); band = get_coef_band(band_translate, c); prob = coef_probs[band][pt]; if (!vp9_read(r, prob[ZERO_CONTEXT_NODE])) { INCREMENT_COUNT(ZERO_TOKEN); ++c; -#if CONFIG_BALANCED_COEFTREE - skip_eob_node = 1; - continue; -#else goto SKIP_START; -#endif - } -#if CONFIG_BALANCED_COEFTREE - if (!skip_eob_node) { - fc->eob_branch_counts[txfm_size][type][ref][band][pt]++; - if (!vp9_read(r, prob[EOB_CONTEXT_NODE])) - break; } - skip_eob_node = 0; -#endif // ONE_CONTEXT_NODE_0_ if (!vp9_read(r, prob[ONE_CONTEXT_NODE])) { @@ -293,8 +249,8 @@ SKIP_START: return c; } -static int get_eob(MACROBLOCKD* const xd, int segment_id, int eob_max) { - return vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP) ? 0 : eob_max; +static int get_eob(struct segmentation *seg, int segment_id, int eob_max) { + return vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max; } struct decode_block_args { @@ -315,7 +271,7 @@ static void decode_block(int plane, int block, struct macroblockd_plane* pd = &xd->plane[plane]; const int segment_id = xd->mode_info_context->mbmi.segment_id; const TX_SIZE ss_tx_size = ss_txfrm_size / 2; - const int seg_eob = get_eob(xd, segment_id, 16 << ss_txfrm_size); + const int seg_eob = get_eob(&xd->seg, segment_id, 16 << ss_txfrm_size); const int off = block >> ss_txfrm_size; const int mod = bw - ss_tx_size - pd->subsampling_x; const int aoff = (off & ((1 << mod) - 1)) << ss_tx_size; @@ -323,7 +279,7 @@ static void decode_block(int plane, int block, ENTROPY_CONTEXT *A = pd->above_context + aoff; ENTROPY_CONTEXT *L = pd->left_context + loff; - const int eob = decode_coefs(&arg->pbi->common.fc, xd, arg->r, block, + const int eob = decode_coefs(&arg->pbi->common, xd, arg->r, block, pd->plane_type, seg_eob, BLOCK_OFFSET(pd->qcoeff, block, 16), ss_tx_size, pd->dequant, A, L); diff --git a/libvpx/vp9/decoder/vp9_dsubexp.c b/libvpx/vp9/decoder/vp9_dsubexp.c new file mode 100644 index 0000000..8cc64f7 --- /dev/null +++ b/libvpx/vp9/decoder/vp9_dsubexp.c @@ -0,0 +1,106 @@ +/* + Copyright (c) 2010 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. + */ + +#include "vp9/common/vp9_entropy.h" + +#include "vp9/decoder/vp9_dsubexp.h" + +static int inv_recenter_nonneg(int v, int m) { + if (v > 2 * m) + return v; + + return v % 2 ? m - (v + 1) / 2 : m + v / 2; +} + +static int decode_uniform(vp9_reader *r, int n) { + int v; + const int l = get_unsigned_bits(n); + const int m = (1 << l) - n; + if (!l) + return 0; + + v = vp9_read_literal(r, l - 1); + return v < m ? v : (v << 1) - m + vp9_read_bit(r); +} + + +static int merge_index(int v, int n, int modulus) { + int max1 = (n - 1 - modulus / 2) / modulus + 1; + if (v < max1) { + v = v * modulus + modulus / 2; + } else { + int w; + v -= max1; + w = v; + v += (v + modulus - modulus / 2) / modulus; + while (v % modulus == modulus / 2 || + w != v - (v + modulus - modulus / 2) / modulus) v++; + } + return v; +} + +static int inv_remap_prob(int v, int m) { + static int inv_map_table[MAX_PROB - 1] = { + // generated by: + // inv_map_table[j] = merge_index(j, MAX_PROB - 1, MODULUS_PARAM); + 6, 19, 32, 45, 58, 71, 84, 97, 110, 123, 136, 149, 162, 175, 188, + 201, 214, 227, 240, 253, 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, + 76, 77, 78, 79, 80, 81, 82, 83, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 189, + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 202, 203, 204, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 215, 216, 217, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, + 238, 239, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + + }; + // v = merge_index(v, MAX_PROBS - 1, MODULUS_PARAM); + v = inv_map_table[v]; + m--; + if ((m << 1) <= MAX_PROB) { + return 1 + inv_recenter_nonneg(v + 1, m); + } else { + return MAX_PROB - inv_recenter_nonneg(v + 1, MAX_PROB - 1 - m); + } +} + +static int decode_term_subexp(vp9_reader *r, int k, int num_syms) { + int i = 0, mk = 0, word; + while (1) { + const int b = i ? k + i - 1 : k; + const int a = 1 << b; + if (num_syms <= mk + 3 * a) { + word = decode_uniform(r, num_syms - mk) + mk; + break; + } else { + if (vp9_read_bit(r)) { + i++; + mk += a; + } else { + word = vp9_read_literal(r, b) + mk; + break; + } + } + } + return word; +} + +void vp9_diff_update_prob(vp9_reader *r, vp9_prob* p) { + int delp = decode_term_subexp(r, SUBEXP_PARAM, 255); + *p = (vp9_prob)inv_remap_prob(delp, *p); +} diff --git a/libvpx/vp9/decoder/vp9_dsubexp.h b/libvpx/vp9/decoder/vp9_dsubexp.h new file mode 100644 index 0000000..aeb9399 --- /dev/null +++ b/libvpx/vp9/decoder/vp9_dsubexp.h @@ -0,0 +1,19 @@ +/* + * 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_DECODER_VP9_DSUBEXP_H_ +#define VP9_DECODER_VP9_DSUBEXP_H_ + +#include "vp9/decoder/vp9_dboolhuff.h" + +void vp9_diff_update_prob(vp9_reader *r, vp9_prob* p); + +#endif // VP9_DECODER_VP9_DSUBEXP_H_ diff --git a/libvpx/vp9/decoder/vp9_idct_blk.c b/libvpx/vp9/decoder/vp9_idct_blk.c index c52963c..0217919 100644 --- a/libvpx/vp9/decoder/vp9_idct_blk.c +++ b/libvpx/vp9/decoder/vp9_idct_blk.c @@ -66,7 +66,7 @@ void vp9_idct_add_c(int16_t *input, uint8_t *dest, int stride, int eob) { vp9_short_idct4x4_add(input, dest, stride); vpx_memset(input, 0, 32); } else { - vp9_dc_only_idct_add(input[0], dest, dest, stride, stride); + vp9_short_idct4x4_1_add(input, dest, stride); ((int *)input)[0] = 0; } } diff --git a/libvpx/vp9/decoder/vp9_onyxd_if.c b/libvpx/vp9/decoder/vp9_onyxd_if.c index 3cef88b..cb72920 100644 --- a/libvpx/vp9/decoder/vp9_onyxd_if.c +++ b/libvpx/vp9/decoder/vp9_onyxd_if.c @@ -136,7 +136,7 @@ VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) { // vp9_init_dequantizer() for every frame. vp9_init_dequantizer(&pbi->common); - vp9_loop_filter_init(&pbi->common); + vp9_loop_filter_init(&pbi->common, &pbi->mb.lf); pbi->common.error.setjmp = 0; pbi->decoded_key_frame = 0; @@ -154,7 +154,6 @@ void vp9_remove_decompressor(VP9D_PTR ptr) { vpx_free(pbi->common.last_frame_seg_map); vp9_remove_common(&pbi->common); - vpx_free(pbi->mbc); vpx_free(pbi); } @@ -347,9 +346,9 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, cm->current_video_frame + 1000); #endif - if (cm->filter_level) { + if (!pbi->do_loopfilter_inline) { /* Apply the loop filter if appropriate. */ - vp9_loop_filter_frame(cm, &pbi->mb, cm->filter_level, 0); + vp9_loop_filter_frame(cm, &pbi->mb, pbi->mb.lf.filter_level, 0); } #if WRITE_RECON_BUFFER == 2 @@ -361,8 +360,9 @@ int vp9_receive_compressed_data(VP9D_PTR ptr, cm->current_video_frame + 3000); #endif - vp9_extend_frame_borders(cm->frame_to_show, - cm->subsampling_x, cm->subsampling_y); + vp9_extend_frame_inner_borders(cm->frame_to_show, + cm->subsampling_x, + cm->subsampling_y); } #if WRITE_RECON_BUFFER == 1 @@ -412,9 +412,8 @@ int vp9_get_raw_frame(VP9D_PTR ptr, YV12_BUFFER_CONFIG *sd, *time_stamp = pbi->last_time_stamp; *time_end_stamp = 0; - sd->clrtype = pbi->common.clr_type; #if CONFIG_POSTPROC - ret = vp9_post_proc_frame(&pbi->common, sd, flags); + ret = vp9_post_proc_frame(&pbi->common, &pbi->mb.lf, sd, flags); #else if (pbi->common.frame_to_show) { diff --git a/libvpx/vp9/decoder/vp9_onyxd_int.h b/libvpx/vp9/decoder/vp9_onyxd_int.h index 8698570..4760066 100644 --- a/libvpx/vp9/decoder/vp9_onyxd_int.h +++ b/libvpx/vp9/decoder/vp9_onyxd_int.h @@ -10,13 +10,14 @@ #ifndef VP9_DECODER_VP9_ONYXD_INT_H_ #define VP9_DECODER_VP9_ONYXD_INT_H_ + #include "./vpx_config.h" -#include "vp9/decoder/vp9_onyxd.h" -#include "vp9/decoder/vp9_treereader.h" + #include "vp9/common/vp9_onyxc_int.h" -#include "vp9/decoder/vp9_idct_blk.h" -// #define DEC_DEBUG +#include "vp9/decoder/vp9_idct_blk.h" +#include "vp9/decoder/vp9_onyxd.h" +#include "vp9/decoder/vp9_treereader.h" typedef struct VP9Decompressor { DECLARE_ALIGNED(16, MACROBLOCKD, mb); @@ -28,35 +29,17 @@ typedef struct VP9Decompressor { const uint8_t *source; uint32_t source_sz; - vp9_reader *mbc; int64_t last_time_stamp; int ready_for_new_data; int refresh_frame_flags; - vp9_prob prob_skip_false; int decoded_key_frame; int initial_width; int initial_height; -} VP9D_COMP; - -#if CONFIG_DEBUG -#define CHECK_MEM_ERROR(lval,expr) do {\ - lval = (expr); \ - if(!lval) \ - vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,\ - "Failed to allocate "#lval" at %s:%d", \ - __FILE__,__LINE__);\ - } while(0) -#else -#define CHECK_MEM_ERROR(lval,expr) do {\ - lval = (expr); \ - if(!lval) \ - vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,\ - "Failed to allocate "#lval);\ - } while(0) -#endif + int do_loopfilter_inline; // apply loopfilter to available rows immediately +} VP9D_COMP; #endif // VP9_DECODER_VP9_TREEREADER_H_ diff --git a/libvpx/vp9/decoder/vp9_read_bit_buffer.h b/libvpx/vp9/decoder/vp9_read_bit_buffer.h index f243cb4..c7fa3aa 100644 --- a/libvpx/vp9/decoder/vp9_read_bit_buffer.h +++ b/libvpx/vp9/decoder/vp9_read_bit_buffer.h @@ -51,4 +51,10 @@ static int vp9_rb_read_literal(struct vp9_read_bit_buffer *rb, int bits) { return value; } +static int vp9_rb_read_signed_literal(struct vp9_read_bit_buffer *rb, + int bits) { + const int value = vp9_rb_read_literal(rb, bits); + return vp9_rb_read_bit(rb) ? -value : value; +} + #endif // VP9_READ_BIT_BUFFER_ -- cgit v1.2.3