vp9_decodframe.c 32.5 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.
John Koleszar's avatar
John Koleszar committed
 */

#include <assert.h>
John Koleszar's avatar
John Koleszar committed

#include "./vp9_rtcd.h"
#include "vpx_mem/vpx_mem.h"
#include "vpx_scale/vpx_scale.h"

Dmitry Kovalev's avatar
Dmitry Kovalev committed
#include "vp9/common/vp9_alloccommon.h"
#include "vp9/common/vp9_common.h"
#include "vp9/common/vp9_entropy.h"
#include "vp9/common/vp9_entropymode.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
#include "vp9/common/vp9_extend.h"
#include "vp9/common/vp9_pred_common.h"
#include "vp9/common/vp9_quant_common.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
#include "vp9/common/vp9_reconintra.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/common/vp9_seg_common.h"
#include "vp9/common/vp9_tile_common.h"

#include "vp9/decoder/vp9_dboolhuff.h"
#include "vp9/decoder/vp9_decodframe.h"
#include "vp9/decoder/vp9_detokenize.h"
#include "vp9/decoder/vp9_decodemv.h"
#include "vp9/decoder/vp9_dsubexp.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
#include "vp9/decoder/vp9_idct_blk.h"
#include "vp9/decoder/vp9_onyxd_int.h"
#include "vp9/decoder/vp9_read_bit_buffer.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
#include "vp9/decoder/vp9_treereader.h"
static int read_be32(const uint8_t *p) {
  return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}

// len == 0 is not allowed
static int read_is_valid(const uint8_t *start, size_t len, const uint8_t *end) {
  return start + len > start && start + len <= end;
}

static int decode_unsigned_max(struct vp9_read_bit_buffer *rb, int max) {
  const int data = vp9_rb_read_literal(rb, get_unsigned_bits(max));
  return data > max ? max : data;
}

static TX_MODE read_tx_mode(vp9_reader *r) {
  TX_MODE tx_mode = vp9_read_literal(r, 2);
  if (tx_mode == ALLOW_32X32)
    tx_mode += vp9_read_bit(r);
  return tx_mode;
static void read_tx_probs(struct tx_probs *tx_probs, vp9_reader *r) {
  int i, j;

  for (i = 0; i < TX_SIZE_CONTEXTS; ++i)
    for (j = 0; j < TX_SIZES - 3; ++j)
      if (vp9_read(r, VP9_MODE_UPDATE_PROB))
        vp9_diff_update_prob(r, &tx_probs->p8x8[i][j]);

  for (i = 0; i < TX_SIZE_CONTEXTS; ++i)
    for (j = 0; j < TX_SIZES - 2; ++j)
      if (vp9_read(r, VP9_MODE_UPDATE_PROB))
        vp9_diff_update_prob(r, &tx_probs->p16x16[i][j]);

  for (i = 0; i < TX_SIZE_CONTEXTS; ++i)
    for (j = 0; j < TX_SIZES - 1; ++j)
      if (vp9_read(r, VP9_MODE_UPDATE_PROB))
        vp9_diff_update_prob(r, &tx_probs->p32x32[i][j]);
static void init_dequantizer(VP9_COMMON *cm, MACROBLOCKD *xd) {
John Koleszar's avatar
John Koleszar committed
  int i;
  const int segment_id = xd->mode_info_context->mbmi.segment_id;
  xd->q_index = vp9_get_qindex(xd, segment_id, cm->base_qindex);
John Koleszar's avatar
John Koleszar committed

  xd->plane[0].dequant = cm->y_dequant[xd->q_index];
  for (i = 1; i < MAX_MB_PLANE; i++)
    xd->plane[i].dequant = cm->uv_dequant[xd->q_index];
static void decode_block(int plane, int block, BLOCK_SIZE_TYPE bsize,
                         int ss_txfrm_size, void *arg) {
  MACROBLOCKD* const xd = arg;
  struct macroblockd_plane *pd = &xd->plane[plane];
  int16_t* const qcoeff = BLOCK_OFFSET(pd->qcoeff, block, 16);
  const int stride = pd->dst.stride;
  const int eob = pd->eobs[block];
  const int raster_block = txfrm_block_to_raster_block(xd, bsize, plane,
                                                       block, ss_txfrm_size);
  uint8_t* const dst = raster_block_offset_uint8(xd, bsize, plane,
                                                 raster_block,
                                                 pd->dst.buf, stride);
  switch (ss_txfrm_size / 2) {
    case TX_4X4: {
      const TX_TYPE tx_type = get_tx_type_4x4(pd->plane_type, xd, raster_block);
      if (tx_type == DCT_DCT)
        xd->itxm_add(qcoeff, dst, stride, eob);
        vp9_iht_add_c(tx_type, qcoeff, dst, stride, eob);
      vp9_iht_add_8x8_c(get_tx_type_8x8(pd->plane_type, xd), qcoeff, dst,
                        stride, eob);
      vp9_iht_add_16x16_c(get_tx_type_16x16(pd->plane_type, xd), qcoeff, dst,
                          stride, eob);
      vp9_idct_add_32x32(qcoeff, dst, stride, eob);
static void decode_block_intra(int plane, int block, BLOCK_SIZE_TYPE bsize,
                               int ss_txfrm_size, void *arg) {
  MACROBLOCKD* const xd = arg;
  struct macroblockd_plane *pd = &xd->plane[plane];
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  MODE_INFO *const mi = xd->mode_info_context;
  const int raster_block = txfrm_block_to_raster_block(xd, bsize, plane,
                                                       block, ss_txfrm_size);
  uint8_t* const dst = raster_block_offset_uint8(xd, bsize, plane,
                                                 raster_block,
                                                 pd->dst.buf, pd->dst.stride);
  const TX_SIZE tx_size = (TX_SIZE)(ss_txfrm_size / 2);
  int plane_b_size;
  const int tx_ib = raster_block >> tx_size;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  const int mode = plane == 0 ? mi->mbmi.mode
                              : mi->mbmi.uv_mode;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  if (plane == 0 && mi->mbmi.sb_type < BLOCK_SIZE_SB8X8) {
Ronald S. Bultje's avatar
Ronald S. Bultje committed
    assert(bsize == BLOCK_SIZE_SB8X8);
    b_mode = mi->bmi[raster_block].as_mode;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
  } else {
    b_mode = mode;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
  }
  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0)
    extend_for_intra(xd, plane, block, bsize, ss_txfrm_size);

  plane_b_size = b_width_log2(bsize) - pd->subsampling_x;
  vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size, b_mode,
                          dst, pd->dst.stride,
                          dst, pd->dst.stride);
  // Early exit if there are no coefficients
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  if (mi->mbmi.mb_skip_coeff)
  decode_block(plane, block, bsize, ss_txfrm_size, arg);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
static int decode_tokens(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize, vp9_reader *r) {
  MACROBLOCKD *const xd = &pbi->mb;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  if (xd->mode_info_context->mbmi.mb_skip_coeff) {
    vp9_reset_sb_tokens_context(xd, bsize);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    return -1;
      init_dequantizer(&pbi->common, xd);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    // TODO(dkovalev) if (!vp9_reader_has_error(r))
    return vp9_decode_tokens(pbi, r, bsize);
static void set_offsets(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize,
                        int mi_row, int mi_col) {
  VP9_COMMON *const cm = &pbi->common;
  MACROBLOCKD *const xd = &pbi->mb;
  const int bh = 1 << mi_height_log2(bsize);
  const int bw = 1 << mi_width_log2(bsize);
  const int mi_idx = mi_row * cm->mode_info_stride + mi_col;
  xd->mode_info_context = cm->mi + mi_idx;
  xd->mode_info_context->mbmi.sb_type = bsize;
  // Special case: if prev_mi is NULL, the previous mode info context
  // cannot be used.
  xd->prev_mode_info_context = cm->prev_mi ? cm->prev_mi + mi_idx : NULL;
  for (i = 0; i < MAX_MB_PLANE; i++) {
    struct macroblockd_plane *pd = &xd->plane[i];
    pd->above_context = cm->above_context[i] +
                            (mi_col * 2 >> pd->subsampling_x);
    pd->left_context = cm->left_context[i] +
                           (((mi_row * 2) & 15) >> pd->subsampling_y);
Loading full blame...