Newer
Older
* 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/decoder/vp9_onyxd_int.h"
#include "vp9/common/vp9_header.h"
#include "vp9/common/vp9_reconintra.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/common/vp9_invtrans.h"
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_quant_common.h"
#include "vp9/common/vp9_setupintrarecon.h"
#include "vp9/decoder/vp9_decodemv.h"
#include "vp9/common/vp9_extend.h"
#include "vp9/common/vp9_modecont.h"
#include "vp9/decoder/vp9_dboolhuff.h"
#include "vp9/common/vp9_tile_common.h"
#define COEFCOUNT_TESTING
#ifdef DEC_DEBUG
int dec_debug = 0;
#endif
static int read_le16(const uint8_t *p) {
return (p[1] << 8) | p[0];
}
static int read_le32(const uint8_t *p) {
return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
}
// len == 0 is not allowed
static int read_is_valid(const unsigned char *start, size_t len,
const unsigned char *end) {
return start + len > start && start + len <= end;
}
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 = 256;
const int modulus = MODULUS_PARAM;
return vp9_inv_recenter_nonneg(v + 1, m);
return n - 1 - vp9_inv_recenter_nonneg(v + 1, n - 1 - m);
static vp9_prob read_prob_diff_update(vp9_reader *const bc, int oldp) {
int delp = vp9_decode_term_subexp(bc, SUBEXP_PARAM, 255);
return (vp9_prob)inv_remap_prob(delp, oldp);
void vp9_init_de_quantizer(VP9D_COMP *pbi) {
VP9_COMMON *const pc = &pbi->common;
for (q = 0; q < QINDEX_RANGE; q++) {
pc->Y1dequant[q][0] = (int16_t)vp9_dc_quant(q, pc->y1dc_delta_q);
pc->UVdequant[q][0] = (int16_t)vp9_dc_uv_quant(q, pc->uvdc_delta_q);
/* all the ac values =; */
for (i = 1; i < 16; i++) {
const int rc = vp9_default_zig_zag1d_4x4[i];
pc->Y1dequant[q][rc] = (int16_t)vp9_ac_yquant(q);
pc->UVdequant[q][rc] = (int16_t)vp9_ac_uv_quant(q, pc->uvac_delta_q);
static int get_qindex(MACROBLOCKD *mb, int segment_id, int base_qindex) {
// Set the Q baseline allowing for any segment level adjustment
if (vp9_segfeature_active(mb, segment_id, SEG_LVL_ALT_Q)) {
if (mb->mb_segment_abs_delta == SEGMENT_ABSDATA)
return vp9_get_segdata(mb, segment_id, SEG_LVL_ALT_Q); // Abs Value
else
return clamp(base_qindex + vp9_get_segdata(mb, segment_id, SEG_LVL_ALT_Q),
0, MAXQ); // Delta Value
} else {
return base_qindex;
}
}
static void mb_init_dequantizer(VP9D_COMP *pbi, MACROBLOCKD *mb) {
const int segment_id = mb->mode_info_context->mbmi.segment_id;
const int qindex = get_qindex(mb, segment_id, pc->base_qindex);
for (i = 0; i < 16; i++)
mb->block[i].dequant = pc->Y1dequant[qindex];
for (i = 16; i < 24; i++)
mb->block[i].dequant = pc->UVdequant[qindex];
mb->inv_txm4x4_1 = vp9_short_iwalsh4x4_1;
mb->inv_txm4x4 = vp9_short_iwalsh4x4;
mb->itxm_add = vp9_dequant_idct_add_lossless_c;
mb->itxm_add_y_block = vp9_dequant_idct_add_y_block_lossless_c;
mb->itxm_add_uv_block = vp9_dequant_idct_add_uv_block_lossless_c;
} else {
mb->inv_txm4x4_1 = vp9_short_idct4x4_1;
mb->inv_txm4x4 = vp9_short_idct4x4;
mb->itxm_add = vp9_dequant_idct_add;
mb->itxm_add_y_block = vp9_dequant_idct_add_y_block;
mb->itxm_add_uv_block = vp9_dequant_idct_add_uv_block;
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#if CONFIG_CODE_NONZEROCOUNT
static void propagate_nzcs(VP9_COMMON *cm, MACROBLOCKD *xd) {
MODE_INFO *m = xd->mode_info_context;
BLOCK_SIZE_TYPE sb_type = m->mbmi.sb_type;
const int mis = cm->mode_info_stride;
int n;
if (sb_type == BLOCK_SIZE_SB64X64) {
for (n = 0; n < 16; ++n) {
int i = n >> 2;
int j = n & 3;
if (i == 0 && j == 0) continue;
vpx_memcpy((m + j + mis * i)->mbmi.nzcs, m->mbmi.nzcs,
384 * sizeof(m->mbmi.nzcs[0]));
}
} else if (sb_type == BLOCK_SIZE_SB32X32) {
for (n = 0; n < 4; ++n) {
int i = n >> 1;
int j = n & 1;
if (i == 0 && j == 0) continue;
vpx_memcpy((m + j + mis * i)->mbmi.nzcs, m->mbmi.nzcs,
384 * sizeof(m->mbmi.nzcs[0]));
}
}
}
#endif
/* skip_recon_mb() is Modified: Instead of writing the result to predictor buffer and then copying it
* to dst buffer, we can write the result directly to dst buffer. This eliminates unnecessary copy.
*/
static void skip_recon_mb(VP9D_COMP *pbi, MACROBLOCKD *xd,
int mb_row, int mb_col) {
MODE_INFO *m = xd->mode_info_context;
BLOCK_SIZE_TYPE sb_type = m->mbmi.sb_type;
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
vp9_build_intra_predictors_sb64uv_s(xd);
vp9_build_intra_predictors_sb64y_s(xd);
vp9_build_intra_predictors_sbuv_s(xd);
vp9_build_intra_predictors_sby_s(xd);
vp9_build_intra_predictors_mbuv_s(xd);
vp9_build_intra_predictors_mby_s(xd);
vp9_build_inter64x64_predictors_sb(xd, mb_row, mb_col);
vp9_build_inter32x32_predictors_sb(xd, mb_row, mb_col);
vp9_build_inter16x16_predictors_mb(xd,
xd->dst.y_buffer,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.y_stride,
xd->dst.uv_stride,
mb_row, mb_col);
#if CONFIG_CODE_NONZEROCOUNT
vpx_memset(m->mbmi.nzcs, 0, 384 * sizeof(m->mbmi.nzcs[0]));
propagate_nzcs(&pbi->common, xd);
#endif
static void decode_16x16(VP9D_COMP *pbi, MACROBLOCKD *xd,
BOOL_DECODER* const bc) {
const TX_TYPE tx_type = get_tx_type_16x16(xd, 0);
if (dec_debug) {
int i;
printf("\n");
printf("qcoeff 16x16\n");
for (i = 0; i < 400; i++) {
printf("%3d ", xd->qcoeff[i]);
if (i % 16 == 15) printf("\n");
}
printf("\n");
printf("predictor\n");
for (i = 0; i < 400; i++) {
printf("%3d ", xd->predictor[i]);
if (i % 16 == 15) printf("\n");
}
}
#endif
if (tx_type != DCT_DCT) {
vp9_ht_dequant_idct_add_16x16_c(tx_type, xd->qcoeff,
xd->block[0].dequant, xd->predictor,
} else {
vp9_dequant_idct_add_16x16(xd->qcoeff, xd->block[0].dequant,
xd->predictor, xd->dst.y_buffer,
16, xd->dst.y_stride, xd->eobs[0]);
}
vp9_dequant_idct_add_uv_block_8x8(
xd->qcoeff + 16 * 16, xd->block[16].dequant,
xd->predictor + 16 * 16, xd->dst.u_buffer, xd->dst.v_buffer,
}
static void decode_8x8(VP9D_COMP *pbi, MACROBLOCKD *xd,
BOOL_DECODER* const bc) {
// First do Y
// if the first one is DCT_DCT assume all the rest are as well
TX_TYPE tx_type = get_tx_type_8x8(xd, 0);
if (dec_debug) {
int i;
printf("\n");
printf("qcoeff 8x8\n");
for (i = 0; i < 384; i++) {
printf("%3d ", xd->qcoeff[i]);
if (i % 16 == 15) printf("\n");
}
}
#endif
if (tx_type != DCT_DCT || xd->mode_info_context->mbmi.mode == I8X8_PRED) {
int i;
for (i = 0; i < 4; i++) {
int ib = vp9_i8x8_block[i];
int idx = (ib & 0x02) ? (ib + 2) : ib;
int16_t *q = xd->block[idx].qcoeff;
int16_t *dq = xd->block[0].dequant;
uint8_t *pre = xd->block[ib].predictor;
uint8_t *dst = *(xd->block[ib].base_dst) + xd->block[ib].dst;
int stride = xd->dst.y_stride;
BLOCKD *b = &xd->block[ib];
if (xd->mode_info_context->mbmi.mode == I8X8_PRED) {
int i8x8mode = b->bmi.as_mode.first;
vp9_intra8x8_predict(xd, b, i8x8mode, b->predictor);
tx_type = get_tx_type_8x8(xd, ib);
if (tx_type != DCT_DCT) {
vp9_ht_dequant_idct_add_8x8_c(tx_type, q, dq, pre, dst, 16, stride,
} else {
vp9_dequant_idct_add_8x8_c(q, dq, pre, dst, 16, stride,
vp9_dequant_idct_add_y_block_8x8(xd->qcoeff,
xd->block[0].dequant,
xd->predictor,
xd->dst.y_buffer,
xd->dst.y_stride,
}
// Now do UV
if (xd->mode_info_context->mbmi.mode == I8X8_PRED) {
int i;
for (i = 0; i < 4; i++) {
int ib = vp9_i8x8_block[i];
BLOCKD *b = &xd->block[ib];
int i8x8mode = b->bmi.as_mode.first;
b = &xd->block[16 + i];
vp9_intra_uv4x4_predict(xd, b, i8x8mode, b->predictor);
xd->itxm_add(b->qcoeff, b->dequant, b->predictor,
*(b->base_dst) + b->dst, 8, b->dst_stride, xd->eobs[16 + i]);
b = &xd->block[20 + i];
vp9_intra_uv4x4_predict(xd, b, i8x8mode, b->predictor);
xd->itxm_add(b->qcoeff, b->dequant, b->predictor,
*(b->base_dst) + b->dst, 8, b->dst_stride, xd->eobs[20 + i]);
}
} else if (xd->mode_info_context->mbmi.mode == SPLITMV) {
xd->itxm_add_uv_block(xd->qcoeff + 16 * 16, xd->block[16].dequant,
xd->predictor + 16 * 16, xd->dst.u_buffer, xd->dst.v_buffer,
} else {
vp9_dequant_idct_add_uv_block_8x8
(xd->qcoeff + 16 * 16, xd->block[16].dequant,
xd->predictor + 16 * 16, xd->dst.u_buffer, xd->dst.v_buffer,
if (dec_debug) {
int i;
printf("\n");
printf("predictor\n");
for (i = 0; i < 384; i++) {
printf("%3d ", xd->predictor[i]);
if (i % 16 == 15) printf("\n");
}
}
#endif
}
static void decode_4x4(VP9D_COMP *pbi, MACROBLOCKD *xd,
BOOL_DECODER* const bc) {
TX_TYPE tx_type;
int i, eobtotal = 0;
MB_PREDICTION_MODE mode = xd->mode_info_context->mbmi.mode;
#if 0 // def DEC_DEBUG
if (dec_debug) {
int i;
printf("\n");
printf("predictor\n");
for (i = 0; i < 384; i++) {
printf("%3d ", xd->predictor[i]);
if (i % 16 == 15) printf("\n");
}
}
#endif
if (mode == I8X8_PRED) {
for (i = 0; i < 4; i++) {
int ib = vp9_i8x8_block[i];
const int iblock[4] = {0, 1, 4, 5};
int j;
BLOCKD *b = &xd->block[ib];
int i8x8mode = b->bmi.as_mode.first;
vp9_intra8x8_predict(xd, b, i8x8mode, b->predictor);
for (j = 0; j < 4; j++) {
b = &xd->block[ib + iblock[j]];
tx_type = get_tx_type_4x4(xd, ib + iblock[j]);
if (tx_type != DCT_DCT) {
vp9_ht_dequant_idct_add_c(tx_type, b->qcoeff,
b->dequant, b->predictor,
*(b->base_dst) + b->dst, 16,
b->dst_stride, xd->eobs[ib + iblock[j]]);
xd->itxm_add(b->qcoeff, b->dequant, b->predictor,
*(b->base_dst) + b->dst, 16, b->dst_stride,
xd->eobs[ib + iblock[j]]);
}
}
b = &xd->block[16 + i];
vp9_intra_uv4x4_predict(xd, b, i8x8mode, b->predictor);
xd->itxm_add(b->qcoeff, b->dequant, b->predictor,
*(b->base_dst) + b->dst, 8, b->dst_stride, xd->eobs[16 + i]);
b = &xd->block[20 + i];
vp9_intra_uv4x4_predict(xd, b, i8x8mode, b->predictor);
xd->itxm_add(b->qcoeff, b->dequant, b->predictor,
*(b->base_dst) + b->dst, 8, b->dst_stride, xd->eobs[20 + i]);
}
} else if (mode == B_PRED) {
for (i = 0; i < 16; i++) {
BLOCKD *b = &xd->block[i];
int b_mode = xd->mode_info_context->bmi[i].as_mode.first;
#if CONFIG_NEWBINTRAMODES
xd->mode_info_context->bmi[i].as_mode.context = b->bmi.as_mode.context =
vp9_find_bpred_context(xd, b);
#endif
if (!xd->mode_info_context->mbmi.mb_skip_coeff)
eobtotal += vp9_decode_coefs_4x4(pbi, xd, bc, PLANE_TYPE_Y_WITH_DC, i);
vp9_intra4x4_predict(xd, b, b_mode, b->predictor);
tx_type = get_tx_type_4x4(xd, i);
if (tx_type != DCT_DCT) {
vp9_ht_dequant_idct_add_c(tx_type, b->qcoeff,
b->dequant, b->predictor,
xd->itxm_add(b->qcoeff, b->dequant, b->predictor,
*(b->base_dst) + b->dst, 16, b->dst_stride, xd->eobs[i]);
}
}
if (!xd->mode_info_context->mbmi.mb_skip_coeff) {
vp9_decode_mb_tokens_4x4_uv(pbi, xd, bc);
}
vp9_build_intra_predictors_mbuv(xd);
xd->itxm_add_uv_block(xd->qcoeff + 16 * 16,
xd->block[16].dequant,
xd->predictor + 16 * 16,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.uv_stride,
} else if (mode == SPLITMV || get_tx_type_4x4(xd, 0) == DCT_DCT) {
xd->block[0].dequant,
xd->predictor,
xd->dst.y_buffer,
xd->dst.y_stride,
xd->itxm_add_uv_block(xd->qcoeff + 16 * 16,
xd->block[16].dequant,
xd->predictor + 16 * 16,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.uv_stride,
if (dec_debug) {
int i;
printf("\n");
printf("qcoeff 4x4\n");
for (i = 0; i < 400; i++) {
printf("%3d ", xd->qcoeff[i]);
if (i % 16 == 15) printf("\n");
}
printf("\n");
printf("predictor\n");
for (i = 0; i < 400; i++) {
printf("%3d ", xd->predictor[i]);
if (i % 16 == 15) printf("\n");
}
}
#endif
for (i = 0; i < 16; i++) {
BLOCKD *b = &xd->block[i];
tx_type = get_tx_type_4x4(xd, i);
if (tx_type != DCT_DCT) {
vp9_ht_dequant_idct_add_c(tx_type, b->qcoeff,
b->dequant, b->predictor,
*(b->base_dst) + b->dst, 16,
xd->itxm_add(b->qcoeff, b->dequant, b->predictor,
*(b->base_dst) + b->dst, 16, b->dst_stride, xd->eobs[i]);
xd->itxm_add_uv_block(xd->qcoeff + 16 * 16,
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
xd->block[16].dequant,
xd->predictor + 16 * 16,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.uv_stride,
xd);
}
}
static INLINE void decode_sb_8x8(MACROBLOCKD *mb, int y_size) {
const int y_count = y_size * y_size;
const int uv_size = y_size / 2;
const int uv_count = uv_size * uv_size;
const int u_qcoeff_offset = 64 * y_count;
const int v_qcoeff_offset = u_qcoeff_offset + 64 * uv_count;
const int u_eob_offset = 4 * y_count;
const int v_eob_offset = u_eob_offset + 4 * uv_count;
int n;
// luma
for (n = 0; n < y_count; n++) {
const int x_idx = n % y_size;
const int y_idx = n / y_size;
const int y_offset = (y_idx * 8) * mb->dst.y_stride + (x_idx * 8);
const TX_TYPE tx_type = get_tx_type_8x8(mb,
(y_idx * 2 * y_size + x_idx) * 2);
if (tx_type == DCT_DCT) {
vp9_dequant_idct_add_8x8_c(mb->qcoeff + n * 64,
mb->block[0].dequant,
mb->dst.y_buffer + y_offset,
mb->dst.y_buffer + y_offset,
mb->dst.y_stride, mb->dst.y_stride,
mb->eobs[n * 4]);
} else {
vp9_ht_dequant_idct_add_8x8_c(tx_type, mb->qcoeff + n * 64,
mb->block[0].dequant,
mb->dst.y_buffer + y_offset,
mb->dst.y_buffer + y_offset,
mb->dst.y_stride, mb->dst.y_stride,
mb->eobs[n * 4]);
}
}
// chroma
for (n = 0; n < uv_count; n++) {
const int x_idx = n % uv_size;
const int y_idx = n / uv_size;
const int uv_offset = (y_idx * 8) * mb->dst.uv_stride + (x_idx * 8);
vp9_dequant_idct_add_8x8_c(mb->qcoeff + u_qcoeff_offset + n * 64,
mb->block[16].dequant,
mb->dst.u_buffer + uv_offset,
mb->dst.u_buffer + uv_offset,
mb->dst.uv_stride, mb->dst.uv_stride,
mb->eobs[u_eob_offset + n * 4]);
vp9_dequant_idct_add_8x8_c(mb->qcoeff + v_qcoeff_offset + n * 64,
mb->block[20].dequant,
mb->dst.v_buffer + uv_offset,
mb->dst.v_buffer + uv_offset,
mb->dst.uv_stride, mb->dst.uv_stride,
mb->eobs[v_eob_offset + n * 4]);
}
}
static void decode_sb_4x4(MACROBLOCKD *mb, int y_size) {
const int y_count = y_size * y_size;
const int uv_size = y_size / 2;
const int uv_count = uv_size * uv_size;
const int u_qcoeff_offset = y_count * 16;
const int v_qcoeff_offset = u_qcoeff_offset + uv_count * 16;
const int u_eob_offset = y_count;
const int v_eob_offset = u_eob_offset + uv_count;
int n;
for (n = 0; n < y_count; n++) {
const int x_idx = n % y_size;
const int y_idx = n / y_size;
const int y_offset = (y_idx * 4) * mb->dst.y_stride + (x_idx * 4);
const TX_TYPE tx_type = get_tx_type_4x4(mb, y_idx * (y_size*2) + x_idx);
if (tx_type == DCT_DCT) {
mb->itxm_add(mb->qcoeff + n * 16,
mb->block[0].dequant,
mb->dst.y_buffer + y_offset,
mb->dst.y_buffer + y_offset,
mb->dst.y_stride, mb->dst.y_stride,
mb->eobs[n]);
} else {
vp9_ht_dequant_idct_add_c(tx_type, mb->qcoeff + n * 16,
mb->block[0].dequant,
mb->dst.y_buffer + y_offset,
mb->dst.y_buffer + y_offset,
mb->dst.y_stride,
mb->dst.y_stride,
mb->eobs[n]);
}
}
for (n = 0; n < uv_count; n++) {
const int x_idx = n % uv_size;
const int y_idx = n / uv_size;
const int uv_offset = (y_idx * 4) * mb->dst.uv_stride + (x_idx * 4);
mb->itxm_add(mb->qcoeff + u_qcoeff_offset + n * 16,
mb->block[16].dequant,
mb->dst.u_buffer + uv_offset,
mb->dst.u_buffer + uv_offset,
mb->dst.uv_stride, mb->dst.uv_stride, mb->eobs[u_eob_offset + n]);
mb->itxm_add(mb->qcoeff + v_qcoeff_offset + n * 16,
mb->block[20].dequant,
mb->dst.v_buffer + uv_offset,
mb->dst.v_buffer + uv_offset,
mb->dst.uv_stride, mb->dst.uv_stride, mb->eobs[v_eob_offset + n]);
static void decode_sb64(VP9D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col,
BOOL_DECODER* const bc) {
VP9_COMMON *const pc = &pbi->common;
MODE_INFO *mi = xd->mode_info_context;
const int mis = pc->mode_info_stride;
assert(mi->mbmi.sb_type == BLOCK_SIZE_SB64X64);
if (pbi->common.frame_type != KEY_FRAME)
vp9_setup_interp_filters(xd, mi->mbmi.interp_filter, pc);
// re-initialize macroblock dequantizer before detokenization
if (xd->segmentation_enabled)
mb_init_dequantizer(pbi, xd);
if (mi->mbmi.mb_skip_coeff) {
vp9_reset_sb64_tokens_context(xd);
// Special case: Force the loopfilter to skip when eobtotal and
// mb_skip_coeff are zero.
skip_recon_mb(pbi, xd, mb_row, mb_col);
// do prediction
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
vp9_build_intra_predictors_sb64y_s(xd);
vp9_build_intra_predictors_sb64uv_s(xd);
} else {
vp9_build_inter64x64_predictors_sb(xd, mb_row, mb_col);
// dequantization and idct
eobtotal = vp9_decode_sb64_tokens(pbi, xd, bc);
if (eobtotal == 0) { // skip loopfilter
const int x_idx = n & 3, y_idx = n >> 2;
if (mb_col + x_idx < pc->mb_cols && mb_row + y_idx < pc->mb_rows)
mi[y_idx * mis + x_idx].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff;
}
} else {
switch (xd->mode_info_context->mbmi.txfm_size) {
case TX_32X32:
for (n = 0; n < 4; n++) {
const int x_idx = n & 1, y_idx = n >> 1;
const int y_offset = x_idx * 32 + y_idx * xd->dst.y_stride * 32;
vp9_dequant_idct_add_32x32(xd->qcoeff + n * 1024,
xd->block[0].dequant,
xd->dst.y_buffer + y_offset,
xd->dst.y_buffer + y_offset,
xd->dst.y_stride, xd->dst.y_stride, xd->eobs[n * 64]);
}
vp9_dequant_idct_add_32x32(xd->qcoeff + 4096,
xd->block[16].dequant, xd->dst.u_buffer, xd->dst.u_buffer,
xd->dst.uv_stride, xd->dst.uv_stride, xd->eobs[256]);
vp9_dequant_idct_add_32x32(xd->qcoeff + 4096 + 1024,
xd->block[20].dequant, xd->dst.v_buffer, xd->dst.v_buffer,
xd->dst.uv_stride, xd->dst.uv_stride, xd->eobs[320]);
break;
for (n = 0; n < 16; n++) {
const int x_idx = n & 3, y_idx = n >> 2;
const int y_offset = y_idx * 16 * xd->dst.y_stride + x_idx * 16;
const TX_TYPE tx_type = get_tx_type_16x16(xd,
(y_idx * 16 + x_idx) * 4);
if (tx_type == DCT_DCT) {
vp9_dequant_idct_add_16x16(xd->qcoeff + n * 256,
xd->block[0].dequant,
xd->dst.y_buffer + y_offset,
xd->dst.y_buffer + y_offset,
xd->dst.y_stride, xd->dst.y_stride, xd->eobs[n * 16]);
} else {
vp9_ht_dequant_idct_add_16x16_c(tx_type, xd->qcoeff + n * 256,
xd->block[0].dequant,
xd->dst.y_buffer + y_offset,
xd->dst.y_buffer + y_offset,
xd->dst.y_stride, xd->dst.y_stride, xd->eobs[n * 16]);
}
}
for (n = 0; n < 4; n++) {
const int x_idx = n & 1, y_idx = n >> 1;
const int uv_offset = y_idx * 16 * xd->dst.uv_stride + x_idx * 16;
vp9_dequant_idct_add_16x16(xd->qcoeff + 4096 + n * 256,
xd->block[16].dequant,
xd->dst.u_buffer + uv_offset,
xd->dst.u_buffer + uv_offset,
xd->dst.uv_stride, xd->dst.uv_stride, xd->eobs[256 + n * 16]);
vp9_dequant_idct_add_16x16(xd->qcoeff + 4096 + 1024 + n * 256,
xd->block[20].dequant,
xd->dst.v_buffer + uv_offset,
xd->dst.v_buffer + uv_offset,
xd->dst.uv_stride, xd->dst.uv_stride, xd->eobs[320 + n * 16]);
}
break;
decode_sb_8x8(xd, 8);
decode_sb_4x4(xd, 16);
break;
default: assert(0);
#if CONFIG_CODE_NONZEROCOUNT
propagate_nzcs(&pbi->common, xd);
#endif
static void decode_sb32(VP9D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col,
BOOL_DECODER* const bc) {
MODE_INFO *mi = xd->mode_info_context;
assert(mi->mbmi.sb_type == BLOCK_SIZE_SB32X32);
if (pbi->common.frame_type != KEY_FRAME)
vp9_setup_interp_filters(xd, mi->mbmi.interp_filter, pc);
// re-initialize macroblock dequantizer before detokenization
if (xd->segmentation_enabled)
mb_init_dequantizer(pbi, xd);
if (mi->mbmi.mb_skip_coeff) {
vp9_reset_sb_tokens_context(xd);
// Special case: Force the loopfilter to skip when eobtotal and
// mb_skip_coeff are zero.
skip_recon_mb(pbi, xd, mb_row, mb_col);
// do prediction
if (mi->mbmi.ref_frame == INTRA_FRAME) {
vp9_build_intra_predictors_sby_s(xd);
vp9_build_intra_predictors_sbuv_s(xd);
} else {
vp9_build_inter32x32_predictors_sb(xd, mb_row, mb_col);
// dequantization and idct
eobtotal = vp9_decode_sb_tokens(pbi, xd, bc);
if (eobtotal == 0) { // skip loopfilter
mi->mbmi.mb_skip_coeff = 1;
if (mb_col + 1 < pc->mb_cols)
mi[1].mbmi.mb_skip_coeff = 1;
if (mb_row + 1 < pc->mb_rows) {
mi[mis].mbmi.mb_skip_coeff = 1;
mi[mis + 1].mbmi.mb_skip_coeff = 1;
switch (xd->mode_info_context->mbmi.txfm_size) {
case TX_32X32:
vp9_dequant_idct_add_32x32(xd->qcoeff, xd->block[0].dequant,
xd->dst.y_buffer, xd->dst.y_buffer,
xd->dst.y_stride, xd->dst.y_stride,
xd->eobs[0]);
vp9_dequant_idct_add_uv_block_16x16_c(xd->qcoeff + 1024,
xd->block[16].dequant,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.uv_stride, xd);
break;
for (n = 0; n < 4; n++) {
const int x_idx = n & 1, y_idx = n >> 1;
const int y_offset = y_idx * 16 * xd->dst.y_stride + x_idx * 16;
const TX_TYPE tx_type = get_tx_type_16x16(xd,
(y_idx * 8 + x_idx) * 4);
if (tx_type == DCT_DCT) {
vp9_dequant_idct_add_16x16(
xd->qcoeff + n * 256, xd->block[0].dequant,
xd->dst.y_buffer + y_offset,
xd->dst.y_buffer + y_offset,
xd->dst.y_stride, xd->dst.y_stride, xd->eobs[n * 16]);
} else {
vp9_ht_dequant_idct_add_16x16_c(tx_type, xd->qcoeff + n * 256,
xd->block[0].dequant,
xd->dst.y_buffer + y_offset,
xd->dst.y_buffer + y_offset,
xd->dst.y_stride, xd->dst.y_stride, xd->eobs[n * 16]);
}
}
vp9_dequant_idct_add_uv_block_16x16_c(xd->qcoeff + 1024,
xd->block[16].dequant,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.uv_stride, xd);
break;
decode_sb_8x8(xd, 4);
decode_sb_4x4(xd, 8);
break;
default: assert(0);
#if CONFIG_CODE_NONZEROCOUNT
propagate_nzcs(&pbi->common, xd);
#endif
static void decode_mb(VP9D_COMP *pbi, MACROBLOCKD *xd,
int mb_row, int mb_col,
BOOL_DECODER* const bc) {
const MB_PREDICTION_MODE mode = xd->mode_info_context->mbmi.mode;
const int tx_size = xd->mode_info_context->mbmi.txfm_size;
assert(!xd->mode_info_context->mbmi.sb_type);
// re-initialize macroblock dequantizer before detokenization
if (xd->segmentation_enabled)
mb_init_dequantizer(pbi, xd);
vp9_reset_mb_tokens_context(xd);
eobtotal = vp9_decode_mb_tokens(pbi, xd, bc);
//mode = xd->mode_info_context->mbmi.mode;
if (pbi->common.frame_type != KEY_FRAME)
vp9_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter,
if (eobtotal == 0 &&
mode != B_PRED &&
mode != SPLITMV &&
mode != I8X8_PRED &&
!bool_error(bc)) {
// Special case: Force the loopfilter to skip when eobtotal and
// mb_skip_coeff are zero.
skip_recon_mb(pbi, xd, mb_row, mb_col);
if (dec_debug)
printf("Decoding mb: %d %d\n", xd->mode_info_context->mbmi.mode, tx_size);
#endif
// moved to be performed before detokenization
// if (xd->segmentation_enabled)
// mb_init_dequantizer(pbi, xd);
// do prediction
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
if (mode != I8X8_PRED) {
vp9_build_intra_predictors_mbuv(xd);
if (mode != B_PRED)
vp9_build_intra_predictors_mby(xd);
if (dec_debug)
printf("Decoding mb: %d %d interp %d\n",
xd->mode_info_context->mbmi.mode, tx_size,
xd->mode_info_context->mbmi.interp_filter);
#endif
vp9_build_inter_predictors_mb(xd, mb_row, mb_col);
if (tx_size == TX_16X16) {
decode_16x16(pbi, xd, bc);
} else if (tx_size == TX_8X8) {
decode_8x8(pbi, xd, bc);
} else {
decode_4x4(pbi, xd, bc);
}
#ifdef DEC_DEBUG
if (dec_debug) {
int i, j;
printf("\n");
printf("predictor y\n");
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++)
printf("%3d ", xd->predictor[i * 16 + j]);
printf("\n");
}
printf("\n");
for (j = 0; j < 16; j++)
printf("%3d ", xd->dst.y_buffer[i * xd->dst.y_stride + j]);
printf("\n");
printf("\n");
printf("final u\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++)
printf("%3d ", xd->dst.u_buffer[i * xd->dst.uv_stride + j]);
printf("\n");
printf("\n");
printf("final v\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++)
printf("%3d ", xd->dst.v_buffer[i * xd->dst.uv_stride + j]);
printf("\n");
static int get_delta_q(vp9_reader *bc, int prev, int *q_update) {
if (vp9_read_bit(bc)) {
ret_val = vp9_read_literal(bc, 4);
// Trigger a quantizer update if the delta-q value has changed
}
#ifdef PACKET_TESTING
#include <stdio.h>
FILE *vpxlog = 0;
#endif
static void set_offsets(VP9D_COMP *pbi, int block_size,
int mb_row, int mb_col) {
VP9_COMMON *const cm = &pbi->common;
MACROBLOCKD *const xd = &pbi->mb;
const int mis = cm->mode_info_stride;
const int idx = mis * mb_row + mb_col;
const int dst_fb_idx = cm->new_fb_idx;
const int recon_y_stride = cm->yv12_fb[dst_fb_idx].y_stride;
const int recon_uv_stride = cm->yv12_fb[dst_fb_idx].uv_stride;
const int recon_yoffset = mb_row * 16 * recon_y_stride + 16 * mb_col;
const int recon_uvoffset = mb_row * 8 * recon_uv_stride + 8 * mb_col;
xd->mode_info_context = cm->mi + idx;
xd->mode_info_context->mbmi.sb_type = block_size >> 5;
xd->prev_mode_info_context = cm->prev_mi + idx;
xd->above_context = cm->above_context + mb_col;
xd->left_context = cm->left_context + (mb_row & 3);
// 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
set_mb_row(cm, xd, mb_row, block_size);
set_mb_col(cm, xd, mb_col, block_size);
xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
}
static void set_refs(VP9D_COMP *pbi, int block_size, int mb_row, int mb_col) {
VP9_COMMON *const cm = &pbi->common;
MACROBLOCKD *const xd = &pbi->mb;
MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
// Select the appropriate reference frame for this MB
const int fb_idx = cm->active_ref_idx[mbmi->ref_frame - 1];
const YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[fb_idx];
xd->scale_factor[0] = cm->active_ref_scale[mbmi->ref_frame - 1];
xd->scale_factor_uv[0] = cm->active_ref_scale[mbmi->ref_frame - 1];
setup_pred_block(&xd->pre, cfg, mb_row, mb_col,
&xd->scale_factor[0], &xd->scale_factor_uv[0]);
xd->corrupted |= cfg->corrupted;
// Select the appropriate reference frame for this MB
const int second_fb_idx = cm->active_ref_idx[mbmi->second_ref_frame - 1];
const YV12_BUFFER_CONFIG *second_cfg = &cm->yv12_fb[second_fb_idx];
setup_pred_block(&xd->second_pre, second_cfg, mb_row, mb_col,
&xd->scale_factor[1], &xd->scale_factor_uv[1]);
xd->corrupted |= second_cfg->corrupted;
/* Decode a row of Superblocks (2x2 region of MBs) */
static void decode_sb_row(VP9D_COMP *pbi, VP9_COMMON *pc,
int mb_row, MACROBLOCKD *xd,
BOOL_DECODER* const bc) {
int mb_col;
// 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));
for (mb_col = pc->cur_tile_mb_col_start;
mb_col < pc->cur_tile_mb_col_end; mb_col += 4) {
if (vp9_read(bc, pc->prob_sb64_coded)) {
dec_debug = (pc->current_video_frame == 11 && pc->show_frame &&
mb_row == 8 && mb_col == 0);