| /* ------------------------------------------------------------------ |
| * 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 |
| |