blob: 2a8bf1e3e2edc15354a8fd638f70713e9b15b6d6 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
#include "mp4dec_lib.h"
#include "vlc_decode.h"
#include "bitstream.h"
#include "zigzag.h"
#include "scaling.h"
void doDCACPrediction(
VideoDecData *video,
int comp,
int16 *q_block,
int *direction
)
{
/*----------------------------------------------------------------------------
; Define all local variables
----------------------------------------------------------------------------*/
int i;
int mbnum = video->mbnum;
int nMBPerRow = video->nMBPerRow;
int x_pos = video->mbnum_col;
int y_pos = video->mbnum_row;
int16 *AC_tmp;
int QP_tmp;
int16 *QP_store = video->QPMB + mbnum;
int QP = video->QPMB[mbnum];
int QP_half = QP >> 1;
int32 val;
int flag_0 = FALSE, flag_1 = FALSE;
uint8 *slice_nb = video->sliceNo;
typeDCStore *DC_store = video->predDC + mbnum;
typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
typeDCACStore *DCAC_col = video->predDCAC_col;
uint ACpred_flag = (uint) video->acPredFlag[mbnum];
int left_bnd, up_bnd;
static const int Xpos[6] = { -1, 0, -1, 0, -1, -1};
static const int Ypos[6] = { -1, -1, 0, 0, -1, -1};
static const int Xtab[6] = {1, 0, 3, 2, 4, 5};
static const int Ytab[6] = {2, 3, 0, 1, 4, 5};
static const int Ztab[6] = {3, 2, 1, 0, 4, 5};
/* I added these to speed up comparisons */
static const int Pos0[6] = { 1, 1, 0, 0, 1, 1};
static const int Pos1[6] = { 1, 0, 1, 0, 1, 1};
static const int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
static const int B_Ytab[6] = {0, 0, 1, 1, 2, 3};
// int *direction; /* 0: HORIZONTAL, 1: VERTICAL */
int block_A, block_B, block_C;
int DC_pred;
int y_offset, x_offset, x_tab, y_tab, z_tab; /* speedup coefficients */
int b_xtab, b_ytab;
if (!comp && x_pos && !(video->headerInfo.Mode[mbnum-1]&INTRA_MASK)) /* not intra */
{
oscl_memset(DCAC_col, 0, sizeof(typeDCACStore));
}
if (!comp && y_pos && !(video->headerInfo.Mode[mbnum-nMBPerRow]&INTRA_MASK)) /* not intra */
{
oscl_memset(DCAC_row, 0, sizeof(typeDCACStore));
}
y_offset = Ypos[comp] * nMBPerRow;
x_offset = Xpos[comp];
x_tab = Xtab[comp];
y_tab = Ytab[comp];
z_tab = Ztab[comp];
b_xtab = B_Xtab[comp];
b_ytab = B_Ytab[comp];
/*----------------------------------------------------------------------------
; Function body here
----------------------------------------------------------------------------*/
/* Find the direction of prediction and the DC prediction */
if (x_pos == 0 && y_pos == 0)
{ /* top left corner */
block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
block_B = (comp == 3) ? DC_store[x_offset][z_tab] : mid_gray;
block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[0][y_tab] : mid_gray;
}
else if (x_pos == 0)
{ /* left edge */
up_bnd = Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow];
block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
block_B = ((comp == 1 && up_bnd) || comp == 3) ? DC_store[y_offset+x_offset][z_tab] : mid_gray;
block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
}
else if (y_pos == 0)
{ /* top row */
left_bnd = Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1];
block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
block_B = ((comp == 2 && left_bnd) || comp == 3) ? DC_store[y_offset + x_offset][z_tab] : mid_gray;
block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
}
else
{
up_bnd = Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow];
left_bnd = Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1];
block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
block_B = (((comp == 0 || comp == 4 || comp == 5) && slice_nb[mbnum] == slice_nb[mbnum-1-nMBPerRow]) ||
(comp == 1 && up_bnd) || (comp == 2 && left_bnd) || (comp == 3)) ? DC_store[y_offset+x_offset][z_tab] : mid_gray;
block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
}
if ((PV_ABS((block_A - block_B))) < (PV_ABS((block_B - block_C))))
{
DC_pred = block_C;
*direction = 1;
if (ACpred_flag == 1)
{
if (flag_1)
{
AC_tmp = DCAC_row[0][b_xtab];
QP_tmp = QP_store[y_offset];
if (QP_tmp == QP)
{
for (i = 1; i < 8; i++)
{
q_block[i] = *AC_tmp++;
}
}
else
{
for (i = 1; i < 8; i++)
{
val = (int32)(*AC_tmp++) * QP_tmp;
q_block[i] = (val < 0) ? (int16)((val - QP_half) / QP) : (int16)((val + QP_half) / QP);
/* Vertical, top ROW of block C */
}
}
}
}
}
else
{
DC_pred = block_A;
*direction = 0;
if (ACpred_flag == 1)
{
if (flag_0)
{
AC_tmp = DCAC_col[0][b_ytab];
QP_tmp = QP_store[x_offset];
if (QP_tmp == QP)
{
for (i = 1; i < 8; i++)
{
q_block[i<<3] = *AC_tmp++;
}
}
else
{
for (i = 1; i < 8; i++)
{
val = (int32)(*AC_tmp++) * QP_tmp;
q_block[i<<3] = (val < 0) ? (int16)((val - QP_half) / QP) : (int16)((val + QP_half) / QP);
/* Vertical, top ROW of block C */
}
}
}
}
}
/* Now predict the DC coefficient */
QP_tmp = (comp < 4) ? video->mblock->DCScalarLum : video->mblock->DCScalarChr;
q_block[0] += (int16)((DC_pred + (QP_tmp >> 1)) * scale[QP_tmp] >> 18);
// q_block[0] += (DC_pred+(QP_tmp>>1))/QP_tmp;
/*----------------------------------------------------------------------------
; Return nothing or data or data pointer
----------------------------------------------------------------------------*/
return;
}
#ifdef PV_ANNEX_IJKT_SUPPORT
void doDCACPrediction_I(
VideoDecData *video,
int comp,
int16 *q_block
)
{
/*----------------------------------------------------------------------------
; Define all local variables
----------------------------------------------------------------------------*/
int mbnum = video->mbnum;
int nMBPerRow = video->nMBPerRow;
int x_pos = video->mbnum_col;
int y_pos = video->mbnum_row;
int16 *AC_tmp;
int flag_0 = FALSE, flag_1 = FALSE;
uint8 *slice_nb = video->sliceNo;
typeDCStore *DC_store = video->predDC + mbnum;
typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
typeDCACStore *DCAC_col = video->predDCAC_col;
int left_bnd, up_bnd;
uint8 *mode = video->headerInfo.Mode;
uint ACpred_flag = (uint) video->acPredFlag[mbnum];
static const int Xpos[6] = { -1, 0, -1, 0, -1, -1};
static const int Ypos[6] = { -1, -1, 0, 0, -1, -1};
static const int Xtab[6] = {1, 0, 3, 2, 4, 5};
static const int Ytab[6] = {2, 3, 0, 1, 4, 5};
/* I added these to speed up comparisons */
static const int Pos0[6] = { 1, 1, 0, 0, 1, 1};
static const int Pos1[6] = { 1, 0, 1, 0, 1, 1};
static const int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
static const int B_Ytab[6] = {0, 0, 1, 1, 2, 3};
// int *direction; /* 0: HORIZONTAL, 1: VERTICAL */
int block_A, block_C;
int y_offset, x_offset, x_tab, y_tab; /* speedup coefficients */
int b_xtab, b_ytab;
y_offset = Ypos[comp] * nMBPerRow;
x_offset = Xpos[comp];
x_tab = Xtab[comp];
y_tab = Ytab[comp];
b_xtab = B_Xtab[comp];
b_ytab = B_Ytab[comp];
/*----------------------------------------------------------------------------
; Function body here
----------------------------------------------------------------------------*/
/* Find the direction of prediction and the DC prediction */
if (x_pos == 0 && y_pos == 0)
{ /* top left corner */
block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[0][y_tab] : mid_gray;
}
else if (x_pos == 0)
{ /* left edge */
up_bnd = (Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
&& (mode[mbnum-nMBPerRow] == MODE_INTRA || mode[mbnum-nMBPerRow] == MODE_INTRA_Q);;
block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
}
else if (y_pos == 0)
{ /* top row */
left_bnd = (Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1])
&& (mode[mbnum-1] == MODE_INTRA || mode[mbnum-1] == MODE_INTRA_Q);
block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
}
else
{
up_bnd = (Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
&& (mode[mbnum-nMBPerRow] == MODE_INTRA || mode[mbnum-nMBPerRow] == MODE_INTRA_Q);
left_bnd = (Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1])
&& (mode[mbnum-1] == MODE_INTRA || mode[mbnum-1] == MODE_INTRA_Q);
block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
}
if (ACpred_flag == 0)
{
if (flag_0 == TRUE)
{
if (flag_1 == TRUE)
{
q_block[0] = (int16)((block_A + block_C) >> 1);
}
else
{
q_block[0] = (int16)block_A;
}
}
else
{
if (flag_1 == TRUE)
{
q_block[0] = (int16)block_C;
}
else
{
q_block[0] = mid_gray;
}
}
}
else
{
if (video->mblock->direction == 1)
{
if (flag_1 == TRUE)
{
q_block[0] = (int16)block_C;
AC_tmp = DCAC_row[0][b_xtab];
q_block[1] = AC_tmp[0];
q_block[2] = AC_tmp[1];
q_block[3] = AC_tmp[2];
q_block[4] = AC_tmp[3];
q_block[5] = AC_tmp[4];
q_block[6] = AC_tmp[5];
q_block[7] = AC_tmp[6];
}
else
{
q_block[0] = mid_gray;
}
}
else
{
if (flag_0 == TRUE)
{
q_block[0] = (int16)block_A;
AC_tmp = DCAC_col[0][b_ytab];
q_block[8] = AC_tmp[0];
q_block[16] = AC_tmp[1];
q_block[24] = AC_tmp[2];
q_block[32] = AC_tmp[3];
q_block[40] = AC_tmp[4];
q_block[48] = AC_tmp[5];
q_block[56] = AC_tmp[6];
}
else
{
q_block[0] = mid_gray;
}
}
}
/*----------------------------------------------------------------------------
; Return nothing or data or data pointer
----------------------------------------------------------------------------*/
return;
}
#endif