diff options
Diffstat (limited to 'media/libstagefright/codecs/avc/common/src/mb_access.cpp')
-rw-r--r-- | media/libstagefright/codecs/avc/common/src/mb_access.cpp | 471 |
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; + + } +} + + |