summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/avc/common/src/mb_access.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/avc/common/src/mb_access.cpp')
-rw-r--r--media/libstagefright/codecs/avc/common/src/mb_access.cpp471
1 files changed, 471 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/avc/common/src/mb_access.cpp b/media/libstagefright/codecs/avc/common/src/mb_access.cpp
new file mode 100644
index 0000000..414b8f7
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/mb_access.cpp
@@ -0,0 +1,471 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include <string.h>
+
+#include "avclib_common.h"
+
+OSCL_EXPORT_REF void InitNeighborAvailability(AVCCommonObj *video, int mbNum)
+{
+ int PicWidthInMbs = video->PicWidthInMbs;
+
+ // do frame-only and postpone intraAvail calculattion
+ video->mbAddrA = mbNum - 1;
+ video->mbAddrB = mbNum - PicWidthInMbs;
+ video->mbAddrC = mbNum - PicWidthInMbs + 1;
+ video->mbAddrD = mbNum - PicWidthInMbs - 1;
+
+ video->mbAvailA = video->mbAvailB = video->mbAvailC = video->mbAvailD = 0;
+ if (video->mb_x)
+ {
+ video->mbAvailA = (video->mblock[video->mbAddrA].slice_id == video->currMB->slice_id);
+ if (video->mb_y)
+ {
+ video->mbAvailD = (video->mblock[video->mbAddrD].slice_id == video->currMB->slice_id);
+ }
+ }
+
+ if (video->mb_y)
+ {
+ video->mbAvailB = (video->mblock[video->mbAddrB].slice_id == video->currMB->slice_id);
+ if (video->mb_x < (PicWidthInMbs - 1))
+ {
+ video->mbAvailC = (video->mblock[video->mbAddrC].slice_id == video->currMB->slice_id);
+ }
+ }
+ return ;
+}
+
+bool mb_is_available(AVCMacroblock *mblock, uint PicSizeInMbs, int mbAddr, int currMbAddr)
+{
+ if (mbAddr < 0 || mbAddr >= (int)PicSizeInMbs)
+ {
+ return FALSE;
+ }
+
+ if (mblock[mbAddr].slice_id != mblock[currMbAddr].slice_id)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+OSCL_EXPORT_REF int predict_nnz(AVCCommonObj *video, int i, int j)
+{
+ int pred_nnz = 0;
+ int cnt = 1;
+ AVCMacroblock *tempMB;
+
+ /* left block */
+ /*getLuma4x4Neighbour(video, mb_nr, i, j, -1, 0, &pix);
+ leftMB = video->mblock + pix.mb_addr; */
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (i)
+ {
+ pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ tempMB = video->mblock + video->mbAddrA;
+ pred_nnz = tempMB->nz_coeff[(j<<2)+3];
+ }
+ else
+ {
+ cnt = 0;
+ }
+ }
+
+
+ /* top block */
+ /*getLuma4x4Neighbour(video, mb_nr, i, j, 0, -1, &pix);
+ topMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (j)
+ {
+ pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
+ cnt++;
+ }
+ else
+ {
+ if (video->mbAvailB)
+ {
+ tempMB = video->mblock + video->mbAddrB;
+ pred_nnz += tempMB->nz_coeff[12+i];
+ cnt++;
+ }
+ }
+
+
+ if (cnt == 2)
+ {
+ pred_nnz = (pred_nnz + 1) >> 1;
+ }
+
+ return pred_nnz;
+
+}
+
+
+OSCL_EXPORT_REF int predict_nnz_chroma(AVCCommonObj *video, int i, int j)
+{
+ int pred_nnz = 0;
+ int cnt = 1;
+ AVCMacroblock *tempMB;
+
+ /* left block */
+ /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, -1, 0, &pix);
+ leftMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+ if (i&1)
+ {
+ pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
+
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ tempMB = video->mblock + video->mbAddrA;
+ pred_nnz = tempMB->nz_coeff[(j<<2)+i+1];
+ }
+ else
+ {
+ cnt = 0;
+ }
+ }
+
+
+ /* top block */
+ /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, 0, -1, &pix);
+ topMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (j&1)
+ {
+ pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
+ cnt++;
+ }
+ else
+ {
+ if (video->mbAvailB)
+ {
+ tempMB = video->mblock + video->mbAddrB;
+ pred_nnz += tempMB->nz_coeff[20+i];
+ cnt++;
+ }
+
+ }
+
+ if (cnt == 2)
+ {
+ pred_nnz = (pred_nnz + 1) >> 1;
+ }
+
+ return pred_nnz;
+}
+
+OSCL_EXPORT_REF void GetMotionVectorPredictor(AVCCommonObj *video, int encFlag)
+{
+ AVCMacroblock *currMB = video->currMB;
+ AVCMacroblock *MB_A, *MB_B, *MB_C, *MB_D;
+ int block_x, block_y, block_x_1, block_y_1, new_block_x;
+ int mbPartIdx, subMbPartIdx, offset_indx;
+ int16 *mv, pmv_x, pmv_y;
+ int nmSubMbHeight, nmSubMbWidth, mbPartIdx_X, mbPartIdx_Y;
+ int avail_a, avail_b, avail_c;
+ const static uint32 C = 0x5750;
+ int i, j, offset_MbPart_indx, refIdxLXA, refIdxLXB, refIdxLXC = 0, curr_ref_idx;
+ int pmv_A_x, pmv_B_x, pmv_C_x = 0, pmv_A_y, pmv_B_y, pmv_C_y = 0;
+
+ /* we have to take care of Intra/skip blocks somewhere, i.e. set MV to 0 and set ref to -1! */
+ /* we have to populate refIdx as well */
+
+
+ MB_A = &video->mblock[video->mbAddrA];
+ MB_B = &video->mblock[video->mbAddrB];
+
+
+ if (currMB->mbMode == AVC_SKIP /* && !encFlag */) /* only for decoder */
+ {
+ currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] = currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = 0;
+ if (video->mbAvailA && video->mbAvailB)
+ {
+ if ((MB_A->ref_idx_L0[1] == 0 && MB_A->mvL0[3] == 0) ||
+ (MB_B->ref_idx_L0[2] == 0 && MB_B->mvL0[12] == 0))
+ {
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ return;
+ }
+ }
+ else
+ {
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ return;
+ }
+ video->mvd_l0[0][0][0] = 0;
+ video->mvd_l0[0][0][1] = 0;
+ }
+
+ MB_C = &video->mblock[video->mbAddrC];
+ MB_D = &video->mblock[video->mbAddrD];
+
+ offset_MbPart_indx = 0;
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ offset_indx = 0;
+ nmSubMbHeight = currMB->SubMbPartHeight[mbPartIdx] >> 2;
+ nmSubMbWidth = currMB->SubMbPartWidth[mbPartIdx] >> 2;
+ mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1) << 1;
+ mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) & 2;
+
+ for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+ {
+ block_x = mbPartIdx_X + ((subMbPartIdx + offset_indx) & 1);
+ block_y = mbPartIdx_Y + (((subMbPartIdx + offset_indx) >> 1) & 1);
+
+ block_x_1 = block_x - 1;
+ block_y_1 = block_y - 1;
+ refIdxLXA = refIdxLXB = refIdxLXC = -1;
+ pmv_A_x = pmv_A_y = pmv_B_x = pmv_B_y = pmv_C_x = pmv_C_y = 0;
+
+ if (block_x)
+ {
+ avail_a = 1;
+ refIdxLXA = currMB->ref_idx_L0[(block_y & 2) + (block_x_1 >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y << 2) + block_x_1);
+ pmv_A_x = *mv++;
+ pmv_A_y = *mv;
+ }
+ else
+ {
+ avail_a = video->mbAvailA;
+ if (avail_a)
+ {
+ refIdxLXA = MB_A->ref_idx_L0[(block_y & 2) + 1];
+ mv = (int16*)(MB_A->mvL0 + (block_y << 2) + 3);
+ pmv_A_x = *mv++;
+ pmv_A_y = *mv;
+ }
+ }
+
+ if (block_y)
+ {
+ avail_b = 1;
+ refIdxLXB = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x);
+ pmv_B_x = *mv++;
+ pmv_B_y = *mv;
+ }
+
+ else
+ {
+ avail_b = video->mbAvailB;
+ if (avail_b)
+ {
+ refIdxLXB = MB_B->ref_idx_L0[2 + (block_x >> 1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + block_x);
+ pmv_B_x = *mv++;
+ pmv_B_y = *mv;
+ }
+ }
+
+ new_block_x = block_x + (currMB->SubMbPartWidth[mbPartIdx] >> 2) - 1;
+ avail_c = (C >> ((block_y << 2) + new_block_x)) & 0x1;
+
+ if (avail_c)
+ {
+ /* it guaranteed that block_y > 0 && new_block_x<3 ) */
+ refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + ((new_block_x+1) >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + (new_block_x + 1));
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ else
+ {
+ if (block_y == 0 && new_block_x < 3)
+ {
+ avail_c = video->mbAvailB;
+ if (avail_c)
+ {
+ refIdxLXC = MB_B->ref_idx_L0[2 + ((new_block_x+1)>>1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + (new_block_x + 1));
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else if (block_y == 0 && new_block_x == 3)
+ {
+ avail_c = video->mbAvailC;
+ if (avail_c)
+ {
+ refIdxLXC = MB_C->ref_idx_L0[2];
+ mv = (int16*)(MB_C->mvL0 + 12);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+
+ if (avail_c == 0)
+ { /* check D */
+ if (block_x && block_y)
+ {
+ avail_c = 1;
+ refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x_1 >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x_1);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ else if (block_y)
+ {
+ avail_c = video->mbAvailA;
+ if (avail_c)
+ {
+ refIdxLXC = MB_A->ref_idx_L0[(block_y_1 & 2) + 1];
+ mv = (int16*)(MB_A->mvL0 + (block_y_1 << 2) + 3);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else if (block_x)
+ {
+ avail_c = video->mbAvailB;
+ if (avail_c)
+ {
+ refIdxLXC = MB_B->ref_idx_L0[2 + (block_x_1 >> 1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + block_x_1);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else
+ {
+ avail_c = video->mbAvailD;
+ if (avail_c)
+ {
+ refIdxLXC = MB_D->ref_idx_L0[3];
+ mv = (int16*)(MB_D->mvL0 + 15);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ }
+ }
+
+ offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
+
+ curr_ref_idx = currMB->ref_idx_L0[(block_y & 2) + (block_x >> 1)];
+
+ if (avail_a && !(avail_b || avail_c))
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ else if (((curr_ref_idx == refIdxLXA) + (curr_ref_idx == refIdxLXB) + (curr_ref_idx == refIdxLXC)) == 1)
+ {
+ if (curr_ref_idx == refIdxLXA)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ else if (curr_ref_idx == refIdxLXB)
+ {
+ pmv_x = pmv_B_x;
+ pmv_y = pmv_B_y;
+ }
+ else
+ {
+ pmv_x = pmv_C_x;
+ pmv_y = pmv_C_y;
+ }
+ }
+ else
+ {
+ pmv_x = AVC_MEDIAN(pmv_A_x, pmv_B_x, pmv_C_x);
+ pmv_y = AVC_MEDIAN(pmv_A_y, pmv_B_y, pmv_C_y);
+ }
+
+ /* overwrite if special case */
+ if (currMB->NumMbPart == 2)
+ {
+ if (currMB->MbPartWidth == 16)
+ {
+ if (mbPartIdx == 0)
+ {
+ if (refIdxLXB == curr_ref_idx)
+ {
+ pmv_x = pmv_B_x;
+ pmv_y = pmv_B_y;
+ }
+ }
+ else if (refIdxLXA == curr_ref_idx)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ }
+ else
+ {
+ if (mbPartIdx == 0)
+ {
+ if (refIdxLXA == curr_ref_idx)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ }
+ else if (refIdxLXC == curr_ref_idx)
+ {
+ pmv_x = pmv_C_x;
+ pmv_y = pmv_C_y;
+ }
+ }
+ }
+
+ mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
+
+ if (encFlag) /* calculate residual MV video->mvd_l0 */
+ {
+ video->mvd_l0[mbPartIdx][subMbPartIdx][0] = *mv++ - pmv_x;
+ video->mvd_l0[mbPartIdx][subMbPartIdx][1] = *mv++ - pmv_y;
+ }
+ else /* calculate original MV currMB->mvL0 */
+ {
+ pmv_x += video->mvd_l0[mbPartIdx][subMbPartIdx][0];
+ pmv_y += video->mvd_l0[mbPartIdx][subMbPartIdx][1];
+
+ for (i = 0; i < nmSubMbHeight; i++)
+ {
+ for (j = 0; j < nmSubMbWidth; j++)
+ {
+ *mv++ = pmv_x;
+ *mv++ = pmv_y;
+ }
+ mv += (8 - (j << 1));
+ }
+ }
+ }
+ offset_MbPart_indx = currMB->MbPartWidth >> 4;
+
+ }
+}
+
+