vp9_decodframe.c 57.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_common.h"
#include "vp9/common/vp9_header.h"
#include "vp9/common/vp9_reconintra.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/common/vp9_entropy.h"
#include "vp9/decoder/vp9_decodframe.h"
#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/common/vp9_invtrans.h"
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_quant_common.h"
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_tile_common.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

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 uint8_t *start, size_t len,
                         const uint8_t *end) {
  return start + len > start && start + len <= end;
}

static TXFM_MODE read_txfm_mode(vp9_reader *r) {
  TXFM_MODE mode = vp9_read_literal(r, 2);
  if (mode == ALLOW_32X32)
    mode += vp9_read_bit(r);
  return mode;
}

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 > (m << 1))
    return v;
  else if ((v & 1) == 0)
    return (v >> 1) + m;
  else
    return m - ((v + 1) >> 1);
}

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;
        word = vp9_read_literal(r, b) + mk;
static int decode_unsigned_max(vp9_reader *r, int max) {
  int data = 0, bit = 0, lmax = max;

  while (lmax) {
    data |= vp9_read_bit(r) << bit++;
    lmax >>= 1;
  }
  return data > max ? max : data;
}

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) {
    return inv_recenter_nonneg(v + 1, m);
John Koleszar's avatar
John Koleszar committed
  } else {
    return n - 1 - inv_recenter_nonneg(v + 1, n - 1 - m);
John Koleszar's avatar
John Koleszar committed
  }
static vp9_prob 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);
void vp9_init_de_quantizer(VP9D_COMP *pbi) {
John Koleszar's avatar
John Koleszar committed
  int i;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  int q;
  VP9_COMMON *const pc = &pbi->common;
John Koleszar's avatar
John Koleszar committed

Dmitry Kovalev's avatar
Dmitry Kovalev committed
  for (q = 0; q < QINDEX_RANGE; q++) {
    pc->y_dequant[q][0] = (int16_t)vp9_dc_quant(q, pc->y_dc_delta_q);
    pc->uv_dequant[q][0] = (int16_t)vp9_dc_uv_quant(q, pc->uv_dc_delta_q);
John Koleszar's avatar
John Koleszar committed

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

Dmitry Kovalev's avatar
Dmitry Kovalev committed
      pc->y_dequant[q][rc] = (int16_t)vp9_ac_yquant(q);
      pc->uv_dequant[q][rc] = (int16_t)vp9_ac_uv_quant(q, pc->uv_ac_delta_q);
John Koleszar's avatar
John Koleszar committed
    }
John Koleszar's avatar
John Koleszar committed
  }
Dmitry Kovalev's avatar
Dmitry Kovalev committed
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)) {
    const int data = vp9_get_segdata(mb, segment_id, SEG_LVL_ALT_Q);
    return mb->mb_segment_abs_delta == SEGMENT_ABSDATA ?
               data :  // Abs value
               clamp(base_qindex + data, 0, MAXQ);  // Delta value
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  } else {
    return base_qindex;
  }
}

static void mb_init_dequantizer(VP9D_COMP *pbi, MACROBLOCKD *mb) {
John Koleszar's avatar
John Koleszar committed
  int i;

Dmitry Kovalev's avatar
Dmitry Kovalev committed
  VP9_COMMON *const pc = &pbi->common;
  const int segment_id = mb->mode_info_context->mbmi.segment_id;
  const int qindex = get_qindex(mb, segment_id, pc->base_qindex);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  mb->q_index = qindex;
Dmitry Kovalev's avatar
Dmitry Kovalev committed

Dmitry Kovalev's avatar
Dmitry Kovalev committed
  for (i = 0; i < 16; i++)
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    mb->block[i].dequant = pc->y_dequant[qindex];
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  for (i = 16; i < 24; i++)
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    mb->block[i].dequant = pc->uv_dequant[qindex];
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  if (mb->lossless) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    assert(qindex == 0);
    mb->inv_txm4x4_1      = vp9_short_iwalsh4x4_1;
    mb->inv_txm4x4        = vp9_short_iwalsh4x4;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    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;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    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;
John Koleszar's avatar
John Koleszar committed
  }
#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

static void decode_16x16(MACROBLOCKD *xd) {
  const TX_TYPE tx_type = get_tx_type_16x16(xd, 0);
  vp9_dequant_iht_add_16x16_c(tx_type, xd->plane[0].qcoeff,
                              xd->block[0].dequant, xd->dst.y_buffer,
                              xd->dst.y_stride, xd->plane[0].eobs[0]);

  vp9_dequant_idct_add_8x8(xd->plane[1].qcoeff, xd->block[16].dequant,
                           xd->dst.u_buffer, xd->dst.uv_stride,
                           xd->plane[1].eobs[0]);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  vp9_dequant_idct_add_8x8(xd->plane[2].qcoeff, xd->block[20].dequant,
                           xd->dst.v_buffer, xd->dst.uv_stride,
                           xd->plane[2].eobs[0]);
static void decode_8x8(MACROBLOCKD *xd) {
  const MB_PREDICTION_MODE mode = xd->mode_info_context->mbmi.mode;
  // luma
  // 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 (tx_type != DCT_DCT || 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  = BLOCK_OFFSET(xd->plane[0].qcoeff, idx, 16);
      int16_t *dq = xd->block[0].dequant;
      uint8_t *dst = *(xd->block[ib].base_dst) + xd->block[ib].dst;
      int stride = xd->dst.y_stride;
      if (mode == I8X8_PRED) {
        BLOCKD *b = &xd->block[ib];
        int i8x8mode = b->bmi.as_mode.first;
        vp9_intra8x8_predict(xd, b, i8x8mode, dst, stride);
      tx_type = get_tx_type_8x8(xd, ib);
      vp9_dequant_iht_add_8x8_c(tx_type, q, dq, dst, stride,
                                xd->plane[0].eobs[idx]);
  } else {
    vp9_dequant_idct_add_y_block_8x8(xd->plane[0].qcoeff,
                                     xd->block[0].dequant, xd->dst.y_buffer,
                                     xd->dst.y_stride, xd);
  // chroma
  if (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->base_dst) + b->dst,
                              b->dst_stride);
      xd->itxm_add(BLOCK_OFFSET(xd->plane[1].qcoeff, i, 16),
                   b->dequant, *(b->base_dst) + b->dst, b->dst_stride,
                   xd->plane[1].eobs[i]);
      b = &xd->block[20 + i];
      vp9_intra_uv4x4_predict(xd, b, i8x8mode, *(b->base_dst) + b->dst,
                              b->dst_stride);
      xd->itxm_add(BLOCK_OFFSET(xd->plane[2].qcoeff, i, 16),
                   b->dequant, *(b->base_dst) + b->dst, b->dst_stride,
                   xd->plane[2].eobs[i]);
  } else if (mode == SPLITMV) {
    xd->itxm_add_uv_block(xd->plane[1].qcoeff, xd->block[16].dequant,
         xd->dst.u_buffer, xd->dst.uv_stride, xd->plane[1].eobs);
    xd->itxm_add_uv_block(xd->plane[2].qcoeff, xd->block[16].dequant,
         xd->dst.v_buffer, xd->dst.uv_stride, xd->plane[2].eobs);
    vp9_dequant_idct_add_8x8(xd->plane[1].qcoeff, xd->block[16].dequant,
                             xd->dst.u_buffer, xd->dst.uv_stride,
                             xd->plane[1].eobs[0]);

    vp9_dequant_idct_add_8x8(xd->plane[2].qcoeff, xd->block[16].dequant,
                             xd->dst.v_buffer, xd->dst.uv_stride,
                             xd->plane[2].eobs[0]);
static INLINE void dequant_add_y(MACROBLOCKD *xd, TX_TYPE tx_type, int idx) {
  BLOCKD *const b = &xd->block[idx];
  struct mb_plane *const y = &xd->plane[0];
  if (tx_type != DCT_DCT) {
    vp9_dequant_iht_add_c(tx_type,
                          BLOCK_OFFSET(y->qcoeff, idx, 16),
                          b->dequant, *(b->base_dst) + b->dst,
                          b->dst_stride, y->eobs[idx]);
  } else {
    xd->itxm_add(BLOCK_OFFSET(y->qcoeff, idx, 16),
                 b->dequant, *(b->base_dst) + b->dst,
                 b->dst_stride, y->eobs[idx]);
  }
}


static void decode_4x4(VP9D_COMP *pbi, MACROBLOCKD *xd, vp9_reader *r) {
  const MB_PREDICTION_MODE mode = xd->mode_info_context->mbmi.mode;
  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;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
      BLOCKD *b = &xd->block[ib];
      int i8x8mode = b->bmi.as_mode.first;
      vp9_intra8x8_predict(xd, b, i8x8mode, *(b->base_dst) + b->dst,
                           b->dst_stride);
      for (j = 0; j < 4; j++) {
        tx_type = get_tx_type_4x4(xd, ib + iblock[j]);
        dequant_add_y(xd, tx_type, ib + iblock[j]);
      }
      b = &xd->block[16 + i];
      vp9_intra_uv4x4_predict(xd, b, i8x8mode, *(b->base_dst) + b->dst,
                              b->dst_stride);
      xd->itxm_add(BLOCK_OFFSET(xd->plane[1].qcoeff, i, 16),
                   b->dequant, *(b->base_dst) + b->dst, b->dst_stride,
                   xd->plane[1].eobs[i]);
      b = &xd->block[20 + i];
      vp9_intra_uv4x4_predict(xd, b, i8x8mode, *(b->base_dst) + b->dst,
                              b->dst_stride);
      xd->itxm_add(BLOCK_OFFSET(xd->plane[2].qcoeff, i, 16),
                   b->dequant, *(b->base_dst) + b->dst, b->dst_stride,
                   xd->plane[2].eobs[i]);
Yaowu Xu's avatar
Yaowu Xu committed
  } else if (mode == I4X4_PRED) {
    for (i = 0; i < 16; i++) {
      BLOCKD *b = &xd->block[i];
Dmitry Kovalev's avatar
Dmitry Kovalev committed
      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);
      if (!xd->mode_info_context->mbmi.mb_skip_coeff)
        vp9_decode_coefs_4x4(pbi, xd, r, PLANE_TYPE_Y_WITH_DC, i);
      vp9_intra4x4_predict(xd, b, b_mode, *(b->base_dst) + b->dst,
                           b->dst_stride);
      tx_type = get_tx_type_4x4(xd, i);
      dequant_add_y(xd, tx_type, i);
#if CONFIG_NEWBINTRAMODES
    if (!xd->mode_info_context->mbmi.mb_skip_coeff)
      vp9_decode_mb_tokens_4x4_uv(pbi, xd, r);
    vp9_build_intra_predictors_sbuv_s(xd, BLOCK_SIZE_MB16X16);
    xd->itxm_add_uv_block(xd->plane[1].qcoeff, xd->block[16].dequant,
         xd->dst.u_buffer, xd->dst.uv_stride, xd->plane[1].eobs);
    xd->itxm_add_uv_block(xd->plane[2].qcoeff, xd->block[16].dequant,
         xd->dst.v_buffer, xd->dst.uv_stride, xd->plane[2].eobs);
  } else if (mode == SPLITMV || get_tx_type_4x4(xd, 0) == DCT_DCT) {
    xd->itxm_add_y_block(xd->plane[0].qcoeff,
                          xd->block[0].dequant,
                          xd->dst.y_buffer, xd->dst.y_stride, xd);
    xd->itxm_add_uv_block(xd->plane[1].qcoeff, xd->block[16].dequant,
         xd->dst.u_buffer, xd->dst.uv_stride, xd->plane[1].eobs);
    xd->itxm_add_uv_block(xd->plane[2].qcoeff, xd->block[16].dequant,
         xd->dst.v_buffer, xd->dst.uv_stride, xd->plane[2].eobs);
    for (i = 0; i < 16; i++) {
      tx_type = get_tx_type_4x4(xd, i);
      dequant_add_y(xd, tx_type, i);
    xd->itxm_add_uv_block(xd->plane[1].qcoeff, xd->block[16].dequant,
                          xd->dst.u_buffer, xd->dst.uv_stride,
                          xd->plane[1].eobs);
    xd->itxm_add_uv_block(xd->plane[2].qcoeff, xd->block[16].dequant,
                          xd->dst.v_buffer, xd->dst.uv_stride,
                          xd->plane[2].eobs);
static INLINE void decode_sby_32x32(MACROBLOCKD *mb, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize) - 1, bw = 1 << bwl;
  const int bhl = mb_height_log2(bsize) - 1, bh = 1 << bhl;
  const int y_count = bw * bh;
  int n;

  for (n = 0; n < y_count; n++) {
    const int x_idx = n & (bw - 1);
    const int y_idx = n >> bwl;
    const int y_offset = (y_idx * 32) * mb->dst.y_stride + (x_idx * 32);
    vp9_dequant_idct_add_32x32(BLOCK_OFFSET(mb->plane[0].qcoeff, n, 1024),
                               mb->block[0].dequant ,
                               mb->dst.y_buffer + y_offset, mb->dst.y_stride,
                               mb->plane[0].eobs[n * 64]);
  }
}

static INLINE void decode_sbuv_32x32(MACROBLOCKD *mb, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize) - 1, bw = (1 << bwl) / 2;
  const int bhl = mb_height_log2(bsize) - 1, bh = (1 << bhl) / 2;
  const int uv_count = bw * bh;
  int n;
  for (n = 0; n < uv_count; n++) {
     const int x_idx = n & (bw - 1);
     const int y_idx = n >> (bwl - 1);
     const int uv_offset = (y_idx * 32) * mb->dst.uv_stride + (x_idx * 32);
     vp9_dequant_idct_add_32x32(BLOCK_OFFSET(mb->plane[1].qcoeff, n, 1024),
                                mb->block[16].dequant,
                                mb->dst.u_buffer + uv_offset,
                                mb->dst.uv_stride, mb->plane[1].eobs[n * 64]);
     vp9_dequant_idct_add_32x32(BLOCK_OFFSET(mb->plane[2].qcoeff, n, 1024),
                                mb->block[20].dequant,
                                mb->dst.v_buffer + uv_offset,
                                mb->dst.uv_stride, mb->plane[2].eobs[n * 64]);
  }
}

static INLINE void decode_sby_16x16(MACROBLOCKD *mb, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize), bw = 1 << bwl;
  const int bhl = mb_height_log2(bsize), bh = 1 << bhl;
  const int y_count = bw * bh;
  int n;

  for (n = 0; n < y_count; n++) {
    const int x_idx = n & (bw - 1);
    const int y_idx = n >> bwl;
    const int y_offset = (y_idx * 16) * mb->dst.y_stride + (x_idx * 16);
    const TX_TYPE tx_type = get_tx_type_16x16(mb,
                                (y_idx * (4 * bw) + x_idx) * 4);
    vp9_dequant_iht_add_16x16_c(tx_type,
                                BLOCK_OFFSET(mb->plane[0].qcoeff, n, 256),
                                mb->block[0].dequant,
                                mb->dst.y_buffer + y_offset,
                                mb->dst.y_stride,
                                mb->plane[0].eobs[n * 16]);
}

static INLINE void decode_sbuv_16x16(MACROBLOCKD *mb, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize), bw = (1 << bwl) / 2;
  const int bhl = mb_height_log2(bsize), bh = (1 << bhl) / 2;
  const int uv_count = bw * bh;
  int n;

  assert(bsize >= BLOCK_SIZE_SB32X32);

  for (n = 0; n < uv_count; n++) {
    const int x_idx = n & (bw - 1);
    const int y_idx = n >> (bwl - 1);
    const int uv_offset = (y_idx * 16) * mb->dst.uv_stride + (x_idx * 16);
    vp9_dequant_idct_add_16x16(BLOCK_OFFSET(mb->plane[1].qcoeff, n, 256),
                               mb->block[16].dequant,
                               mb->dst.u_buffer + uv_offset, mb->dst.uv_stride,
                               mb->plane[1].eobs[n * 16]);
    vp9_dequant_idct_add_16x16(BLOCK_OFFSET(mb->plane[2].qcoeff, n, 256),
                               mb->block[20].dequant,
                               mb->dst.v_buffer + uv_offset, mb->dst.uv_stride,
                               mb->plane[2].eobs[n * 16]);
static INLINE void decode_sby_8x8(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize)  + 1, bw = 1 << bwl;
  const int bhl = mb_height_log2(bsize) + 1, bh = 1 << bhl;
  const int y_count = bw * bh;
  int n;

  // luma
  for (n = 0; n < y_count; n++) {
    const int x_idx = n & (bw - 1);
    const int y_idx = n >> bwl;
    const int y_offset = (y_idx * 8) * xd->dst.y_stride + (x_idx * 8);
    const TX_TYPE tx_type = get_tx_type_8x8(xd,
                                            (y_idx * (2 * bw) + x_idx) * 2);

    vp9_dequant_iht_add_8x8_c(tx_type,
                              BLOCK_OFFSET(xd->plane[0].qcoeff, n, 64),
                              xd->block[0].dequant,
                              xd->dst.y_buffer + y_offset, xd->dst.y_stride,
                              xd->plane[0].eobs[n * 4]);
}

static INLINE void decode_sbuv_8x8(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize)  + 1, bw = 1 << (bwl - 1);
  const int bhl = mb_height_log2(bsize) + 1, bh = 1 << (bhl - 1);
  const int uv_count = bw * bh;
  int n;

  // chroma
  for (n = 0; n < uv_count; n++) {
    const int x_idx = n & (bw - 1);
    const int y_idx = n >> (bwl - 1);
    const int uv_offset = (y_idx * 8) * xd->dst.uv_stride + (x_idx * 8);
    vp9_dequant_idct_add_8x8(BLOCK_OFFSET(xd->plane[1].qcoeff, n, 64),
                             xd->block[16].dequant,
                             xd->dst.u_buffer + uv_offset, xd->dst.uv_stride,
                             xd->plane[1].eobs[n * 4]);
    vp9_dequant_idct_add_8x8(BLOCK_OFFSET(xd->plane[2].qcoeff, n, 64),
                             xd->block[20].dequant,
                             xd->dst.v_buffer + uv_offset, xd->dst.uv_stride,
                             xd->plane[2].eobs[n * 4]);
static INLINE void decode_sby_4x4(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize)  + 2, bw = 1 << bwl;
  const int bhl = mb_height_log2(bsize) + 2, bh = 1 << bhl;
  const int y_count = bw * bh;
  int n;

  for (n = 0; n < y_count; n++) {
    const int x_idx = n & (bw - 1);
    const int y_idx = n >> bwl;
    const int y_offset = (y_idx * 4) * xd->dst.y_stride + (x_idx * 4);
    const TX_TYPE tx_type = get_tx_type_4x4(xd, n);
      xd->itxm_add(BLOCK_OFFSET(xd->plane[0].qcoeff, n, 16),
                   xd->block[0].dequant,
                   xd->dst.y_buffer + y_offset, xd->dst.y_stride,
                   xd->plane[0].eobs[n]);
      vp9_dequant_iht_add_c(tx_type,
                            BLOCK_OFFSET(xd->plane[0].qcoeff, n, 16),
                            xd->block[0].dequant, xd->dst.y_buffer + y_offset,
                            xd->dst.y_stride, xd->plane[0].eobs[n]);
}

static INLINE void decode_sbuv_4x4(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize)  + 2, bw = 1 << (bwl - 1);
  const int bhl = mb_height_log2(bsize) + 2, bh = 1 << (bhl - 1);
  const int uv_count = bw * bh;
  int n;

  for (n = 0; n < uv_count; n++) {
    const int x_idx = n & (bw - 1);
    const int y_idx = n >> (bwl - 1);
    const int uv_offset = (y_idx * 4) * xd->dst.uv_stride + (x_idx * 4);
    xd->itxm_add(BLOCK_OFFSET(xd->plane[1].qcoeff, n, 16),
        xd->block[16].dequant,
        xd->dst.u_buffer + uv_offset, xd->dst.uv_stride, xd->plane[1].eobs[n]);
    xd->itxm_add(BLOCK_OFFSET(xd->plane[2].qcoeff, n, 16),
        xd->block[20].dequant,
        xd->dst.v_buffer + uv_offset, xd->dst.uv_stride, xd->plane[2].eobs[n]);
// TODO(jingning): combine luma and chroma dequantization and inverse
// transform into a single function looping over planes.
static void decode_sb_32x32(MACROBLOCKD *mb, BLOCK_SIZE_TYPE bsize) {
  decode_sby_32x32(mb, bsize);
  if (bsize == BLOCK_SIZE_SB64X64)
    decode_sbuv_32x32(mb, bsize);
  else
    decode_sbuv_16x16(mb, bsize);
}

static void decode_sb_16x16(MACROBLOCKD *mb, BLOCK_SIZE_TYPE bsize) {
  decode_sby_16x16(mb, bsize);
  if (bsize >= BLOCK_SIZE_SB32X32)
    decode_sbuv_16x16(mb, bsize);
  else
    decode_sbuv_8x8(mb, bsize);
}

static void decode_sb(VP9D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col,
                      vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
  const int bwl = mb_width_log2(bsize), bhl = mb_height_log2(bsize);
  const int bw = 1 << bwl, bh = 1 << bhl;
  int n, eobtotal;
  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 == bsize);

  if (pbi->common.frame_type != KEY_FRAME)
    vp9_setup_interp_filters(xd, mi->mbmi.interp_filter, pc);
  // generate prediction
  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
    vp9_build_intra_predictors_sby_s(xd, bsize);
    vp9_build_intra_predictors_sbuv_s(xd, bsize);
  } else {
    vp9_build_inter_predictors_sb(xd, mb_row, mb_col, bsize);
Yunqing Wang's avatar
Yunqing Wang committed
  if (mi->mbmi.mb_skip_coeff) {
    vp9_reset_sb_tokens_context(xd, bsize);
#if CONFIG_CODE_NONZEROCOUNT
    vpx_memset(mi->mbmi.nzcs, 0, 384 * sizeof(mi->mbmi.nzcs[0]));
#endif
Yunqing Wang's avatar
Yunqing Wang committed
    // re-initialize macroblock dequantizer before detokenization
    if (xd->segmentation_enabled)
      mb_init_dequantizer(pbi, xd);

    // dequantization and idct
    eobtotal = vp9_decode_tokens(pbi, xd, r, bsize);
Yunqing Wang's avatar
Yunqing Wang committed
    if (eobtotal == 0) {  // skip loopfilter
      for (n = 0; n < bw * bh; n++) {
        const int x_idx = n & (bw - 1), y_idx = n >> bwl;

        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 = 1;
      }
    } else {
      switch (xd->mode_info_context->mbmi.txfm_size) {
        case TX_32X32:
          decode_sb_32x32(xd, bsize);
          break;
        case TX_16X16:
          decode_sb_16x16(xd, bsize);
          break;
        case TX_8X8:
          decode_sby_8x8(xd, bsize);
          decode_sbuv_8x8(xd, bsize);
          break;
        case TX_4X4:
          decode_sby_4x4(xd, bsize);
          decode_sbuv_4x4(xd, bsize);
          break;
        default: assert(0);
      }
Yunqing Wang's avatar
Yunqing Wang committed

#if CONFIG_CODE_NONZEROCOUNT
  propagate_nzcs(&pbi->common, xd);
#endif
// TODO(jingning): Need to merge SB and MB decoding. The MB decoding currently
// couples special handles on I8x8, B_PRED, and splitmv modes.
static void decode_mb(VP9D_COMP *pbi, MACROBLOCKD *xd,
                     int mb_row, int mb_col,
John Koleszar's avatar
John Koleszar committed
  int eobtotal = 0;
  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);
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 (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
    if (mode != I8X8_PRED) {
      vp9_build_intra_predictors_sbuv_s(xd, BLOCK_SIZE_MB16X16);
Yaowu Xu's avatar
Yaowu Xu committed
      if (mode != I4X4_PRED)
        vp9_build_intra_predictors_sby_s(xd, BLOCK_SIZE_MB16X16);
John Koleszar's avatar
John Koleszar committed
    }
John Koleszar's avatar
John Koleszar committed
  } else {
#if 0  // def 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, mb_row, mb_col);
John Koleszar's avatar
John Koleszar committed
  }

Yunqing Wang's avatar
Yunqing Wang committed
  if (xd->mode_info_context->mbmi.mb_skip_coeff) {
    vp9_reset_sb_tokens_context(xd, BLOCK_SIZE_MB16X16);
Yunqing Wang's avatar
Yunqing Wang committed
    // re-initialize macroblock dequantizer before detokenization
    if (xd->segmentation_enabled)
      mb_init_dequantizer(pbi, xd);

Yunqing Wang's avatar
Yunqing Wang committed
#if CONFIG_NEWBINTRAMODES
    if (mode != I4X4_PRED)
#endif
      eobtotal = vp9_decode_tokens(pbi, xd, r, BLOCK_SIZE_MB16X16);
Yunqing Wang's avatar
Yunqing Wang committed
    }
  }

  if (eobtotal == 0 &&
      mode != I4X4_PRED &&
      mode != SPLITMV &&
      mode != I8X8_PRED &&
Yunqing Wang's avatar
Yunqing Wang committed
    xd->mode_info_context->mbmi.mb_skip_coeff = 1;
  } else {
#if 0  // def DEC_DEBUG
  if (dec_debug)
    printf("Decoding mb:  %d %d\n", xd->mode_info_context->mbmi.mode, tx_size);
#endif

    if (tx_size == TX_16X16) {
Yunqing Wang's avatar
Yunqing Wang committed
    } else if (tx_size == TX_8X8) {
Yunqing Wang's avatar
Yunqing Wang committed
    } else {
Yunqing Wang's avatar
Yunqing Wang committed
    }
Yunqing Wang's avatar
Yunqing Wang committed

#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");
    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 *r, int *dq) {
  const int old_value = *dq;

  if (vp9_read_bit(r)) {  // Update bit
    const int value = vp9_read_literal(r, 4);
    *dq = vp9_read_and_apply_sign(r, value);
John Koleszar's avatar
John Koleszar committed
  }
  // Trigger a quantizer update if the delta-q value has changed
  return old_value != *dq;
John Koleszar's avatar
John Koleszar committed
}

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

static void set_offsets(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize,
                        int mb_row, int mb_col) {
  const int bh = 1 << mb_height_log2(bsize);
  const int bw = 1 << mb_width_log2(bsize);
  VP9_COMMON *const cm = &pbi->common;
  MACROBLOCKD *const xd = &pbi->mb;
John Koleszar's avatar
John Koleszar committed

  const int mb_idx = mb_row * cm->mode_info_stride + mb_col;
  const YV12_BUFFER_CONFIG *dst_fb = &cm->yv12_fb[cm->new_fb_idx];
  const int recon_yoffset = (16 * mb_row) * dst_fb->y_stride + (16 * mb_col);
  const int recon_uvoffset = (8 * mb_row) * dst_fb->uv_stride + (8 * mb_col);

  xd->mode_info_context = cm->mi + mb_idx;
  xd->mode_info_context->mbmi.sb_type = bsize;
  xd->prev_mode_info_context = cm->prev_mi + mb_idx;
  xd->above_context = cm->above_context + mb_col;
  xd->left_context = cm->left_context + mb_row % 4;
  // 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, bh);
  set_mb_col(cm, xd, mb_col, bw);
  xd->dst.y_buffer = dst_fb->y_buffer + recon_yoffset;
  xd->dst.u_buffer = dst_fb->u_buffer + recon_uvoffset;
  xd->dst.v_buffer = dst_fb->v_buffer + recon_uvoffset;
John Koleszar's avatar
John Koleszar committed

static void set_refs(VP9D_COMP *pbi, 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;

  if (mbmi->ref_frame > INTRA_FRAME) {
    // 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;
    if (mbmi->second_ref_frame > INTRA_FRAME) {
      // 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];
Yunqing Wang's avatar
Yunqing Wang committed
      xd->scale_factor[1]    = cm->active_ref_scale[mbmi->second_ref_frame - 1];
      xd->scale_factor_uv[1] = cm->active_ref_scale[mbmi->second_ref_frame - 1];
      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;
John Koleszar's avatar
John Koleszar committed

static void decode_modes_b(VP9D_COMP *pbi, int mb_row, int mb_col,
                           vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
  MACROBLOCKD *const xd = &pbi->mb;

  set_offsets(pbi, bsize, mb_row, mb_col);
  vp9_decode_mb_mode_mv(pbi, xd, mb_row, mb_col, r);
  set_refs(pbi, mb_row, mb_col);

  // TODO(jingning): merge decode_sb_ and decode_mb_
  if (bsize > BLOCK_SIZE_MB16X16)
    decode_sb(pbi, xd, mb_row, mb_col, r, bsize);
  else
    decode_mb(pbi, xd, mb_row, mb_col, r);

  xd->corrupted |= bool_error(r);
}

static void decode_modes_sb(VP9D_COMP *pbi, int mb_row, int mb_col,
                            vp9_reader* r, BLOCK_SIZE_TYPE bsize) {
  VP9_COMMON *const pc = &pbi->common;
  MACROBLOCKD *const xd = &pbi->mb;
  int bsl = mb_width_log2(bsize), bs = (1 << bsl) / 2;
  int n;
  PARTITION_TYPE partition = PARTITION_NONE;
  BLOCK_SIZE_TYPE subsize;

  if (mb_row >= pc->mb_rows || mb_col >= pc->mb_cols)
    return;

  if (bsize > BLOCK_SIZE_MB16X16) {
    // read the partition information
    partition = treed_read(r, vp9_partition_tree,
                           pc->fc.partition_prob[bsl - 1]);
    pc->fc.partition_counts[bsl - 1][partition]++;
  }

  switch (partition) {
    case PARTITION_NONE:
      subsize = bsize;
      decode_modes_b(pbi, mb_row, mb_col, r, subsize);
      break;
#if CONFIG_SBSEGMENT
    case PARTITION_HORZ:
      subsize = (bsize == BLOCK_SIZE_SB64X64) ? BLOCK_SIZE_SB64X32 :
                                                BLOCK_SIZE_SB32X16;
      decode_modes_b(pbi, mb_row, mb_col, r, subsize);
      if ((mb_row + bs) < pc->mb_rows)
        decode_modes_b(pbi, mb_row + bs, mb_col, r, subsize);
      break;
    case PARTITION_VERT:
      subsize = (bsize == BLOCK_SIZE_SB64X64) ? BLOCK_SIZE_SB32X64 :
                                                BLOCK_SIZE_SB16X32;
      decode_modes_b(pbi, mb_row, mb_col, r, subsize);
      if ((mb_col + bs) < pc->mb_cols)
        decode_modes_b(pbi, mb_row, mb_col + bs, r, subsize);
      break;
#endif
    case PARTITION_SPLIT:
      subsize = (bsize == BLOCK_SIZE_SB64X64) ? BLOCK_SIZE_SB32X32 :
                                                BLOCK_SIZE_MB16X16;
      for (n = 0; n < 4; n++) {
        int j = n >> 1, i = n & 0x01;
        if (subsize == BLOCK_SIZE_SB32X32)
          xd->sb_index = n;
        else
          xd->mb_index = n;
        decode_modes_sb(pbi, mb_row + j * bs, mb_col + i * bs, r, subsize);
      }
      break;
    default:
      assert(0);
  }
}

/* Decode a row of Superblocks (4x4 region of MBs) */
static void decode_tile(VP9D_COMP *pbi, vp9_reader* r) {
  VP9_COMMON *const pc = &pbi->common;
  int mb_row, mb_col;

  for (mb_row = pc->cur_tile_mb_row_start;
       mb_row < pc->cur_tile_mb_row_end; mb_row += 4) {
    // 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) {
      decode_modes_sb(pbi, mb_row, mb_col, r, BLOCK_SIZE_SB64X64);
    }
John Koleszar's avatar
John Koleszar committed
  }
static void setup_token_decoder(VP9D_COMP *pbi,
                                const uint8_t *data,
                                vp9_reader *r) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  VP9_COMMON *pc = &pbi->common;
  const uint8_t *data_end = pbi->source + pbi->source_sz;
  const size_t partition_size = data_end - data;
John Koleszar's avatar
John Koleszar committed

Dmitry Kovalev's avatar
Dmitry Kovalev committed
  // Validate the calculated partition length. If the buffer
  // described by the partition can't be fully read, then restrict
  // it to the portion that can be (for EC mode) or throw an error.
  if (!read_is_valid(data, partition_size, data_end))
John Koleszar's avatar
John Koleszar committed
    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
                       "Truncated packet or corrupt partition "
                       "%d length", 1);

  if (vp9_start_decode(r, data, partition_size))
John Koleszar's avatar
John Koleszar committed
    vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                       "Failed to allocate bool decoder %d", 1);
static void init_frame(VP9D_COMP *pbi) {
  VP9_COMMON *const pc = &pbi->common;
  MACROBLOCKD *const xd = &pbi->mb;
John Koleszar's avatar
John Koleszar committed
  if (pc->frame_type == KEY_FRAME) {
    vp9_setup_past_independence(pc, xd);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    // All buffers are implicitly updated on key frames.
    pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
  } else if (pc->error_resilient_mode) {
    vp9_setup_past_independence(pc, xd);
  }
John Koleszar's avatar
John Koleszar committed
  xd->mode_info_context = pc->mi;
  xd->prev_mode_info_context = pc->prev_mi;
John Koleszar's avatar
John Koleszar committed
  xd->frame_type = pc->frame_type;
  xd->mode_info_context->mbmi.mode = DC_PRED;
  xd->mode_info_stride = pc->mode_info_stride;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  xd->corrupted = 0;
#if CONFIG_CODE_NONZEROCOUNT
static void read_nzc_probs_common(VP9_COMMON *cm,
  int c, r, b, t;
  int tokens, nodes;
  vp9_prob *nzc_probs;
  vp9_prob upd;

  if (!get_nzc_used(tx_size)) return;
  if (!vp9_read_bit(rd)) return;
  if (tx_size == TX_32X32) {
    tokens = NZC32X32_TOKENS;
    nzc_probs = cm->fc.nzc_probs_32x32[0][0][0];