/*
* 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 "vpx_config.h"
#include "vp8_rtcd.h"
#include "./vpx_scale_rtcd.h"
#include "onyxd_int.h"
#include "vp8/common/header.h"
#include "vp8/common/reconintra4x4.h"
#include "vp8/common/reconinter.h"
#include "detokenize.h"
#include "vp8/common/invtrans.h"
#include "vp8/common/alloccommon.h"
#include "vp8/common/entropymode.h"
#include "vp8/common/quant_common.h"
#include "vpx_scale/vpx_scale.h"
#include "vp8/common/setupintrarecon.h"
#include "decodemv.h"
#include "vp8/common/extend.h"
#if CONFIG_ERROR_CONCEALMENT
#include "error_concealment.h"
#endif
#include "vpx_mem/vpx_mem.h"
#include "vp8/common/threading.h"
#include "decoderthreading.h"
#include "dboolhuff.h"
#include <assert.h>
#include <stdio.h>
void vp8cx_init_de_quantizer(VP8D_COMP *pbi)
{
int Q;
VP8_COMMON *const pc = & pbi->common;
for (Q = 0; Q < QINDEX_RANGE; Q++)
{
pc->Y1dequant[Q][0] = (short)vp8_dc_quant(Q, pc->y1dc_delta_q);
pc->Y2dequant[Q][0] = (short)vp8_dc2quant(Q, pc->y2dc_delta_q);
pc->UVdequant[Q][0] = (short)vp8_dc_uv_quant(Q, pc->uvdc_delta_q);
pc->Y1dequant[Q][1] = (short)vp8_ac_yquant(Q);
pc->Y2dequant[Q][1] = (short)vp8_ac2quant(Q, pc->y2ac_delta_q);
pc->UVdequant[Q][1] = (short)vp8_ac_uv_quant(Q, pc->uvac_delta_q);
}
}
void vp8_mb_init_dequantizer(VP8D_COMP *pbi, MACROBLOCKD *xd)
{
int i;
int QIndex;
MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
VP8_COMMON *const pc = & pbi->common;
/* Decide whether to use the default or alternate baseline Q value. */
if (xd->segmentation_enabled)
{
/* Abs Value */
if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA)
QIndex = xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
/* Delta Value */
else
{
QIndex = pc->base_qindex + xd->segment_feature_data[MB_LVL_ALT_Q][mbmi->segment_id];
QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0; /* Clamp to valid range */
}
}
else
QIndex = pc->base_qindex;
/* Set up the macroblock dequant constants */
xd->dequant_y1_dc[0] = 1;
xd->dequant_y1[0] = pc->Y1dequant[QIndex][0];
xd->dequant_y2[0] = pc->Y2dequant[QIndex][0];
xd->dequant_uv[0] = pc->UVdequant[QIndex][0];
for (i = 1; i < 16; i++)
{
xd->dequant_y1_dc[i] =
xd->dequant_y1[i] = pc->Y1dequant[QIndex][1];
xd->dequant_y2[i] = pc->Y2dequant[QIndex][1];
xd->dequant_uv[i] = pc->UVdequant[QIndex][1];
}
}
static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
unsigned int mb_idx)
{
MB_PREDICTION_MODE mode;
int i;
#if CONFIG_ERROR_CONCEALMENT
int corruption_detected = 0;
#endif
if (xd->mode_info_context->mbmi.mb_skip_coeff)
{
vp8_reset_mb_tokens_context(xd);
}
else if (!vp8dx_bool_error(xd->current_bc))
{
int eobtotal;
eobtotal = vp8_decode_mb_tokens(pbi, xd);
/* Special case: Force the loopfilter to skip when eobtotal is zero */
xd->mode_info_context->mbmi.mb_skip_coeff = (eobtotal==0);
}
mode = xd->mode_info_context->mbmi.mode;
if (xd->segmentation_enabled)
vp8_mb_init_dequantizer(pbi, xd);
#if CONFIG_ERROR_CONCEALMENT
if(pbi->ec_active)
{
int throw_residual;
/* When we have independent partitions we can apply residual even
* though other partitions within the frame are corrupt.
*/
throw_residual = (!pbi->independent_partitions &&
pbi->frame_corrupt_residual);
throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
if ((mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
{
/* MB with corrupt residuals or corrupt mode/motion vectors.
* Better to use the predictor as reconstruction.
*/
pbi->frame_corrupt_residual = 1;
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
vp8_conceal_corrupt_mb(xd);
corruption_detected = 1;
/* force idct to be skipped for B_PRED and use the
* prediction only for reconstruction
* */
vpx_memset(xd->eobs, 0, 25);
}
}
#endif
/* do prediction */
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
{
vp8_build_intra_predictors_mbuv_s(xd,
xd->recon_above[1],
xd->recon_above[2],
xd->recon_left[1],
xd->recon_left[2],
xd->recon_left_stride[1],
xd->dst.u_buffer, xd->dst.v_buffer,
xd->dst.uv_stride);
if (mode != B_PRED)
{
vp8_build_intra_predictors_mby_s(xd,
xd->recon_above[0],
xd->recon_left[0],
xd->recon_left_stride[0],
xd->dst.y_buffer,
xd->dst.y_stride);
}
else
{
short *DQC = xd->dequant_y1;
int dst_stride = xd->dst.y_stride;
/* clear out residual eob info */
if(xd->mode_info_context->mbmi.mb_skip_coeff)
vpx_memset(xd->eobs, 0, 25);
intra_prediction_down_copy(xd, xd->recon_above[0] + 16);
for (i = 0; i < 16; i++)
{
BLOCKD *b = &xd->block[i];
unsigned char *dst = xd->dst.y_buffer + b->offset;
B_PREDICTION_MODE b_mode =
xd->mode_info_context->bmi[i].as_mode;
unsigned char *Above = dst - dst_stride;
unsigned char *yleft = dst - 1;
int left_stride = dst_stride;
unsigned char top_left = Above[-1];
vp8_intra4x4_predict(Above, yleft, left_stride, b_mode,
dst, dst_stride, top_left);
if (xd->eobs[i])
{
if (xd->eobs[i] > 1)
{
vp8_dequant_idct_add(b->qcoeff, DQC, dst, dst_stride);
}
else
{
vp8_dc_only_idct_add
(b->qcoeff[0] * DQC[0],
dst, dst_stride,
dst, dst_stride);
vpx_memset(b->qcoeff, 0, 2 * sizeof(b->qcoeff[0]));
}
}
}
}
}
else
{
vp8_build_inter_predictors_mb(xd);
}
#if CONFIG_ERROR_CONCEALMENT
if (corruption_detected)
{
return;
}
#endif
if(!xd->mode_info_context->mbmi.mb_skip_coeff)
{
/* dequantization and idct */
if (mode != B_PRED)
{
short *DQC = xd->dequant_y1;
if (mode != SPLITMV)
{
BLOCKD *b = &xd->block[24];
/* do 2nd order transform on the dc block */
if (xd->eobs[24] > 1)
{
vp8_dequantize_b(b, xd->dequant_y2);
vp8_short_inv_walsh4x4(&b->dqcoeff[0],
xd->qcoef