vpx/vp9/decoder/vp9_detokenize.c
Ronald S. Bultje d3724abe9f Re-add support for ADST in superblocks.
This also changes the RD search to take account of the correct block
index when searching (this is required for ADST positioning to work
correctly in combination with tx_select).

Change-Id: Ie50d05b3a024a64ecd0b376887aa38ac5f7b6af6
2013-03-07 11:19:10 -08:00

629 lines
21 KiB
C

/*
* 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_blockd.h"
#include "vp9/decoder/vp9_onyxd_int.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/common/vp9_seg_common.h"
#define EOB_CONTEXT_NODE 0
#define ZERO_CONTEXT_NODE 1
#define ONE_CONTEXT_NODE 2
#define LOW_VAL_CONTEXT_NODE 3
#define TWO_CONTEXT_NODE 4
#define THREE_CONTEXT_NODE 5
#define HIGH_LOW_CONTEXT_NODE 6
#define CAT_ONE_CONTEXT_NODE 7
#define CAT_THREEFOUR_CONTEXT_NODE 8
#define CAT_THREE_CONTEXT_NODE 9
#define CAT_FIVE_CONTEXT_NODE 10
#define CAT1_MIN_VAL 5
#define CAT2_MIN_VAL 7
#define CAT3_MIN_VAL 11
#define CAT4_MIN_VAL 19
#define CAT5_MIN_VAL 35
#define CAT6_MIN_VAL 67
#define CAT1_PROB0 159
#define CAT2_PROB0 145
#define CAT2_PROB1 165
#define CAT3_PROB0 140
#define CAT3_PROB1 148
#define CAT3_PROB2 173
#define CAT4_PROB0 135
#define CAT4_PROB1 140
#define CAT4_PROB2 155
#define CAT4_PROB3 176
#define CAT5_PROB0 130
#define CAT5_PROB1 134
#define CAT5_PROB2 141
#define CAT5_PROB3 157
#define CAT5_PROB4 180
static const vp9_prob cat6_prob[15] = {
254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0
};
DECLARE_ALIGNED(16, extern const uint8_t, vp9_norm[256]);
static int get_signed(BOOL_DECODER *br, int value_to_sign) {
return decode_bool(br, 128) ? -value_to_sign : value_to_sign;
}
#define INCREMENT_COUNT(token) \
do { \
coef_counts[type][ref][get_coef_band(txfm_size, c)][pt][token]++; \
pt = vp9_get_coef_context(&recent_energy, token); \
} while (0)
#if CONFIG_CODE_NONZEROCOUNT
#define WRITE_COEF_CONTINUE(val, token) \
{ \
qcoeff_ptr[scan[c]] = (int16_t) get_signed(br, val); \
INCREMENT_COUNT(token); \
c++; \
nzc++; \
continue; \
}
#else
#define WRITE_COEF_CONTINUE(val, token) \
{ \
qcoeff_ptr[scan[c]] = (int16_t) get_signed(br, val); \
INCREMENT_COUNT(token); \
c++; \
continue; \
}
#endif // CONFIG_CODE_NONZEROCOUNT
#define ADJUST_COEF(prob, bits_count) \
do { \
if (vp9_read(br, prob)) \
val += (uint16_t)(1 << bits_count);\
} while (0);
static int decode_coefs(VP9D_COMP *dx, const MACROBLOCKD *xd,
BOOL_DECODER* const br, int block_idx,
PLANE_TYPE type, int seg_eob, int16_t *qcoeff_ptr,
TX_SIZE txfm_size) {
ENTROPY_CONTEXT* const A0 = (ENTROPY_CONTEXT *) xd->above_context;
ENTROPY_CONTEXT* const L0 = (ENTROPY_CONTEXT *) xd->left_context;
int aidx, lidx;
ENTROPY_CONTEXT above_ec, left_ec;
FRAME_CONTEXT *const fc = &dx->common.fc;
int recent_energy = 0;
int pt, c = 0;
vp9_coeff_probs *coef_probs;
vp9_prob *prob;
vp9_coeff_count *coef_counts;
const int ref = xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME;
#if CONFIG_CODE_NONZEROCOUNT
uint16_t nzc = 0;
uint16_t nzc_expected = xd->mode_info_context->mbmi.nzcs[block_idx];
#endif
const int *scan;
if (xd->mode_info_context->mbmi.sb_type == BLOCK_SIZE_SB64X64) {
aidx = vp9_block2above_sb64[txfm_size][block_idx];
lidx = vp9_block2left_sb64[txfm_size][block_idx];
} else if (xd->mode_info_context->mbmi.sb_type == BLOCK_SIZE_SB32X32) {
aidx = vp9_block2above_sb[txfm_size][block_idx];
lidx = vp9_block2left_sb[txfm_size][block_idx];
} else {
aidx = vp9_block2above[txfm_size][block_idx];
lidx = vp9_block2left[txfm_size][block_idx];
}
switch (txfm_size) {
default:
case TX_4X4: {
const TX_TYPE tx_type = get_tx_type_4x4(xd, block_idx);
switch (tx_type) {
default:
scan = vp9_default_zig_zag1d_4x4;
break;
case ADST_DCT:
scan = vp9_row_scan_4x4;
break;
case DCT_ADST:
scan = vp9_col_scan_4x4;
break;
}
above_ec = A0[aidx] != 0;
left_ec = L0[lidx] != 0;
coef_probs = fc->coef_probs_4x4;
coef_counts = fc->coef_counts_4x4;
break;
}
case TX_8X8:
scan = vp9_default_zig_zag1d_8x8;
coef_probs = fc->coef_probs_8x8;
coef_counts = fc->coef_counts_8x8;
above_ec = (A0[aidx] + A0[aidx + 1]) != 0;
left_ec = (L0[lidx] + L0[lidx + 1]) != 0;
break;
case TX_16X16:
scan = vp9_default_zig_zag1d_16x16;
coef_probs = fc->coef_probs_16x16;
coef_counts = fc->coef_counts_16x16;
if (type == PLANE_TYPE_UV) {
ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
above_ec = (A0[aidx] + A0[aidx + 1] + A1[aidx] + A1[aidx + 1]) != 0;
left_ec = (L0[lidx] + L0[lidx + 1] + L1[lidx] + L1[lidx + 1]) != 0;
} else {
above_ec = (A0[aidx] + A0[aidx + 1] + A0[aidx + 2] + A0[aidx + 3]) != 0;
left_ec = (L0[lidx] + L0[lidx + 1] + L0[lidx + 2] + L0[lidx + 3]) != 0;
}
break;
case TX_32X32:
scan = vp9_default_zig_zag1d_32x32;
coef_probs = fc->coef_probs_32x32;
coef_counts = fc->coef_counts_32x32;
if (type == PLANE_TYPE_UV) {
ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
ENTROPY_CONTEXT *A2 = (ENTROPY_CONTEXT *) (xd->above_context + 2);
ENTROPY_CONTEXT *L2 = (ENTROPY_CONTEXT *) (xd->left_context + 2);
ENTROPY_CONTEXT *A3 = (ENTROPY_CONTEXT *) (xd->above_context + 3);
ENTROPY_CONTEXT *L3 = (ENTROPY_CONTEXT *) (xd->left_context + 3);
above_ec = (A0[aidx] + A0[aidx + 1] + A1[aidx] + A1[aidx + 1] +
A2[aidx] + A2[aidx + 1] + A3[aidx] + A3[aidx + 1]) != 0;
left_ec = (L0[lidx] + L0[lidx + 1] + L1[lidx] + L1[lidx + 1] +
L2[lidx] + L2[lidx + 1] + L3[lidx] + L3[lidx + 1]) != 0;
} else {
ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
above_ec = (A0[aidx] + A0[aidx + 1] + A0[aidx + 2] + A0[aidx + 3] +
A1[aidx] + A1[aidx + 1] + A1[aidx + 2] + A1[aidx + 3]) != 0;
left_ec = (L0[lidx] + L0[lidx + 1] + L0[lidx + 2] + L0[lidx + 3] +
L1[lidx] + L1[lidx + 1] + L1[lidx + 2] + L1[lidx + 3]) != 0;
}
break;
}
VP9_COMBINEENTROPYCONTEXTS(pt, above_ec, left_ec);
while (1) {
int val;
const uint8_t *cat6 = cat6_prob;
if (c >= seg_eob)
break;
#if CONFIG_CODE_NONZEROCOUNT
if (nzc == nzc_expected)
break;
#endif
prob = coef_probs[type][ref][get_coef_band(txfm_size, c)][pt];
#if CONFIG_CODE_NONZEROCOUNT == 0
if (!vp9_read(br, prob[EOB_CONTEXT_NODE]))
break;
#endif
SKIP_START:
if (c >= seg_eob)
break;
#if CONFIG_CODE_NONZEROCOUNT
if (nzc == nzc_expected)
break;
// decode zero node only if there are zeros left
if (seg_eob - nzc_expected - c + nzc > 0)
#endif
if (!vp9_read(br, prob[ZERO_CONTEXT_NODE])) {
INCREMENT_COUNT(ZERO_TOKEN);
++c;
prob = coef_probs[type][ref][get_coef_band(txfm_size, c)][pt];
goto SKIP_START;
}
// ONE_CONTEXT_NODE_0_
if (!vp9_read(br, prob[ONE_CONTEXT_NODE])) {
WRITE_COEF_CONTINUE(1, ONE_TOKEN);
}
// LOW_VAL_CONTEXT_NODE_0_
if (!vp9_read(br, prob[LOW_VAL_CONTEXT_NODE])) {
if (!vp9_read(br, prob[TWO_CONTEXT_NODE])) {
WRITE_COEF_CONTINUE(2, TWO_TOKEN);
}
if (!vp9_read(br, prob[THREE_CONTEXT_NODE])) {
WRITE_COEF_CONTINUE(3, THREE_TOKEN);
}
WRITE_COEF_CONTINUE(4, FOUR_TOKEN);
}
// HIGH_LOW_CONTEXT_NODE_0_
if (!vp9_read(br, prob[HIGH_LOW_CONTEXT_NODE])) {
if (!vp9_read(br, prob[CAT_ONE_CONTEXT_NODE])) {
val = CAT1_MIN_VAL;
ADJUST_COEF(CAT1_PROB0, 0);
WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY1);
}
val = CAT2_MIN_VAL;
ADJUST_COEF(CAT2_PROB1, 1);
ADJUST_COEF(CAT2_PROB0, 0);
WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY2);
}
// CAT_THREEFOUR_CONTEXT_NODE_0_
if (!vp9_read(br, prob[CAT_THREEFOUR_CONTEXT_NODE])) {
if (!vp9_read(br, prob[CAT_THREE_CONTEXT_NODE])) {
val = CAT3_MIN_VAL;
ADJUST_COEF(CAT3_PROB2, 2);
ADJUST_COEF(CAT3_PROB1, 1);
ADJUST_COEF(CAT3_PROB0, 0);
WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY3);
}
val = CAT4_MIN_VAL;
ADJUST_COEF(CAT4_PROB3, 3);
ADJUST_COEF(CAT4_PROB2, 2);
ADJUST_COEF(CAT4_PROB1, 1);
ADJUST_COEF(CAT4_PROB0, 0);
WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY4);
}
// CAT_FIVE_CONTEXT_NODE_0_:
if (!vp9_read(br, prob[CAT_FIVE_CONTEXT_NODE])) {
val = CAT5_MIN_VAL;
ADJUST_COEF(CAT5_PROB4, 4);
ADJUST_COEF(CAT5_PROB3, 3);
ADJUST_COEF(CAT5_PROB2, 2);
ADJUST_COEF(CAT5_PROB1, 1);
ADJUST_COEF(CAT5_PROB0, 0);
WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY5);
}
val = 0;
while (*cat6) {
val = (val << 1) | vp9_read(br, *cat6++);
}
val += CAT6_MIN_VAL;
WRITE_COEF_CONTINUE(val, DCT_VAL_CATEGORY6);
}
#if CONFIG_CODE_NONZEROCOUNT == 0
if (c < seg_eob)
coef_counts[type][ref][get_coef_band(txfm_size, c)][pt][DCT_EOB_TOKEN]++;
#endif
A0[aidx] = L0[lidx] = c > 0;
if (txfm_size >= TX_8X8) {
A0[aidx + 1] = L0[lidx + 1] = A0[aidx];
if (txfm_size >= TX_16X16) {
if (type == PLANE_TYPE_UV) {
ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
A1[aidx] = A1[aidx + 1] = L1[lidx] = L1[lidx + 1] = A0[aidx];
if (txfm_size >= TX_32X32) {
ENTROPY_CONTEXT *A2 = (ENTROPY_CONTEXT *) (xd->above_context + 2);
ENTROPY_CONTEXT *L2 = (ENTROPY_CONTEXT *) (xd->left_context + 2);
ENTROPY_CONTEXT *A3 = (ENTROPY_CONTEXT *) (xd->above_context + 3);
ENTROPY_CONTEXT *L3 = (ENTROPY_CONTEXT *) (xd->left_context + 3);
A2[aidx] = A2[aidx + 1] = A3[aidx] = A3[aidx + 1] = A0[aidx];
L2[lidx] = L2[lidx + 1] = L3[lidx] = L3[lidx + 1] = A0[aidx];
}
} else {
A0[aidx + 2] = A0[aidx + 3] = L0[lidx + 2] = L0[lidx + 3] = A0[aidx];
if (txfm_size >= TX_32X32) {
ENTROPY_CONTEXT *A1 = (ENTROPY_CONTEXT *) (xd->above_context + 1);
ENTROPY_CONTEXT *L1 = (ENTROPY_CONTEXT *) (xd->left_context + 1);
A1[aidx] = A1[aidx + 1] = A1[aidx + 2] = A1[aidx + 3] = A0[aidx];
L1[lidx] = L1[lidx + 1] = L1[lidx + 2] = L1[lidx + 3] = A0[aidx];
}
}
}
}
return c;
}
static int get_eob(MACROBLOCKD* const xd, int segment_id, int eob_max) {
return vp9_get_segdata(xd, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
}
int vp9_decode_sb_tokens(VP9D_COMP* const pbi,
MACROBLOCKD* const xd,
BOOL_DECODER* const bc) {
const int segment_id = xd->mode_info_context->mbmi.segment_id;
int i, eobtotal = 0, seg_eob, c;
switch (xd->mode_info_context->mbmi.txfm_size) {
case TX_32X32:
// Luma block
c = decode_coefs(pbi, xd, bc, 0, PLANE_TYPE_Y_WITH_DC,
get_eob(xd, segment_id, 1024), xd->qcoeff, TX_32X32);
xd->eobs[0] = c;
eobtotal += c;
// 16x16 chroma blocks
seg_eob = get_eob(xd, segment_id, 256);
for (i = 64; i < 96; i += 16) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
xd->qcoeff + i * 16, TX_16X16);
xd->eobs[i] = c;
eobtotal += c;
}
break;
case TX_16X16:
// 16x16 luma blocks
seg_eob = get_eob(xd, segment_id, 256);
for (i = 0; i < 64; i += 16) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
seg_eob, xd->qcoeff + i * 16, TX_16X16);
xd->eobs[i] = c;
eobtotal += c;
}
// 16x16 chroma blocks
for (i = 64; i < 96; i += 16) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
xd->qcoeff + i * 16, TX_16X16);
xd->eobs[i] = c;
eobtotal += c;
}
break;
case TX_8X8:
// 8x8 luma blocks
seg_eob = get_eob(xd, segment_id, 64);
for (i = 0; i < 64; i += 4) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
seg_eob, xd->qcoeff + i * 16, TX_8X8);
xd->eobs[i] = c;
eobtotal += c;
}
// 8x8 chroma blocks
for (i = 64; i < 96; i += 4) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
xd->qcoeff + i * 16, TX_8X8);
xd->eobs[i] = c;
eobtotal += c;
}
break;
case TX_4X4:
// 4x4 luma blocks
seg_eob = get_eob(xd, segment_id, 16);
for (i = 0; i < 64; i++) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
seg_eob, xd->qcoeff + i * 16, TX_4X4);
xd->eobs[i] = c;
eobtotal += c;
}
// 4x4 chroma blocks
for (i = 64; i < 96; i++) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
xd->qcoeff + i * 16, TX_4X4);
xd->eobs[i] = c;
eobtotal += c;
}
break;
default: assert(0);
}
return eobtotal;
}
int vp9_decode_sb64_tokens(VP9D_COMP* const pbi,
MACROBLOCKD* const xd,
BOOL_DECODER* const bc) {
const int segment_id = xd->mode_info_context->mbmi.segment_id;
int i, eobtotal = 0, seg_eob, c;
switch (xd->mode_info_context->mbmi.txfm_size) {
case TX_32X32:
// Luma block
seg_eob = get_eob(xd, segment_id, 1024);
for (i = 0; i < 256; i += 64) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
seg_eob, xd->qcoeff + i * 16, TX_32X32);
xd->eobs[i] = c;
eobtotal += c;
}
// 32x32 chroma blocks
for (i = 256; i < 384; i += 64) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
xd->qcoeff + i * 16, TX_32X32);
xd->eobs[i] = c;
eobtotal += c;
}
break;
case TX_16X16:
// 16x16 luma blocks
seg_eob = get_eob(xd, segment_id, 256);
for (i = 0; i < 256; i += 16) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
seg_eob, xd->qcoeff + i * 16, TX_16X16);
xd->eobs[i] = c;
eobtotal += c;
}
// 16x16 chroma blocks
for (i = 256; i < 384; i += 16) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
xd->qcoeff + i * 16, TX_16X16);
xd->eobs[i] = c;
eobtotal += c;
}
break;
case TX_8X8:
// 8x8 luma blocks
seg_eob = get_eob(xd, segment_id, 64);
for (i = 0; i < 256; i += 4) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
seg_eob, xd->qcoeff + i * 16, TX_8X8);
xd->eobs[i] = c;
eobtotal += c;
}
// 8x8 chroma blocks
for (i = 256; i < 384; i += 4) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
xd->qcoeff + i * 16, TX_8X8);
xd->eobs[i] = c;
eobtotal += c;
}
break;
case TX_4X4:
// 4x4 luma blocks
seg_eob = get_eob(xd, segment_id, 16);
for (i = 0; i < 256; i++) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
seg_eob, xd->qcoeff + i * 16, TX_4X4);
xd->eobs[i] = c;
eobtotal += c;
}
// 4x4 chroma blocks
for (i = 256; i < 384; i++) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV, seg_eob,
xd->qcoeff + i * 16, TX_4X4);
xd->eobs[i] = c;
eobtotal += c;
}
break;
default: assert(0);
}
return eobtotal;
}
static int vp9_decode_mb_tokens_16x16(VP9D_COMP* const pbi,
MACROBLOCKD* const xd,
BOOL_DECODER* const bc) {
const int segment_id = xd->mode_info_context->mbmi.segment_id;
int i, eobtotal = 0, seg_eob;
// Luma block
int c = decode_coefs(pbi, xd, bc, 0, PLANE_TYPE_Y_WITH_DC,
get_eob(xd, segment_id, 256), xd->qcoeff, TX_16X16);
xd->eobs[0] = c;
eobtotal += c;
// 8x8 chroma blocks
seg_eob = get_eob(xd, segment_id, 64);
for (i = 16; i < 24; i += 4) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV,
seg_eob, xd->block[i].qcoeff, TX_8X8);
xd->eobs[i] = c;
eobtotal += c;
}
return eobtotal;
}
static int vp9_decode_mb_tokens_8x8(VP9D_COMP* const pbi,
MACROBLOCKD* const xd,
BOOL_DECODER* const bc) {
int c, i, eobtotal = 0, seg_eob;
const int segment_id = xd->mode_info_context->mbmi.segment_id;
// luma blocks
seg_eob = get_eob(xd, segment_id, 64);
for (i = 0; i < 16; i += 4) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_Y_WITH_DC,
seg_eob, xd->block[i].qcoeff, TX_8X8);
xd->eobs[i] = c;
eobtotal += c;
}
// chroma blocks
if (xd->mode_info_context->mbmi.mode == I8X8_PRED ||
xd->mode_info_context->mbmi.mode == SPLITMV) {
// use 4x4 transform for U, V components in I8X8/splitmv prediction mode
seg_eob = get_eob(xd, segment_id, 16);
for (i = 16; i < 24; i++) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV,
seg_eob, xd->block[i].qcoeff, TX_4X4);
xd->eobs[i] = c;
eobtotal += c;
}
} else {
for (i = 16; i < 24; i += 4) {
c = decode_coefs(pbi, xd, bc, i, PLANE_TYPE_UV,
seg_eob, xd->block[i].qcoeff, TX_8X8);
xd->eobs[i] = c;
eobtotal += c;
}
}
return eobtotal;
}
static int decode_coefs_4x4(VP9D_COMP *dx, MACROBLOCKD *xd,
BOOL_DECODER* const bc,
PLANE_TYPE type, int i, int seg_eob) {
int c = decode_coefs(dx, xd, bc, i, type, seg_eob,
xd->block[i].qcoeff, TX_4X4);
xd->eobs[i] = c;
return c;
}
int vp9_decode_coefs_4x4(VP9D_COMP *dx, MACROBLOCKD *xd,
BOOL_DECODER* const bc,
PLANE_TYPE type, int i) {
const int segment_id = xd->mode_info_context->mbmi.segment_id;
const int seg_eob = get_eob(xd, segment_id, 16);
return decode_coefs_4x4(dx, xd, bc, type, i, seg_eob);
}
static int decode_mb_tokens_4x4_uv(VP9D_COMP* const dx,
MACROBLOCKD* const xd,
BOOL_DECODER* const bc,
int seg_eob) {
int eobtotal = 0, i;
// chroma blocks
for (i = 16; i < 24; i++) {
eobtotal += decode_coefs_4x4(dx, xd, bc, PLANE_TYPE_UV, i, seg_eob);
}
return eobtotal;
}
int vp9_decode_mb_tokens_4x4_uv(VP9D_COMP* const dx,
MACROBLOCKD* const xd,
BOOL_DECODER* const bc) {
const int segment_id = xd->mode_info_context->mbmi.segment_id;
const int seg_eob = get_eob(xd, segment_id, 16);
return decode_mb_tokens_4x4_uv(dx, xd, bc, seg_eob);
}
static int vp9_decode_mb_tokens_4x4(VP9D_COMP* const dx,
MACROBLOCKD* const xd,
BOOL_DECODER* const bc) {
int i, eobtotal = 0;
const int segment_id = xd->mode_info_context->mbmi.segment_id;
const int seg_eob = get_eob(xd, segment_id, 16);
// luma blocks
for (i = 0; i < 16; ++i) {
eobtotal += decode_coefs_4x4(dx, xd, bc, PLANE_TYPE_Y_WITH_DC, i, seg_eob);
}
// chroma blocks
eobtotal += decode_mb_tokens_4x4_uv(dx, xd, bc, seg_eob);
return eobtotal;
}
int vp9_decode_mb_tokens(VP9D_COMP* const dx,
MACROBLOCKD* const xd,
BOOL_DECODER* const bc) {
const TX_SIZE tx_size = xd->mode_info_context->mbmi.txfm_size;
switch (tx_size) {
case TX_16X16:
return vp9_decode_mb_tokens_16x16(dx, xd, bc);
case TX_8X8:
return vp9_decode_mb_tokens_8x8(dx, xd, bc);
default:
assert(tx_size == TX_4X4);
return vp9_decode_mb_tokens_4x4(dx, xd, bc);
}
}