vp9_decodframe.c 59.8 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
/*
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
 *
 *  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_reconintra4x4.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/decoder/vp9_decodframe.h"
#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/common/vp9_invtrans.h"
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_quant_common.h"
Johann's avatar
Johann committed
#include "vpx_scale/vpx_scale.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"
John Koleszar's avatar
John Koleszar committed
#include "vpx_mem/vpx_mem.h"
#include "vp9/decoder/vp9_dboolhuff.h"
John Koleszar's avatar
John Koleszar committed

#include "vp9/common/vp9_seg_common.h"
#include "vp9/common/vp9_entropy.h"
#include "vp9_rtcd.h"
John Koleszar's avatar
John Koleszar committed
#include <assert.h>
#include <stdio.h>

#define COEFCOUNT_TESTING

// #define DEC_DEBUG
#ifdef DEC_DEBUG
int dec_debug = 0;
#endif

John Koleszar's avatar
John Koleszar committed
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;
John Koleszar's avatar
John Koleszar committed
static int inv_remap_prob(int v, int m) {
  const int n = 256;
  const int modulus = MODULUS_PARAM;
John Koleszar's avatar
John Koleszar committed
  v = merge_index(v, n - 1, modulus);
  if ((m << 1) <= n) {
    i = vp9_inv_recenter_nonneg(v + 1, m);
John Koleszar's avatar
John Koleszar committed
  } else {
    i = n - 1 - vp9_inv_recenter_nonneg(v + 1, n - 1 - m);
John Koleszar's avatar
John Koleszar committed
  }
  return i;
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) {
John Koleszar's avatar
John Koleszar committed
  int i;
  int Q;
  VP9_COMMON *const pc = &pbi->common;
John Koleszar's avatar
John Koleszar committed

  for (Q = 0; Q < QINDEX_RANGE; Q++) {
    pc->Y1dequant[Q][0] = (short)vp9_dc_quant(Q, pc->y1dc_delta_q);
    pc->Y2dequant[Q][0] = (short)vp9_dc2quant(Q, pc->y2dc_delta_q);
    pc->UVdequant[Q][0] = (short)vp9_dc_uv_quant(Q, pc->uvdc_delta_q);
John Koleszar's avatar
John Koleszar committed

    /* all the ac values =; */
    for (i = 1; i < 16; i++) {
      int rc = vp9_default_zig_zag1d[i];
John Koleszar's avatar
John Koleszar committed

      pc->Y1dequant[Q][rc] = (short)vp9_ac_yquant(Q);
      pc->Y2dequant[Q][rc] = (short)vp9_ac2quant(Q, pc->y2ac_delta_q);
      pc->UVdequant[Q][rc] = (short)vp9_ac_uv_quant(Q, pc->uvac_delta_q);
John Koleszar's avatar
John Koleszar committed
    }
John Koleszar's avatar
John Koleszar committed
  }
static void mb_init_dequantizer(VP9D_COMP *pbi, MACROBLOCKD *xd) {
John Koleszar's avatar
John Koleszar committed
  int i;
  int QIndex;
  VP9_COMMON *const pc = &pbi->common;
John Koleszar's avatar
John Koleszar committed
  int segment_id = xd->mode_info_context->mbmi.segment_id;

  // Set the Q baseline allowing for any segment level adjustment
  if (vp9_segfeature_active(xd, segment_id, SEG_LVL_ALT_Q)) {
John Koleszar's avatar
John Koleszar committed
    /* Abs Value */
    if (xd->mb_segment_abs_delta == SEGMENT_ABSDATA)
      QIndex = vp9_get_segdata(xd, segment_id, SEG_LVL_ALT_Q);
John Koleszar's avatar
John Koleszar committed

    /* Delta Value */
    else {
      QIndex = pc->base_qindex +
               vp9_get_segdata(xd, segment_id, SEG_LVL_ALT_Q);
John Koleszar's avatar
John Koleszar committed
      QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0;    /* Clamp to valid range */
John Koleszar's avatar
John Koleszar committed
    }
John Koleszar's avatar
John Koleszar committed
  } else
    QIndex = pc->base_qindex;
Deb Mukherjee's avatar
Deb Mukherjee committed
  xd->q_index = QIndex;
John Koleszar's avatar
John Koleszar committed
  /* Set up the block level dequant pointers */
  for (i = 0; i < 16; i++) {
    xd->block[i].dequant = pc->Y1dequant[QIndex];
  }
Hui Su's avatar
Hui Su committed
#if CONFIG_LOSSLESS
John Koleszar's avatar
John Koleszar committed
  if (!QIndex) {
    pbi->mb.inv_xform4x4_1_x8     = vp9_short_inv_walsh4x4_1_x8;
    pbi->mb.inv_xform4x4_x8       = vp9_short_inv_walsh4x4_x8;
    pbi->mb.inv_walsh4x4_1        = vp9_short_inv_walsh4x4_1_lossless;
    pbi->mb.inv_walsh4x4_lossless = vp9_short_inv_walsh4x4_lossless;
    pbi->idct_add            = vp9_dequant_idct_add_lossless_c;
    pbi->dc_idct_add         = vp9_dequant_dc_idct_add_lossless_c;
    pbi->dc_idct_add_y_block = vp9_dequant_dc_idct_add_y_block_lossless_c;
    pbi->idct_add_y_block    = vp9_dequant_idct_add_y_block_lossless_c;
    pbi->idct_add_uv_block   = vp9_dequant_idct_add_uv_block_lossless_c;
John Koleszar's avatar
John Koleszar committed
  } else {
    pbi->mb.inv_xform4x4_1_x8     = vp9_short_idct4x4llm_1;
    pbi->mb.inv_xform4x4_x8       = vp9_short_idct4x4llm;
    pbi->mb.inv_walsh4x4_1        = vp9_short_inv_walsh4x4_1;
    pbi->mb.inv_walsh4x4_lossless = vp9_short_inv_walsh4x4;
    pbi->idct_add            = vp9_dequant_idct_add;
    pbi->dc_idct_add         = vp9_dequant_dc_idct_add;
    pbi->dc_idct_add_y_block = vp9_dequant_dc_idct_add_y_block;
    pbi->idct_add_y_block    = vp9_dequant_idct_add_y_block;
    pbi->idct_add_uv_block   = vp9_dequant_idct_add_uv_block;
John Koleszar's avatar
John Koleszar committed
  }
  pbi->mb.inv_xform4x4_1_x8     = vp9_short_idct4x4llm_1;
  pbi->mb.inv_xform4x4_x8       = vp9_short_idct4x4llm;
  pbi->mb.inv_walsh4x4_1        = vp9_short_inv_walsh4x4_1;
  pbi->mb.inv_walsh4x4_lossless = vp9_short_inv_walsh4x4;
  pbi->idct_add            = vp9_dequant_idct_add;
  pbi->dc_idct_add         = vp9_dequant_dc_idct_add;
  pbi->dc_idct_add_y_block = vp9_dequant_dc_idct_add_y_block;
  pbi->idct_add_y_block    = vp9_dequant_idct_add_y_block;
  pbi->idct_add_uv_block   = vp9_dequant_idct_add_uv_block;
Hui Su's avatar
Hui Su committed
#endif

John Koleszar's avatar
John Koleszar committed
  for (i = 16; i < 24; i++) {
    xd->block[i].dequant = pc->UVdequant[QIndex];
  }
John Koleszar's avatar
John Koleszar committed
  xd->block[24].dequant = pc->Y2dequant[QIndex];
/* 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) {
John Koleszar's avatar
John Koleszar committed
  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
#if CONFIG_SUPERBLOCKS
    if (xd->mode_info_context->mbmi.encoded_as_sb) {
      vp9_build_intra_predictors_sbuv_s(xd);
      vp9_build_intra_predictors_sby_s(xd);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
    } else {
#endif
    vp9_build_intra_predictors_mbuv_s(xd);
    vp9_build_intra_predictors_mby_s(xd);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
#if CONFIG_SUPERBLOCKS
    }
#endif
John Koleszar's avatar
John Koleszar committed
  } else {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
#if CONFIG_SUPERBLOCKS
    if (xd->mode_info_context->mbmi.encoded_as_sb) {
      vp9_build_inter32x32_predictors_sb(xd,
                                         xd->dst.y_buffer,
                                         xd->dst.u_buffer,
                                         xd->dst.v_buffer,
                                         xd->dst.y_stride,
                                         xd->dst.uv_stride);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
    } else {
#endif
    vp9_build_1st_inter16x16_predictors_mb(xd,
                                           xd->dst.y_buffer,
                                           xd->dst.u_buffer,
                                           xd->dst.v_buffer,
                                           xd->dst.y_stride,
                                           xd->dst.uv_stride);

    if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
      vp9_build_2nd_inter16x16_predictors_mb(xd,
                                             xd->dst.y_buffer,
                                             xd->dst.u_buffer,
                                             xd->dst.v_buffer,
                                             xd->dst.y_stride,
                                             xd->dst.uv_stride);
#if CONFIG_COMP_INTERINTRA_PRED
    else if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) {
      vp9_build_interintra_16x16_predictors_mb(xd,
                                               xd->dst.y_buffer,
                                               xd->dst.u_buffer,
                                               xd->dst.v_buffer,
                                               xd->dst.y_stride,
                                               xd->dst.uv_stride);
    }
#endif
Ronald S. Bultje's avatar
Ronald S. Bultje committed
#if CONFIG_SUPERBLOCKS
    }
#endif
John Koleszar's avatar
John Koleszar committed
  }
static void decode_16x16(VP9D_COMP *pbi, MACROBLOCKD *xd,
                         BOOL_DECODER* const bc) {
  BLOCKD *bd = &xd->block[0];
  TX_TYPE tx_type = get_tx_type_16x16(xd, bd);
  assert(get_2nd_order_usage(xd) == 0);
#ifdef DEC_DEBUG
  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,
                                    xd->dst.y_buffer, 16, xd->dst.y_stride);
  } 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,
      xd->dst.uv_stride, xd->eobs + 16, xd);
}

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, &xd->block[0]);
#ifdef DEC_DEBUG
  if (dec_debug) {
    int i;
    printf("\n");
    printf("qcoeff 8x8\n");
    for (i = 0; i < 400; 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;
    assert(get_2nd_order_usage(xd) == 0);
    for (i = 0; i < 4; i++) {
      int ib = vp9_i8x8_block[i];
      int idx = (ib & 0x02) ? (ib + 2) : ib;
      short *q  = xd->block[idx].qcoeff;
      short *dq = xd->block[0].dequant;
      unsigned char *pre = xd->block[ib].predictor;
      unsigned char *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(b, i8x8mode, b->predictor);
      }
      tx_type = get_tx_type_8x8(xd, &xd->block[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,
                                   0, xd->eobs[idx]);
      }
    }
  } else if (xd->mode_info_context->mbmi.mode == SPLITMV) {
    assert(get_2nd_order_usage(xd) == 0);
    vp9_dequant_idct_add_y_block_8x8(xd->qcoeff,
                                     xd->block[0].dequant,
                                     xd->predictor,
                                     xd->dst.y_buffer,
                                     xd->dst.y_stride,
                                     xd->eobs, xd);
  } else {
    BLOCKD *b = &xd->block[24];
Jim Bankoski's avatar
Jim Bankoski committed
    assert(get_2nd_order_usage(xd) == 1);
    vp9_dequantize_b_2x2(b);
    vp9_short_ihaar2x2(&b->dqcoeff[0], b->diff, 8);
    ((int *)b->qcoeff)[0] = 0;  // 2nd order block are set to 0 after idct
    ((int *)b->qcoeff)[1] = 0;
    ((int *)b->qcoeff)[2] = 0;
    ((int *)b->qcoeff)[3] = 0;
    ((int *)b->qcoeff)[4] = 0;
    ((int *)b->qcoeff)[5] = 0;
    ((int *)b->qcoeff)[6] = 0;
    ((int *)b->qcoeff)[7] = 0;
    vp9_dequant_dc_idct_add_y_block_8x8(xd->qcoeff,
                                        xd->block[0].dequant,
                                        xd->predictor,
                                        xd->dst.y_buffer,
                                        xd->dst.y_stride,
                                        xd->eobs,
                                        xd->block[24].diff,
                                        xd);
  }

  // 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->block[16 + i], i8x8mode, b->predictor);
      pbi->idct_add(b->qcoeff, b->dequant, b->predictor,
                    *(b->base_dst) + b->dst, 8, b->dst_stride);
      b = &xd->block[20 + i];
      vp9_intra_uv4x4_predict(&xd->block[20 + i], i8x8mode, b->predictor);
      pbi->idct_add(b->qcoeff, b->dequant, b->predictor,
                    *(b->base_dst) + b->dst, 8, b->dst_stride);
    }
  } else if (xd->mode_info_context->mbmi.mode == SPLITMV) {
    pbi->idct_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, xd->eobs + 16);
  } 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,
         xd->dst.uv_stride, xd->eobs + 16, xd);
  }
#ifdef 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
}

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 (mode == I8X8_PRED) {
    assert(get_2nd_order_usage(xd) == 0);
    for (i = 0; i < 4; i++) {
      int ib = vp9_i8x8_block[i];
      const int iblock[4] = {0, 1, 4, 5};
      int j;
      int i8x8mode;
      BLOCKD *b;
      b = &xd->block[ib];
      i8x8mode = b->bmi.as_mode.first;
      vp9_intra8x8_predict(b, i8x8mode, b->predictor);
      for (j = 0; j < 4; j++) {
        b = &xd->block[ib + iblock[j]];
        tx_type = get_tx_type_4x4(xd, b);
        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);
        } else {
          vp9_dequant_idct_add(b->qcoeff, b->dequant, b->predictor,
                               *(b->base_dst) + b->dst, 16, b->dst_stride);
        }
      }
      b = &xd->block[16 + i];
      vp9_intra_uv4x4_predict(b, i8x8mode, b->predictor);
      pbi->idct_add(b->qcoeff, b->dequant, b->predictor,
                    *(b->base_dst) + b->dst, 8, b->dst_stride);
      b = &xd->block[20 + i];
      vp9_intra_uv4x4_predict(b, i8x8mode, b->predictor);
      pbi->idct_add(b->qcoeff, b->dequant, b->predictor,
                    *(b->base_dst) + b->dst, 8, b->dst_stride);
    }
  } else if (mode == B_PRED) {
    assert(get_2nd_order_usage(xd) == 0);
    for (i = 0; i < 16; i++) {
      int b_mode;
#if CONFIG_COMP_INTRA_PRED
      int b_mode2;
#endif
      BLOCKD *b = &xd->block[i];
      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(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);
#if CONFIG_COMP_INTRA_PRED
      b_mode2 = xd->mode_info_context->bmi[i].as_mode.second;

      if (b_mode2 == (B_PREDICTION_MODE)(B_DC_PRED - 1)) {
#endif
        vp9_intra4x4_predict(b, b_mode, b->predictor);
#if CONFIG_COMP_INTRA_PRED
      } else {
        vp9_comp_intra4x4_predict(b, b_mode, b_mode2, b->predictor);
      }
#endif
      tx_type = get_tx_type_4x4(xd, b);
      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);
      } else {
        vp9_dequant_idct_add(b->qcoeff, b->dequant, b->predictor,
                             *(b->base_dst) + b->dst, 16, b->dst_stride);
      }
      xd->above_context->y2 = 1;
      xd->left_context->y2 = 1;
    }
    if (!xd->mode_info_context->mbmi.mb_skip_coeff) {
      vp9_decode_mb_tokens_4x4_uv(pbi, xd, bc);
    }
    vp9_build_intra_predictors_mbuv(xd);
    pbi->idct_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,
                           xd->eobs + 16);
  } else if (mode == SPLITMV) {
    assert(get_2nd_order_usage(xd) == 0);
    pbi->idct_add_y_block(xd->qcoeff,
                          xd->block[0].dequant,
                          xd->predictor,
                          xd->dst.y_buffer,
                          xd->dst.y_stride,
                          xd->eobs);
    pbi->idct_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,
                           xd->eobs + 16);
  } else {
#ifdef DEC_DEBUG
    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
    tx_type = get_tx_type_4x4(xd, &xd->block[0]);
    if (tx_type != DCT_DCT) {
      assert(get_2nd_order_usage(xd) == 0);
      for (i = 0; i < 16; i++) {
        BLOCKD *b = &xd->block[i];
        tx_type = get_tx_type_4x4(xd, b);
        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);
        } else {
          vp9_dequant_idct_add(b->qcoeff, b->dequant, b->predictor,
                               *(b->base_dst) + b->dst, 16, b->dst_stride);
        }
      }
    } else {
      BLOCKD *b = &xd->block[24];
Jim Bankoski's avatar
Jim Bankoski committed
      assert(get_2nd_order_usage(xd) == 1);
      vp9_dequantize_b(b);
      if (xd->eobs[24] > 1) {
        vp9_short_inv_walsh4x4(&b->dqcoeff[0], b->diff);
        ((int *)b->qcoeff)[0] = 0;
        ((int *)b->qcoeff)[1] = 0;
        ((int *)b->qcoeff)[2] = 0;
        ((int *)b->qcoeff)[3] = 0;
        ((int *)b->qcoeff)[4] = 0;
        ((int *)b->qcoeff)[5] = 0;
        ((int *)b->qcoeff)[6] = 0;
        ((int *)b->qcoeff)[7] = 0;
      } else {
        xd->inv_walsh4x4_1(&b->dqcoeff[0], b->diff);
        ((int *)b->qcoeff)[0] = 0;
      }
      vp9_dequantize_b(b);
      pbi->dc_idct_add_y_block(xd->qcoeff,
                               xd->block[0].dequant,
                               xd->predictor,
                               xd->dst.y_buffer,
                               xd->dst.y_stride,
                               xd->eobs,
                               xd->block[24].diff);
    }
    pbi->idct_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,
                           xd->eobs + 16);
  }
}

#if CONFIG_SUPERBLOCKS
static void decode_16x16_sb(VP9D_COMP *pbi, MACROBLOCKD *xd,
                            BOOL_DECODER* const bc, int n) {
  int x_idx = n & 1, y_idx = n >> 1;
  TX_TYPE tx_type = get_tx_type_16x16(xd, &xd->block[0]);
  if (tx_type != DCT_DCT) {
    vp9_ht_dequant_idct_add_16x16_c(
        tx_type, xd->qcoeff, xd->block[0].dequant,
        xd->dst.y_buffer + y_idx * 16 * xd->dst.y_stride + x_idx * 16,
        xd->dst.y_buffer + y_idx * 16 * xd->dst.y_stride + x_idx * 16,
        xd->dst.y_stride, xd->dst.y_stride);
  } else {
    vp9_dequant_idct_add_16x16(
        xd->qcoeff, xd->block[0].dequant,
        xd->dst.y_buffer + y_idx * 16 * xd->dst.y_stride + x_idx * 16,
        xd->dst.y_buffer + y_idx * 16 * xd->dst.y_stride + x_idx * 16,
        xd->dst.y_stride, xd->dst.y_stride, xd->eobs[0]);
  }
  vp9_dequant_idct_add_uv_block_8x8_inplace_c(
      xd->qcoeff + 16 * 16,
      xd->block[16].dequant,
      xd->dst.u_buffer + y_idx * 8 * xd->dst.uv_stride + x_idx * 8,
      xd->dst.v_buffer + y_idx * 8 * xd->dst.uv_stride + x_idx * 8,
      xd->dst.uv_stride, xd->eobs + 16, xd);
};

static void decode_8x8_sb(VP9D_COMP *pbi, MACROBLOCKD *xd,
                          BOOL_DECODER* const bc, int n) {
  BLOCKD *b = &xd->block[24];
  int x_idx = n & 1, y_idx = n >> 1;
  TX_TYPE tx_type = get_tx_type_8x8(xd, &xd->block[0]);
  if (tx_type != DCT_DCT) {
    int i;
    for (i = 0; i < 4; i++) {
      int ib = vp9_i8x8_block[i];
      int idx = (ib & 0x02) ? (ib + 2) : ib;
      short *q  = xd->block[idx].qcoeff;
      short *dq = xd->block[0].dequant;
      int stride = xd->dst.y_stride;
      BLOCKD *b = &xd->block[ib];
      tx_type = get_tx_type_8x8(xd, &xd->block[ib]);
      if (tx_type != DCT_DCT) {
        vp9_ht_dequant_idct_add_8x8_c(
            tx_type, q, dq,
            xd->dst.y_buffer + (y_idx * 16 + (i / 2) * 8) * xd->dst.y_stride
            + x_idx * 16 + (i & 1) * 8,
            xd->dst.y_buffer + (y_idx * 16 + (i / 2) * 8) * xd->dst.y_stride
            + x_idx * 16 + (i & 1) * 8,
            stride, stride);
      } else {
        vp9_dequant_idct_add_8x8_c(
            q, dq,
            xd->dst.y_buffer + (y_idx * 16 + (i / 2) * 8) * xd->dst.y_stride
            + x_idx * 16 + (i & 1) * 8,
            xd->dst.y_buffer + (y_idx * 16 + (i / 2) * 8) * xd->dst.y_stride
            + x_idx * 16 + (i & 1) * 8,
            stride, stride, 0, b->eob);
      }
      vp9_dequant_idct_add_uv_block_8x8_inplace_c(
          xd->qcoeff + 16 * 16, xd->block[16].dequant,
          xd->dst.u_buffer + y_idx * 8 * xd->dst.uv_stride + x_idx * 8,
          xd->dst.v_buffer + y_idx * 8 * xd->dst.uv_stride + x_idx * 8,
          xd->dst.uv_stride, xd->eobs + 16, xd);
    }
  } else {
    vp9_dequantize_b_2x2(b);
    vp9_short_ihaar2x2(&b->dqcoeff[0], b->diff, 8);
    ((int *)b->qcoeff)[0] = 0;  // 2nd order block are set to 0 after idct
    ((int *)b->qcoeff)[1] = 0;
    ((int *)b->qcoeff)[2] = 0;
    ((int *)b->qcoeff)[3] = 0;
    ((int *)b->qcoeff)[4] = 0;
    ((int *)b->qcoeff)[5] = 0;
    ((int *)b->qcoeff)[6] = 0;
    ((int *)b->qcoeff)[7] = 0;
    vp9_dequant_dc_idct_add_y_block_8x8_inplace_c(
        xd->qcoeff, xd->block[0].dequant,
        xd->dst.y_buffer + y_idx * 16 * xd->dst.y_stride + x_idx * 16,
        xd->dst.y_stride, xd->eobs, xd->block[24].diff, xd);
    vp9_dequant_idct_add_uv_block_8x8_inplace_c(
        xd->qcoeff + 16 * 16, xd->block[16].dequant,
        xd->dst.u_buffer + y_idx * 8 * xd->dst.uv_stride + x_idx * 8,
        xd->dst.v_buffer + y_idx * 8 * xd->dst.uv_stride + x_idx * 8,
        xd->dst.uv_stride, xd->eobs + 16, xd);
  }
};

static void decode_4x4_sb(VP9D_COMP *pbi, MACROBLOCKD *xd,
                          BOOL_DECODER* const bc, int n) {
  BLOCKD *b = &xd->block[24];
  int x_idx = n & 1, y_idx = n >> 1;
  TX_TYPE tx_type = get_tx_type_4x4(xd, &xd->block[0]);
  if (tx_type != DCT_DCT) {
    int i;
    for (i = 0; i < 16; i++) {
      BLOCKD *b = &xd->block[i];
      tx_type = get_tx_type_4x4(xd, b);
      if (tx_type != DCT_DCT) {
        vp9_ht_dequant_idct_add_c(
            tx_type, b->qcoeff, b->dequant,
            xd->dst.y_buffer + (y_idx * 16 + (i / 4) * 4) * xd->dst.y_stride
            + x_idx * 16 + (i & 3) * 4,
            xd->dst.y_buffer + (y_idx * 16 + (i / 4) * 4) * xd->dst.y_stride
            + x_idx * 16 + (i & 3) * 4,
            xd->dst.y_stride, xd->dst.y_stride);
      } else {
        vp9_dequant_idct_add_c(
            b->qcoeff, b->dequant,
            xd->dst.y_buffer + (y_idx * 16 + (i / 4) * 4) * xd->dst.y_stride
            + x_idx * 16 + (i & 3) * 4,
            xd->dst.y_buffer + (y_idx * 16 + (i / 4) * 4) * xd->dst.y_stride
            + x_idx * 16 + (i & 3) * 4,
            xd->dst.y_stride, xd->dst.y_stride);
      }
    }
  } else {
    vp9_dequantize_b(b);
    if (xd->eobs[24] > 1) {
      vp9_short_inv_walsh4x4(&b->dqcoeff[0], b->diff);
      ((int *)b->qcoeff)[0] = 0;
      ((int *)b->qcoeff)[1] = 0;
      ((int *)b->qcoeff)[2] = 0;
      ((int *)b->qcoeff)[3] = 0;
      ((int *)b->qcoeff)[4] = 0;
      ((int *)b->qcoeff)[5] = 0;
      ((int *)b->qcoeff)[6] = 0;
      ((int *)b->qcoeff)[7] = 0;
    } else {
      xd->inv_walsh4x4_1(&b->dqcoeff[0], b->diff);
      ((int *)b->qcoeff)[0] = 0;
    }
    vp9_dequant_dc_idct_add_y_block_4x4_inplace_c(
        xd->qcoeff, xd->block[0].dequant,
        xd->dst.y_buffer + y_idx * 16 * xd->dst.y_stride + x_idx * 16,
        xd->dst.y_stride, xd->eobs, xd->block[24].diff, xd);
  }
  vp9_dequant_idct_add_uv_block_4x4_inplace_c(
      xd->qcoeff + 16 * 16, xd->block[16].dequant,
      xd->dst.u_buffer + y_idx * 8 * xd->dst.uv_stride + x_idx * 8,
      xd->dst.v_buffer + y_idx * 8 * xd->dst.uv_stride + x_idx * 8,
      xd->dst.uv_stride, xd->eobs + 16, xd);
};

static void decode_superblock(VP9D_COMP *pbi, MACROBLOCKD *xd,
                              int mb_row, unsigned int mb_col,
                              BOOL_DECODER* const bc) {
  int i, n, eobtotal;
  TX_SIZE tx_size = xd->mode_info_context->mbmi.txfm_size;
  VP9_COMMON *const pc = &pbi->common;
  MODE_INFO *orig_mi = xd->mode_info_context;
  const int mis = pc->mode_info_stride;

  assert(xd->mode_info_context->mbmi.encoded_as_sb);

  if (pbi->common.frame_type != KEY_FRAME)
    vp9_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter, pc);

  // re-initialize macroblock dequantizer before detokenization
  if (xd->segmentation_enabled)
    mb_init_dequantizer(pbi, xd);

  if (xd->mode_info_context->mbmi.mb_skip_coeff) {
    vp9_reset_mb_tokens_context(xd);
    if (mb_col < pc->mb_cols - 1)
      xd->above_context++;
    if (mb_row < pc->mb_rows - 1)
      xd->left_context++;
    vp9_reset_mb_tokens_context(xd);
    if (mb_col < pc->mb_cols - 1)
      xd->above_context--;
    if (mb_row < pc->mb_rows - 1)
      xd->left_context--;

    /* Special case:  Force the loopfilter to skip when eobtotal and
     * mb_skip_coeff are zero.
     */
    skip_recon_mb(pbi, xd);
    return;
  }

  /* do prediction */
  if (xd->mode_info_context->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, xd->dst.y_buffer,
                                       xd->dst.u_buffer, xd->dst.v_buffer,
                                       xd->dst.y_stride, xd->dst.uv_stride);
  }

  /* dequantization and idct */
#if CONFIG_TX32X32
  if (xd->mode_info_context->mbmi.txfm_size == TX_32X32) {
    eobtotal = vp9_decode_sb_tokens(pbi, xd, bc);
    if (eobtotal == 0) {  // skip loopfilter
      xd->mode_info_context->mbmi.mb_skip_coeff = 1;
      if (mb_col + 1 < pc->mb_cols)
        xd->mode_info_context[1].mbmi.mb_skip_coeff = 1;
      if (mb_row + 1 < pc->mb_rows) {
        xd->mode_info_context[mis].mbmi.mb_skip_coeff = 1;
        if (mb_col + 1 < pc->mb_cols)
          xd->mode_info_context[mis + 1].mbmi.mb_skip_coeff = 1;
      }
    } else {
      vp9_dequant_idct_add_32x32(xd->sb_coeff_data.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->sb_coeff_data.qcoeff + 1024,
                                            xd->block[16].dequant,
                                            xd->dst.u_buffer, xd->dst.v_buffer,
                                            xd->dst.uv_stride, xd->eobs + 16);
    }
  } else {
#endif
  for (n = 0; n < 4; n++) {
    int x_idx = n & 1, y_idx = n >> 1;

    if (mb_col + x_idx >= pc->mb_cols || mb_row + y_idx >= pc->mb_rows)
      continue;

    xd->above_context = pc->above_context + mb_col + x_idx;
    xd->left_context = pc->left_context + y_idx;
    xd->mode_info_context = orig_mi + x_idx + y_idx * mis;
    for (i = 0; i < 25; i++) {
      xd->block[i].eob = 0;
      xd->eobs[i] = 0;
    }

    eobtotal = vp9_decode_mb_tokens(pbi, xd, bc);
    if (eobtotal == 0) {  // skip loopfilter
      xd->mode_info_context->mbmi.mb_skip_coeff = 1;
      continue;
    }

    if (tx_size == TX_16X16) {
      decode_16x16_sb(pbi, xd, bc, n);
    } else if (tx_size == TX_8X8) {
      decode_8x8_sb(pbi, xd, bc, n);
      decode_4x4_sb(pbi, xd, bc, n);
    }
  }

  xd->above_context = pc->above_context + mb_col;
  xd->left_context = pc->left_context;
  xd->mode_info_context = orig_mi;
#if CONFIG_TX32X32
  }
#endif
static void decode_macroblock(VP9D_COMP *pbi, MACROBLOCKD *xd,
                              int mb_row, unsigned int mb_col,
                              BOOL_DECODER* const bc) {
John Koleszar's avatar
John Koleszar committed
  int eobtotal = 0;
  MB_PREDICTION_MODE mode;
  int i;
Deb Mukherjee's avatar
Deb Mukherjee committed
  int tx_size;
#if CONFIG_SUPERBLOCKS
  assert(!xd->mode_info_context->mbmi.encoded_as_sb);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
#endif
John Koleszar's avatar
John Koleszar committed

  // re-initialize macroblock dequantizer before detokenization
  if (xd->segmentation_enabled)
    mb_init_dequantizer(pbi, xd);

Deb Mukherjee's avatar
Deb Mukherjee committed
  tx_size = xd->mode_info_context->mbmi.txfm_size;
  mode = xd->mode_info_context->mbmi.mode;

John Koleszar's avatar
John Koleszar committed
  if (xd->mode_info_context->mbmi.mb_skip_coeff) {
    vp9_reset_mb_tokens_context(xd);
  } else if (!bool_error(bc)) {
John Koleszar's avatar
John Koleszar committed
    for (i = 0; i < 25; i++) {
      xd->block[i].eob = 0;
      xd->eobs[i] = 0;
    if (mode != B_PRED) {
      eobtotal = vp9_decode_mb_tokens(pbi, xd, bc);
John Koleszar's avatar
John Koleszar committed
  }
  //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,
John Koleszar's avatar
John Koleszar committed
  if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV
      && mode != I8X8_PRED
      && !bool_error(bc)) {
John Koleszar's avatar
John Koleszar committed
    /* Special case:  Force the loopfilter to skip when eobtotal and
     * mb_skip_coeff are zero.
     * */
    xd->mode_info_context->mbmi.mb_skip_coeff = 1;
    skip_recon_mb(pbi, xd);
    return;
John Koleszar's avatar
John Koleszar committed
  }
#ifdef DEC_DEBUG
  if (dec_debug)
    printf("Decoding mb:  %d %d\n", xd->mode_info_context->mbmi.mode, tx_size);
#endif
Yaowu Xu's avatar
Yaowu Xu committed

  // moved to be performed before detokenization
//  if (xd->segmentation_enabled)
//    mb_init_dequantizer(pbi, xd);
John Koleszar's avatar
John Koleszar committed
  /* do prediction */
  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
    if (mode != I8X8_PRED) {
      vp9_build_intra_predictors_mbuv(xd);
John Koleszar's avatar
John Koleszar committed
      if (mode != B_PRED) {
        vp9_build_intra_predictors_mby(xd);
John Koleszar's avatar
John Koleszar committed
      }
John Koleszar's avatar
John Koleszar committed
    }
John Koleszar's avatar
John Koleszar committed
  } else {
#ifdef DEC_DEBUG
  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);
John Koleszar's avatar
John Koleszar committed
  }

  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("final y\n");
John Koleszar's avatar
John Koleszar committed
    for (i = 0; i < 16; i++) {
      for (j = 0; j < 16; j++)
        printf("%3d ", xd->dst.y_buffer[i * xd->dst.y_stride + j]);
      printf("\n");
John Koleszar's avatar
John Koleszar committed
    }
    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");
John Koleszar's avatar
John Koleszar committed
  }
Yaowu Xu's avatar
Yaowu Xu committed
}
static int get_delta_q(vp9_reader *bc, int prev, int *q_update) {
John Koleszar's avatar
John Koleszar committed
  int ret_val = 0;
  if (vp9_read_bit(bc)) {
    ret_val = vp9_read_literal(bc, 4);
    if (vp9_read_bit(bc))
John Koleszar's avatar
John Koleszar committed
      ret_val = -ret_val;
  }
John Koleszar's avatar
John Koleszar committed
  /* Trigger a quantizer update if the delta-q value has changed */
  if (ret_val != prev)
    *q_update = 1;
John Koleszar's avatar
John Koleszar committed
  return ret_val;
John Koleszar's avatar
John Koleszar committed
}

#ifdef PACKET_TESTING
#include <stdio.h>
FILE *vpxlog = 0;
#endif

Adrian Grange's avatar
Adrian Grange committed
/* Decode a row of Superblocks (2x2 region of MBs) */
decode_sb_row(VP9D_COMP *pbi, VP9_COMMON *pc, int mbrow, MACROBLOCKD *xd,
              BOOL_DECODER* const bc) {
John Koleszar's avatar
John Koleszar committed
  int i;
  int sb_col;
  int mb_row, mb_col;
  int recon_yoffset, recon_uvoffset;
  int ref_fb_idx = pc->lst_fb_idx;
  int dst_fb_idx = pc->new_fb_idx;
  int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
  int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
  int row_delta[4] = { 0, +1,  0, -1};
  int col_delta[4] = { +1, -1, +1, +1};
  int sb_cols = (pc->mb_cols + 1) >> 1;

  // For a SB there are 2 left contexts, each pertaining to a MB row within
Ronald S. Bultje's avatar
Ronald S. Bultje committed
  vpx_memset(pc->left_context, 0, sizeof(pc->left_context));
John Koleszar's avatar
John Koleszar committed

  mb_row = mbrow;
  mb_col = 0;

  for (sb_col = 0; sb_col < sb_cols; sb_col++) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
    MODE_INFO *mi = xd->mode_info_context;

#if CONFIG_SUPERBLOCKS
    mi->mbmi.encoded_as_sb = vp9_read(bc, pc->sb_coded);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
#endif

John Koleszar's avatar
John Koleszar committed
    // Process the 4 MBs within the SB in the order:
    // top-left, top-right, bottom-left, bottom-right
    for (i = 0; i < 4; i++) {
      int dy = row_delta[i];
      int dx = col_delta[i];
      int offset_extended = dy * xd->mode_info_stride + dx;

Ronald S. Bultje's avatar
Ronald S. Bultje committed
      mi = xd->mode_info_context;
John Koleszar's avatar
John Koleszar committed
      if ((mb_row >= pc->mb_rows) || (mb_col >= pc->mb_cols)) {
        // MB lies outside frame, skip on to next
        mb_row += dy;
        mb_col += dx;
        xd->mode_info_context += offset_extended;
        xd->prev_mode_info_context += offset_extended;
John Koleszar's avatar
John Koleszar committed
        continue;
      }
#if CONFIG_SUPERBLOCKS
      if (i)
        mi->mbmi.encoded_as_sb = 0;
#endif
Yaowu Xu's avatar
Yaowu Xu committed

John Koleszar's avatar
John Koleszar committed
      // Set above context pointer
      xd->above_context = pc->above_context + mb_col;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
      xd->left_context = pc->left_context + (i >> 1);
John Koleszar's avatar
John Koleszar committed

      /* 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
       */
      xd->mb_to_top_edge = -((mb_row * 16)) << 3;
      xd->mb_to_left_edge = -((mb_col * 16) << 3);
#if CONFIG_SUPERBLOCKS
      if (mi->mbmi.encoded_as_sb) {
        xd->mb_to_bottom_edge = ((pc->mb_rows - 2 - mb_row) * 16) << 3;
        xd->mb_to_right_edge = ((pc->mb_cols - 2 - mb_col) * 16) << 3;
      } else {
#endif
        xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;