diff options
Diffstat (limited to 'media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c')
-rw-r--r-- | media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c | 1892 |
1 files changed, 1892 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c new file mode 100644 index 0000000..33dbf3f --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c @@ -0,0 +1,1892 @@ +/** x + * + * File Name: omxVCM4P10_MotionEstimationMB.c + * OpenMAX DL: v1.0.2 + * Revision: 9641 + * Date: Thursday, February 7, 2008 + * + * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. + * + * + * Description: + * This function perform MB level motion estimation + * + */ + +#include "omxtypes.h" +#include "armOMX.h" +#include "omxVC.h" + +#include "armCOMM.h" +#include "armVC.h" + +#define ARM_VCM4P10_MAX_FRAMES (15) +#define ARM_VCM4P10_MAX_4x4_SAD (0xffff) +#define ARM_VCM4P10_MAX_MODE_VALUE (0xffffffff) +#define ARM_VCM4P10_MAX_MODES (16) +#define ARM_VCM4P10_MB_BLOCK_SIZE (16) +#define ARM_VCM4P10_MEDIAN(a,b,c) (a>b?a>c?b>c?b:c:a:b>c?a>c?a:c:b) +#define ARM_VCM4P10_SHIFT_QP (12) + +#define ARM_VCM4P10_MVPRED_MEDIAN (0) +#define ARM_VCM4P10_MVPRED_L (1) +#define ARM_VCM4P10_MVPRED_U (2) +#define ARM_VCM4P10_MVPRED_UR (3) + +#define ARM_VCM4P10_MB_BLOCK_SIZE (16) +#define ARM_VCM4P10_BLOCK_SIZE (4) +#define ARM_VCM4P10_MAX_COST (1 << 30) +#define ARM_VCM4P10_INVALID_BLOCK (-2) + + +/** + * Function: armVCM4P10_CalculateBlockSAD + * + * Description: + * Calculate SAD value for the selected MB encoding mode and update + * pDstBlockSAD parameter. These SAD values are calculated 4x4 blocks at + * a time and in the scan order. + * + * Remarks: + * + * Parameters: + * [in] pSrcMBInfo - + * [in] pSrcCurrBuf - + * [in] SrcCurrStep - + * [in] pSrcRefBufList- + * [in] SrcRefStep - + * [in] pSrcRecBuf - + * [in] SrcRecStep - + * [in] pRefRect - + * [in] pCurrPointPos - + * [in] Lambda - + * [in] pMESpec - + * [in] pMBInter - + * [in] pMBIntra - + * [out] pDstBlockSAD - pointer to 16 element array for SAD corresponding to 4x4 blocks + * Return Value: + * None + * + */ + +static OMXResult armVCM4P10_CalculateBlockSAD( + OMXVCM4P10MBInfo *pSrcMBInfo, + const OMX_U8 *pSrcCurrBuf, + OMX_S32 SrcCurrStep, + const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], + OMX_S32 SrcRefStep, + const OMX_U8 *pSrcRecBuf, + OMX_S32 SrcRecStep, + const OMXRect *pRefRect, + const OMXVCM4P2Coordinate *pCurrPointPos, + const OMXVCM4P10MBInfoPtr *pMBInter, + const OMXVCM4P10MBInfoPtr *pMBIntra, + OMX_U16 *pDstBlockSAD) +{ + OMX_INT InvalidSAD = 0; + OMX_INT i; + + OMX_U8 Buffer [16*16 + 15]; + OMX_U8 *pTempDstBuf; + OMX_S32 TempDstStep; + OMX_U8 *pTempRefBuf; + OMX_S32 TempRefStep; + + /* Temporary buffer to store the predicted mb coefficients */ + pTempDstBuf = armAlignTo16Bytes(Buffer); + TempDstStep = 16; + + /* Update pDstBlockSAD if MB is a valid type */ + if (pSrcMBInfo) + { + OMX_U32 Width=0, Height=0, MaxXPart, MaxYPart,MaxSubXPart,MaxSubYPart; + + /* Depending on type of MB, do prediction and fill temp buffer */ + switch (pSrcMBInfo->mbType) + { + case OMX_VC_P_16x16: + Width = 16; + Height = 16; + break; + case OMX_VC_P_16x8: + Width = 16; + Height = 8; + break; + case OMX_VC_P_8x16: + Width = 8; + Height = 16; + break; + case OMX_VC_P_8x8: + Width = 8; + Height = 8; + break; + case OMX_VC_INTRA_4x4: + { + /* Create predicted MB Intra4x4 mode */ + OMX_S32 PredIntra4x4Mode [5][9]; + OMX_S32 x, y, Block8x8, Block4x4, BlockX, BlockY; + OMX_U8 pSrcYBuff [(16*3)*(16*2)]; + OMX_U8 *pSrcY; + OMX_S32 StepSrcY; + OMX_S32 availability; + + for (y = 0; y < 5; y++) + { + for (x = 0; x < 9; x++) + { + /* + * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this + * 4x4 block is not available + */ + PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK; + } + } + + /* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/ + for (x = 0; x < 4; x++) + { + /* Store values of b0, b1, b2, b3 */ + if (pMBIntra[1] != NULL) + { + PredIntra4x4Mode [0][x + 1] = + pMBIntra[1]->pIntra4x4PredMode[3*4 + x]; + } + + /* Store values of d0, d1, d2, d3 */ + if (pMBIntra[3] != NULL) + { + PredIntra4x4Mode [0][x + 5] = + pMBIntra[3]->pIntra4x4PredMode[3*4 + x]; + } + } + + /* Store values of c3 */ + if (pMBIntra[2] != NULL) + { + PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15]; + } + + for (y = 0; y < 4; y++) + { + /* Store values of a0, a1, a2, a3 */ + if (pMBIntra[0] != NULL) + { + PredIntra4x4Mode [y + 1][0] = + pMBIntra[0]->pIntra4x4PredMode[y*4 + 3]; + } + } + + /* + * Update neighbouring Pred mode array which will be used for + * prediction of Intra4x4 modes. + */ + + pSrcY = pSrcYBuff; + StepSrcY = 16 * 3; + for (y = 0; y < (16 * 2); y++) + { + for (x = 0; x < (16 * 3); x++) + { + pSrcY [StepSrcY * y + x] = + pSrcRecBuf [SrcRecStep * (y - 16) + x - 16]; + } + } + + + /* for each 8x8 block */ + for (Block8x8 = 0; Block8x8 < 4; Block8x8++) + { + /* for each 4x4 block inside 8x8 block */ + for (Block4x4 = 0; Block4x4 < 4; Block4x4++) + { + /* Get block cordinates from 8x8 block index and 4x4 block index */ + BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1); + BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1); + + /* Add offset to point to start of current MB in the array pIntra4x4PredMode */ + x = BlockX + 1; + y = BlockY + 1; + + availability = 0; + + /* Check for availability of LEFT Block */ + if (PredIntra4x4Mode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK) + { + availability |= OMX_VC_LEFT; + } + + /* Check for availability of UPPER Block */ + if (PredIntra4x4Mode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK) + { + availability |= OMX_VC_UPPER; + } + + /* Check for availability of UPPER LEFT Block */ + if (PredIntra4x4Mode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK) + { + availability |= OMX_VC_UPPER_LEFT; + } + + PredIntra4x4Mode [y][x] = pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX]; + x = BlockX * 4; + y = BlockY * 4; + + pSrcY = pSrcYBuff + 16 * StepSrcY + 16 + y * StepSrcY + x; + + omxVCM4P10_PredictIntra_4x4( + pSrcY - 1, + pSrcY - StepSrcY, + pSrcY - StepSrcY - 1, + pTempDstBuf + x + y * TempDstStep, + StepSrcY, + TempDstStep, + pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX], + availability); + + for (BlockY=0;BlockY<4;BlockY++) + { + for(BlockX=0;BlockX<4;BlockX++) + { + pSrcY [BlockY * StepSrcY + BlockX] = + (OMX_U8)(*(pTempDstBuf + x + y * TempDstStep + BlockY * TempDstStep + BlockX)); + } + } + + } + } + break; + } + case OMX_VC_INTRA_16x16: + { + OMX_U32 MBPosX = pCurrPointPos->x >> 4; + OMX_U32 MBPosY = pCurrPointPos->y >> 4; + OMX_U32 availability = 0; + + /* Check for availability of LEFT MB */ + if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0)) + { + availability |= OMX_VC_LEFT; + } + + /* Check for availability of UP MB */ + if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0)) + { + availability |= OMX_VC_UPPER; + } + + /* Check for availability of UP-LEFT MB */ + if ((MBPosX > 0) && (MBPosY > 0) && + (pMBIntra [2] != 0 || pMBInter [2] != 0)) + { + availability |= OMX_VC_UPPER_LEFT; + } + + omxVCM4P10_PredictIntra_16x16( + pSrcRecBuf - 1, + pSrcRecBuf - SrcRecStep, + pSrcRecBuf - SrcRecStep - 1, + pTempDstBuf, + SrcRecStep, + TempDstStep, + pSrcMBInfo->Intra16x16PredMode, + availability); + + break; + } + + case OMX_VC_INTER_SKIP: + case OMX_VC_PREF0_8x8: + case OMX_VC_INTRA_PCM: + default: + /* These cases will update pDstBlockSAD with MAX value */ + InvalidSAD = 1; + break; + } + + /* INTER MB */ + if ((pSrcMBInfo->mbType == OMX_VC_P_16x16) || + (pSrcMBInfo->mbType == OMX_VC_P_8x16) || + (pSrcMBInfo->mbType == OMX_VC_P_16x8) || + (pSrcMBInfo->mbType == OMX_VC_P_8x8)) + { + const OMX_U8 *pTempSrcBuf; + OMX_S32 TempSrcStep; + OMX_S32 mvx,mvy; + OMX_U32 PartX, PartY, SubPartX, SubPartY; + + TempSrcStep = SrcRefStep; + + MaxXPart = 16/Width; + MaxYPart = 16/Height; + + + for (PartY = 0; PartY < MaxYPart; PartY++) + { + for (PartX = 0; PartX < MaxXPart; PartX++) + { + + pTempSrcBuf = pSrcRefBufList[pSrcMBInfo->pRefL0Idx[PartY * 2 + PartX]]; + + if (MaxXPart == 2 && MaxYPart == 2) + { + switch (pSrcMBInfo->subMBType[PartY*2+PartX]) + { + case OMX_VC_SUB_P_8x8: + Width = 8; + Height = 8; + break; + case OMX_VC_SUB_P_8x4: + Width = 8; + Height = 4; + break; + case OMX_VC_SUB_P_4x8: + Width = 4; + Height = 8; + break; + case OMX_VC_SUB_P_4x4: + Width = 4; + Height = 4; + break; + default: + /* Default */ + Width = 4; + Height = 4; + break; + } + + MaxSubXPart = 8/Width; + MaxSubYPart = 8/Height; + + for (SubPartY = 0; SubPartY < MaxSubYPart; SubPartY++) + { + for (SubPartX = 0; SubPartX < MaxSubXPart; SubPartX++) + { + mvx = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dx; + mvy = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dy; + armVCM4P10_Interpolate_Luma( + pTempSrcBuf + (8*PartX + 4*SubPartX + (mvx/4)) + (8*PartY + 4*SubPartY + (mvy/4)) * TempSrcStep, + TempSrcStep, + pTempDstBuf + (8*PartX + 4*SubPartX) + (8*PartY + 4*SubPartY) * TempDstStep, + TempDstStep, + Width, + Height, + mvx & 3, + mvy & 3 + ); + } + } + } + else + { + + mvx = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dx; + mvy = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dy; + armVCM4P10_Interpolate_Luma( + pTempSrcBuf + (8*PartX + (mvx/4)) + (8*PartY + (mvy/4)) * TempSrcStep, + TempSrcStep, + pTempDstBuf + (8*PartX) + (8*PartY) * TempDstStep, + TempDstStep, + Width, + Height, + mvx & 3, + mvy & 3 + ); + + } + } + } + } + } + else + { + InvalidSAD = 1; + } + + /* Calculate SAD from predicted buffer */ + if (!InvalidSAD) + { + OMX_U32 x8x8, y8x8, x4x4, y4x4, Block8x8, Block4x4; + OMX_S32 SAD; + + pTempRefBuf = pTempDstBuf; + TempRefStep = 16; + + /* SAD for each 4x4 block in scan order */ + for (Block8x8 = 0; Block8x8 < 4; Block8x8++) + { + x8x8 = 8*(Block8x8 & 1); + y8x8 = 8*(Block8x8 >> 1); + for (Block4x4 = 0; Block4x4 < 4; Block4x4++) + { + x4x4 = 4*(Block4x4 & 1); + y4x4 = 4*(Block4x4 >> 1); + + armVCCOMM_SAD( + pSrcCurrBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * SrcCurrStep, + SrcCurrStep, + pTempRefBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * TempRefStep, + TempRefStep, + &SAD, + 4, /* Height */ + 4); /* Width */ + *(pDstBlockSAD + 4 * Block8x8 + Block4x4) = (SAD < 0x7fff) ? (OMX_U16) SAD : ARM_VCM4P10_MAX_MODE_VALUE; + } + } + } + else + { + /* Fill SADs with max values and return*/ + for (i = 0; i < 16; i++) + { + pDstBlockSAD [i] = ARM_VCM4P10_MAX_4x4_SAD; + } + } + return OMX_Sts_NoErr; +} + + + +/** + * Function: armVCM4P10_Mode4x4Decision + * + * Description: + * Intra 4x4 Mode decision by calculating cost for all possible modes and + * choosing the best mode + * + * Remarks: + * + * Parameters: + * [in] pSrcCurrBuf - Pointer to the start of current Macroblock + * [in] SrcCurrStep - Step size of the pointer pSrcCurrBuf + * [in/out] pSrcDstMBCurr - Pointer to the OMXVCM4P10MBInfo which will be updated for + * field pIntra4x4PredMode of the current block. + * [in] Block8x8 - Index 8x8 block in which current 4x4 block belongs + * [in] Block4x4 - Index of current 4x4 block + * [in/out] pPredIntra4x4SrcY - Pointer to current block location in buffer + * with reconstructed values. This will be modified by this + * function with best mode predicted values + * [in] StepPredIntra4x4SrcY - Step size of the pointer pPredIntra4x4SrcY + * [in] pIntra4x4PredMode - Array of Intra 4x4 prediction mode for the MB. + * Current MB modes starts at [1,1]. + * [in] pBestCost - Cost for the Best Intra 4x4 mode + * Return Value: + * None + * + */ +static OMXVoid armVCM4P10_Mode4x4Decision ( + const OMX_U8* pSrcCurrBuf, + OMX_S32 SrcCurrStep, + OMXVCM4P10MBInfo *pSrcDstMBCurr, + OMX_S32 Block8x8, + OMX_S32 Block4x4, + OMX_U8 *pPredIntra4x4SrcY, + OMX_S32 StepPredIntra4x4SrcY, + OMX_S32 pIntra4x4PredMode [][9], + OMX_S32 *pBestCost +) +{ + OMX_S32 i, j, x, y, BlockX, BlockY, mode; + OMX_S32 Cost, BestCost; + OMX_U8 *pSrcY; + OMX_S32 StepSrcY; + OMX_S32 availability = 0; + OMX_U8 pPredBlock [4*4]; + OMXResult Ret = OMX_Sts_Err; + + /* Get block cordinates from 8x8 block index and 4x4 block index */ + BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1); + BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1); + + /* Add offset to point to start of current MB in the array pIntra4x4PredMode */ + x = BlockX + 1; + y = BlockY + 1; + + /* Check for availability of LEFT Block */ + if (pIntra4x4PredMode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK) + { + availability |= OMX_VC_LEFT; + } + + /* Check for availability of UPPER Block */ + if (pIntra4x4PredMode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK) + { + availability |= OMX_VC_UPPER; + } + + /* Check for availability of UPPER LEFT Block */ + if (pIntra4x4PredMode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK) + { + availability |= OMX_VC_UPPER_LEFT; + } + + pSrcY = pPredIntra4x4SrcY + + StepPredIntra4x4SrcY * (BlockY << 2) + + (BlockX << 2); + + StepSrcY = StepPredIntra4x4SrcY; + + x = BlockX * 4; + y = BlockY * 4; + + Cost = BestCost = ARM_VCM4P10_MAX_COST; + + /* Go through each mode for minim cost */ + for (mode = 0; mode < 9; mode++) + { + Ret = omxVCM4P10_PredictIntra_4x4( + pSrcY - 1, + pSrcY - StepSrcY, + pSrcY - StepSrcY - 1, + pPredBlock, + StepSrcY, + 4, + (OMXVCM4P10Intra4x4PredMode) mode, + availability); + + if (Ret == OMX_Sts_NoErr) + { + armVCCOMM_SAD( + pSrcCurrBuf + (y * SrcCurrStep) + x, + SrcCurrStep, + pPredBlock, + 4, + &Cost, + 4, + 4); + + if (Cost < BestCost) + { + BestCost = Cost; + + pIntra4x4PredMode [BlockY + 1][BlockX + 1] = + (OMXVCM4P10Intra4x4PredMode) mode; + pSrcDstMBCurr->pIntra4x4PredMode [BlockY * 4 + BlockX] = + (OMXVCM4P10Intra4x4PredMode) mode; + + for (j = 0; j < 4; j++) + { + for (i = 0; i < 4; i++) + { + pSrcY [StepSrcY * j + i] = pPredBlock [4 * j + i]; + } + } + } + } + } + + *pBestCost = BestCost; + return; +} + +/** + * Function: armVCM4P10_SetMotionVectorPredictor + * + * Description: + * This function will do the MV Prediction for Inter MBs + * + * Parameters: + * [in] BlockStartX - Start X index in integer pels in current Block + * [in] BlockStartY - Start Y index in integer pels in current Block + * [in] BlockSizeX - Width of current block + * [in] BlockSizeY - Height of current block + * [in] RefFrame - Index of the reference frame for prediction + * [in] pRefFrArr - Pointer to Ref array storing neighbouring MVs for MV prediction + * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction + * [out] pMVPred - Pointer to predicted MVs + * Remarks: + * + * Return Value: + * None + * + */ +static OMXVoid armVCM4P10_SetMotionVectorPredictor( + OMX_U32 BlockStartX, + OMX_U32 BlockStartY, + OMX_U32 BlockSizex, + OMX_U32 BlockSizey, + OMX_S32 RefFrame, + OMX_S32 pRefFrArr[][6], + OMXVCMotionVector pMVArr[][12], + OMXVCMotionVector *pMVPred +) +{ + OMX_S32 RFrameL; /* Left */ + OMX_S32 RFrameU; /* Up */ + OMX_S32 RFrameUR; /* Up-Right */ + + OMX_S32 BlockX, BlockY, BlockXFr, BlockYFr, MVPredType; + OMX_S32 BlockXPlusOff, BlockXPlusOffFr, BlockXMin1Fr, BlockYMin1Fr; + + BlockX = 4 + (BlockStartX >> 2); + BlockY = 4 + (BlockStartY >> 2); + BlockXPlusOff = BlockX + (BlockSizex >> 2); + + BlockXFr = BlockX >> 1; + BlockYFr = BlockY >> 1; + BlockXMin1Fr = (BlockX - 1) >> 1; + BlockYMin1Fr = (BlockY - 1) >> 1; + BlockXPlusOffFr = BlockXPlusOff >> 1; + + MVPredType = ARM_VCM4P10_MVPRED_MEDIAN; + + RFrameL = pRefFrArr [BlockYFr][BlockXMin1Fr]; + RFrameU = pRefFrArr [BlockYMin1Fr][BlockXFr]; + RFrameUR = pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr]; + + if (RFrameUR == ARM_VCM4P10_INVALID_BLOCK) + { + RFrameUR = pRefFrArr [BlockYMin1Fr][BlockXMin1Fr]; + } + + /* + * Prediction if only one of the neighbors uses the reference frame + * we are checking + */ + + if (RFrameL == RefFrame && RFrameU != RefFrame && RFrameUR != RefFrame) + { + MVPredType = ARM_VCM4P10_MVPRED_L; + } + else if(RFrameL != RefFrame && RFrameU == RefFrame && RFrameUR != RefFrame) + { + MVPredType = ARM_VCM4P10_MVPRED_U; + } + else if(RFrameL != RefFrame && RFrameU != RefFrame && RFrameUR == RefFrame) + { + MVPredType = ARM_VCM4P10_MVPRED_UR; + } + + /* Directional predictions */ + else if(BlockSizex == 8 && BlockSizey == 16) + { + if(BlockStartX == 0) + { + if(RFrameL == RefFrame) + { + MVPredType = ARM_VCM4P10_MVPRED_L; + } + } + else + { + if (RFrameUR == RefFrame) + { + MVPredType = ARM_VCM4P10_MVPRED_UR; + } + } + } + else if(BlockSizex == 16 && BlockSizey == 8) + { + if(BlockStartY == 0) + { + if(RFrameU == RefFrame) + { + MVPredType = ARM_VCM4P10_MVPRED_U; + } + } + else + { + if(RFrameL == RefFrame) + { + MVPredType = ARM_VCM4P10_MVPRED_L; + } + } + } + + switch (MVPredType) + { + case ARM_VCM4P10_MVPRED_MEDIAN: + if (!(pRefFrArr [BlockYMin1Fr][BlockXMin1Fr] == ARM_VCM4P10_INVALID_BLOCK || + pRefFrArr [BlockYMin1Fr][BlockXFr] == ARM_VCM4P10_INVALID_BLOCK || + pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr] == ARM_VCM4P10_INVALID_BLOCK)) + { + pMVPred->dx = pMVArr [BlockY][BlockX - 1].dx; + pMVPred->dy = pMVArr [BlockY][BlockX - 1].dy; + } + else + { + pMVPred->dx = + ARM_VCM4P10_MEDIAN(pMVArr [BlockY][BlockX - 1].dx, + pMVArr [BlockY - 1][BlockX].dx, + pMVArr [BlockY - 1][BlockXPlusOff].dx); + pMVPred->dy = + ARM_VCM4P10_MEDIAN(pMVArr [BlockY][BlockX - 1].dy, + pMVArr [BlockY - 1][BlockX].dy, + pMVArr [BlockY - 1][BlockXPlusOff].dy); + } + break; + + case ARM_VCM4P10_MVPRED_L: + pMVPred->dx = pMVArr [BlockY][BlockX - 1].dx; + pMVPred->dy = pMVArr [BlockY][BlockX - 1].dy; + break; + case ARM_VCM4P10_MVPRED_U: + pMVPred->dx = pMVArr [BlockY - 1][BlockX].dx; + pMVPred->dy = pMVArr [BlockY - 1][BlockX].dy; + break; + case ARM_VCM4P10_MVPRED_UR: + if (pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr] != ARM_VCM4P10_INVALID_BLOCK) + { + pMVPred->dx = pMVArr [BlockY - 1][BlockXPlusOff].dx; + pMVPred->dy = pMVArr [BlockY - 1][BlockXPlusOff].dy; + } + else + { + pMVPred->dx = pMVArr [BlockY - 1][BlockX - 1].dx; + pMVPred->dy = pMVArr [BlockY - 1][BlockX - 1].dy; + } + break; + default: + break; + } + + return; +} + +/** + * Function: armVCM4P10_BlockMotionSearch + * + * Description: + * Gets best MV for the current block + * + * Parameters: + * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock + * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf + * [in] pSrcRefY - Pointer to the start of luma component of co-located reference MB + * [in] nSrcRefStep - Step size for the pointer pSrcRefY + * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin. + * [in] pCurrPointPos Position of the current macroblock in the current plane. + * [in] pMESpec - Motion estimation structure + * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four + * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right). + * [in] nLamda - For calculating the cost + * [out] pBestCost - Minimum cost for encoding current block + * [out] pBestMV - MV corresponding to best cost + * [in] BlockStartX - Block start X index in integer pels + * [in] BlockStartY - Block start Y index in integer pels + * [in] BlockSizeX - Width of current block + * [in] BlockSizeY - Height of current block + * [in] RefFrame - Index of the reference frame for prediction + * [in] pRefFrArr - Pointer to reference frame array storing neighbouring MVs for prediction + * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction + * [in] pMVPred - Pointer to MV predicted from neighbour MVs + * Remarks: + * + * Return Value: + * OMXResult + * + */ +static OMXResult armVCM4P10_BlockMotionSearch( + const OMX_U8* pSrcCurrBuf, + OMX_S32 SrcCurrStep, + const OMX_U8* pSrcRefY, + OMX_S32 nSrcRefStep, + const OMXRect *pRefRect, + const OMXVCM4P2Coordinate *pCurrPointPos, + void* pMESpec, + + OMX_S32 nLamda, + OMX_S32* pBestCost, + OMXVCMotionVector *pBestMV, + + OMX_U32 BlockStartX, + OMX_U32 BlockStartY, + OMX_U32 BlockSizeX, + OMX_U32 BlockSizeY, + OMX_S32 RefFrame, + OMX_S32 pRefFrArr [][6], + OMXVCMotionVector pMVArr [][12], + OMXVCMotionVector *pMVPred + ) +{ + + OMXVCMotionVector MVCalculated, MVCandidate; + OMX_S32 Cost; + OMXResult RetValue; + OMXVCM4P10MEParams *pMEParams; + OMXVCM4P2Coordinate CurrBlockPos; + + /* Get Predicted Motion Vectors */ + armVCM4P10_SetMotionVectorPredictor ( + BlockStartX, + BlockStartY, + BlockSizeX, + BlockSizeY, + RefFrame, + pRefFrArr, + pMVArr, + pMVPred); + + /* Initialize candidate MV */ + MVCandidate.dx = 0; + MVCandidate.dy = 0; + + CurrBlockPos.x = pCurrPointPos->x + BlockStartX; + CurrBlockPos.y = pCurrPointPos->y + BlockStartY; + + /* Block Match Integer */ + RetValue = omxVCM4P10_BlockMatch_Integer ( + pSrcCurrBuf, + SrcCurrStep, + pSrcRefY, + nSrcRefStep, + pRefRect, + &CurrBlockPos, + BlockSizeX, + BlockSizeY, + nLamda, + pMVPred, + &MVCandidate, + &MVCalculated, + &Cost, + pMESpec); + + /* updated BestMV*/ + /**pBestCost = Cost; + pBestMV->dx = MVCalculated.dx; + pBestMV->dy = MVCalculated.dy;*/ + + pMEParams = (OMXVCM4P10MEParams *) pMESpec; + + /* Block Match Half pel */ + if (pMEParams->halfSearchEnable) + { + RetValue = omxVCM4P10_BlockMatch_Half( + pSrcCurrBuf, + SrcCurrStep, + pSrcRefY, + nSrcRefStep, + BlockSizeX, + BlockSizeY, + nLamda, + pMVPred, + &MVCalculated, /* input/output*/ + &Cost); + } + + /* Block Match Quarter pel */ + if (pMEParams->quarterSearchEnable) + { + RetValue = omxVCM4P10_BlockMatch_Quarter( + pSrcCurrBuf, + SrcCurrStep, + pSrcRefY, + nSrcRefStep, + BlockSizeX, + BlockSizeY, + nLamda, + pMVPred, + &MVCalculated, + &Cost); + } + + /* updated Best Cost and Best MV */ + *pBestCost = Cost; + pBestMV->dx = MVCalculated.dx; + pBestMV->dy = MVCalculated.dy; + + /* + * Skip MB cost calculations of 16x16 inter mode + */ + return RetValue; +} + +/** + * Function: armVCM4P10_PartitionME + * + * Description: + * Gets best cost for the current partition + * + * Parameters: + * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock + * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf + * [in] pSrcRefBufList - Pointer to List of ref buffer of co-located reference MB + * [in] nSrcRefStep - Step size for the pointer pSrcRefY + * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin. + * [in] pCurrPointPos Position of the current macroblock in the current plane. + * [in] pMESpec - Motion estimation structure + * [in] PartWidth - Width of current partition + * [in] PartHeight - Height of current partition + * [in] BlockWidth - Width of current block + * [in] BlockHeight - Height of current block + * [in] PartStartX - Partition start X index in integer pels + * [in] PartStartY - Partition start Y index in integer pels + * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction + * [in] pRefFrArr - Pointer to reference frame array storing neighbouring MVs for prediction + * [in] Lambda - For calculating the cost + * [out] pCost - Pointer to cost for Inter MB + * + * Return Value: + * OMXResult + * + */ +static OMXResult armVCM4P10_PartitionME ( + const OMX_U8* pSrcCurrBuf, + OMX_S32 SrcCurrStep, + const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], + OMX_S32 SrcRefStep, + const OMXRect *pRefRect, + const OMXVCM4P2Coordinate *pCurrPointPos, + void* pMESpec, + + OMX_S32 PartWidth, + OMX_S32 PartHeight, + OMX_S32 BlockWidth, + OMX_S32 BlockHeight, + OMX_S32 PartStartX, + OMX_S32 PartStartY, + + OMXVCMotionVector pMVArr [][12], + OMX_S32 pRefFrArr [][6], + OMXVCMotionVector pMVPredArr [][4], + + OMX_S32 Lambda, + OMX_S32 *pCost +) +{ + OMX_U32 x, y, i, j, ref, OffX, OffY, OffSrc, OffRef; + OMX_S32 BlockCost, PartitionCost, BestCost; + OMX_S32 BestRefFrame=0; + OMXVCMotionVector BestMV [4][4]; + OMXVCMotionVector BestMVPred [4][4]; + OMXVCMotionVector MVPred; + OMXVCMotionVector DstMV; + + BestCost = ARM_VCM4P10_MAX_COST; + + for (ref = 0; ref < ARM_VCM4P10_MAX_FRAMES; ref++) + { + if (pSrcRefBufList [ref] == NULL) + { + /* No reference frame, continue */ + continue; + } + + PartitionCost = 0; + + for (y = 0; y < PartHeight; y += BlockHeight) + { + for (x = 0; x < PartWidth; x += BlockWidth) + { + OffSrc = SrcCurrStep * (PartStartY + y) + PartStartX + x; + OffRef = SrcRefStep * (PartStartY + y) + PartStartX + x; + armVCM4P10_BlockMotionSearch ( + pSrcCurrBuf + OffSrc, + SrcCurrStep, + pSrcRefBufList [ref] + OffRef, + SrcRefStep, + pRefRect, + pCurrPointPos, + pMESpec, + + Lambda, + &BlockCost, + &DstMV, + + x + PartStartX, + y + PartStartY, + BlockWidth, + BlockHeight, + ref, + pRefFrArr, + pMVArr, + &MVPred); + + PartitionCost += BlockCost; + + OffX = (PartStartX + x) >> 2; + OffY = (PartStartY + y) >> 2; + + for (j = 0; j < (BlockHeight >> 2); j++) + { + for (i = 0; i < (BlockWidth >> 2); i++) + { + pMVArr [4 + OffY + j][4 + OffX + i].dx = DstMV.dx; + pMVArr [4 + OffY + j][4 + OffX + i].dy = DstMV.dy; + pMVPredArr [OffY + j][OffX + i].dx = MVPred.dx; + pMVPredArr [OffY + j][OffX + i].dy = MVPred.dy; + } + } + + pRefFrArr [2 + (OffY >> 1)][2 + (OffX >> 1)] = ref; + for (j = 0; j < (BlockHeight >> 3); j++) + { + for (i = 0; i < (BlockWidth >> 3); i++) + { + pRefFrArr [2 + (OffY >> 1) + j][2 + (OffX >> 1) + i] = ref; + } + } + + } + } + + /* + * If PartitionCost is less for this reference frame, motion vectors needs to be backedup + */ + if (PartitionCost <= BestCost) + { + BestCost = PartitionCost; + BestRefFrame = ref; + + for (y = 0; y < (PartHeight/BlockHeight); y++) + { + for (x = 0; x < (PartWidth/BlockWidth); x++) + { + OffX = (PartStartX + x * BlockWidth) >> 2; + OffY = (PartStartY + y * BlockHeight) >> 2; + + BestMV[y][x].dx = pMVArr [4 + OffY][4 + OffX].dx; + BestMV[y][x].dy = pMVArr [4 + OffY][4 + OffX].dy; + BestMVPred[y][x].dx = pMVPredArr [OffY][OffX].dx; + BestMVPred[y][x].dy = pMVPredArr [OffY][OffX].dy; + } + } + } + + } + + /* + * Copy back best reference frame, motion vectors and cost. + */ + for (y = 0; y < (PartHeight/BlockHeight); y++) + { + for (x = 0; x < (PartWidth/BlockWidth); x++) + { + OffX = (PartStartX + x * BlockWidth) >> 2; + OffY = (PartStartY + y * BlockHeight) >> 2; + + for (j = 0; j < (BlockHeight >> 2); j++) + { + for (i = 0; i < (BlockWidth >> 2); i++) + { + pMVArr [4 + OffY + j][4 + OffX + i].dx = BestMV[y][x].dx; + pMVArr [4 + OffY + j][4 + OffX + i].dy = BestMV[y][x].dy; + pMVPredArr [OffY + j][OffX + i].dx = BestMVPred[y][x].dx; + pMVPredArr [OffY + j][OffX + i].dy = BestMVPred[y][x].dy; + } + } + + for (j = 0; j < (BlockHeight >> 3); j++) + { + for (i = 0; i < (BlockWidth >> 3); i++) + { + pRefFrArr [2 + (OffY >> 1) + j][2 + (OffX >> 1) + i] = BestRefFrame; + } + } + } + } + + *pCost = BestCost; + return OMX_Sts_NoErr; + +} + +/** + * Function: armVCM4P10_Intra16x16Estimation + * + * Description: + * Performs MB-level motion estimation for INTER MB type and selects best motion estimation strategy from + * the set of modes supported in baseline profile ISO/IEC 14496-10. + * + * Remarks: + * + * Parameters: + * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock + * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf + * [in] pSrcRecBuf - Pointer to the start of luma component of co-located reconstructed MB + * [in] SrcRecStep - Step size for the pointer pSrcRecBuf + * [in] nMBPosX - Position of MB in the frame w.r.t X axis + * [in] nMBPosY - Position of MB in the frame w.r.t Y axis + * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four + * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right). + * [in] pMBIntra - Array, of dimension four, containing pointers to information associated with four + * adjacent type INTRA MBs (Left, Top, Top-Left, Top-Right). + * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set + * before calling this function + * [in] Lambda - For calculating the cost + * [out] pCost - Pointer to cost for Intra16x16 + * Return Value: + * OMX_Sts_NoErr - No Error + * OMX_Sts_BadArgErr - Bad arguments: + * + */ + +static OMXResult armVCM4P10_Intra16x16Estimation( + const OMX_U8* pSrcCurrBuf, + OMX_S32 SrcCurrStep, + const OMX_U8* pSrcRecBuf, + OMX_S32 SrcRecStep, + const OMXVCM4P2Coordinate *pCurrPointPos, + const OMXVCM4P10MBInfoPtr *pMBInter, + const OMXVCM4P10MBInfoPtr *pMBIntra, + OMXVCM4P10MBInfo *pSrcDstMBCurr, + OMX_U32 *pCost) +{ + OMX_U8 PredBuf [16*16 + 16]; + OMX_U8 *pPred; + OMX_S32 mode; + OMX_S32 Cost; + OMX_S32 availability = 0; + OMXResult Ret; + OMXVCM4P10Intra16x16PredMode IntraMode16x16 [4] = + {OMX_VC_16X16_VERT, OMX_VC_16X16_HOR, + OMX_VC_16X16_DC, OMX_VC_16X16_PLANE}; + OMX_U32 MBPosX = pCurrPointPos->x >> 4; + OMX_U32 MBPosY = pCurrPointPos->y >> 4; + + pPred = armAlignTo16Bytes(PredBuf); + + /* Check for availability of LEFT MB */ + if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0)) + { + availability |= OMX_VC_LEFT; + } + + /* Check for availability of UP MB */ + if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0)) + { + availability |= OMX_VC_UPPER; + } + + /* Check for availability of UP-LEFT MB */ + if ((MBPosX > 0) && (MBPosY > 0) && + (pMBIntra [2] != 0 || pMBInter [2] != 0)) + { + availability |= OMX_VC_UPPER_LEFT; + } + + *pCost = ARM_VCM4P10_MAX_COST; + for (mode = 0; mode < 4; mode++) + { + Ret = omxVCM4P10_PredictIntra_16x16( + pSrcRecBuf - 1, + pSrcRecBuf - SrcRecStep, + pSrcRecBuf - SrcRecStep - 1, + pPred, + SrcRecStep, + 16, + IntraMode16x16 [mode], + availability); + if (Ret == OMX_Sts_NoErr) + { + armVCCOMM_SAD( + pSrcCurrBuf, + SrcCurrStep, + pPred, + 16, + &Cost, + 16, + 16); + if (Cost < *pCost) + { + *pCost = Cost; + pSrcDstMBCurr->Intra16x16PredMode = IntraMode16x16 [mode]; + } + + } + + } + + return OMX_Sts_NoErr; +} + +/** + * Function: armVCM4P10_Intra4x4Estimation + * + * Description: + * Performs MB-level motion estimation for Intra 4x4 MB type and selects + * the best set of modes supported in baseline profile. + * + * Parameters: + * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock + * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf + * [in] pSrcRecBuf - Pointer to the start of luma component of co-located reconstructed MB + * [in] SrcRecStep - Step size for the pointer pSrcRecBuf + * [in] nMBPosX - Position of MB in the frame w.r.t X axis + * [in] nMBPosY - Position of MB in the frame w.r.t Y axis + * [in] pMBIntra - Array, of dimension four, containing pointers to information associated with four + * adjacent type INTRA MBs (Left, Top, Top-Left, Top-Right). + * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set + * before calling this function + * [in] Lambda - For calculating the cost + * [out] pCost - Pointer to cost for Intra4x4 + * Return Value: + * OMX_Sts_NoErr - No Error + * OMX_Sts_BadArgErr - Bad arguments: + * + */ + +static OMXResult armVCM4P10_Intra4x4Estimation( + const OMX_U8* pSrcCurrBuf, + OMX_S32 SrcCurrStep, + const OMX_U8* pSrcRecBuf, + OMX_S32 SrcRecStep, + const OMXVCM4P10MBInfoPtr *pMBIntra, + OMXVCM4P10MBInfo *pSrcDstMBCurr, + OMX_U32 *pCost) +{ + OMX_S32 x, y, Block4x4, Block8x8; + OMX_S32 Cost; + + /* + * PredIntra4x4Mode will store prediction modes of 4x4 blocks. + * Modes for current MB starts at index [1][1]. + * Modes of nighbouring MB's will be as shown below + * A value of ARM_VCM4P10_INVALID_BLOCK for any block in this array means + * that block is not available for prediction. + * + * c3 b0 b1 b2 b3 d0 d1 d2 d3 + * a0 xx xx xx xx - - - - + * a1 xx xx xx xx - - - - + * a2 xx xx xx xx - - - - + * a3 xx xx xx xx - - - - + * + */ + OMX_S32 PredIntra4x4Mode [5][9]; + + /* + * pSrcY stores re-construsted source array of size 3MB X 2MB as below + * + * MB11 MB12 MB13 + * MB21 MB22 MB23 + * + * This array will be used for local reconstruction of 4x4 blocks + * with best prediction mode within an MB + */ + OMX_U8 pSrcY [(16*3)*(16*2)]; + OMX_S32 StepSrcY; + + /* init */ + *pCost = 0; + + for (y = 0; y < 5; y++) + { + for (x = 0; x < 9; x++) + { + /* + * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this + * 4x4 block is not available + */ + PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK; + } + } + + /* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/ + for (x = 0; x < 4; x++) + { + /* Store values of b0, b1, b2, b3 */ + if (pMBIntra[1] != NULL) + { + PredIntra4x4Mode [0][x + 1] = + pMBIntra[1]->pIntra4x4PredMode[3*4 + x]; + } + + /* Store values of d0, d1, d2, d3 */ + if (pMBIntra[3] != NULL) + { + PredIntra4x4Mode [0][x + 5] = + pMBIntra[3]->pIntra4x4PredMode[3*4 + x]; + } + } + + /* Store values of c3 */ + if (pMBIntra[2] != NULL) + { + PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15]; + } + + for (y = 0; y < 4; y++) + { + /* Store values of a0, a1, a2, a3 */ + if (pMBIntra[0] != NULL) + { + PredIntra4x4Mode [y + 1][0] = + pMBIntra[0]->pIntra4x4PredMode[y*4 + 3]; + } + } + + /* + * Update neighbouring Pred mode array which will be used for + * prediction of Intra4x4 modes. + */ + + StepSrcY = 16 * 3; + for (y = 0; y < (16 * 2); y++) + { + for (x = 0; x < (16 * 3); x++) + { + pSrcY [StepSrcY * y + x] = + pSrcRecBuf [SrcRecStep * (y - 16) + x - 16]; + } + } + + /* for each 8x8 block */ + for (Block8x8 = 0; Block8x8 < 4; Block8x8++) + { + /* for each 4x4 block inside 8x8 block */ + for (Block4x4 = 0; Block4x4 < 4; Block4x4++) + { + armVCM4P10_Mode4x4Decision ( + pSrcCurrBuf, + SrcCurrStep, + pSrcDstMBCurr, + Block8x8, + Block4x4, + pSrcY + 16 * StepSrcY + 16, + StepSrcY, + PredIntra4x4Mode, + &Cost); + + *pCost += Cost; + } + } + return OMX_Sts_NoErr; +} + +/** + * Function: armVCM4P10_InterMEMB + * + * Description: + * Performs MB-level motion estimation for INTER MB type and selects best motion estimation strategy from + * the set of modes supported in baseline profile ISO/IEC 14496-10. + * + * Remarks: + * + * Parameters: + * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock + * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf + * [in] pSrcRefBufList - Pointer to the start of luma component of co-located reference MB + * [in] SrcRefStep - Step size for the pointer pSrcRefY + * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin. + * [in] pCurrPointPos Position of the current macroblock in the current plane. + * [in] pMESpec - Motion estimation structure + * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four + * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right). + * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set + * before calling this function + * [in] Lambda - For calculating the cost + * [out] pDstCost - Pointer to cost for Inter MB + * Return Value: + * OMX_Sts_NoErr - No Error + * OMX_Sts_BadArgErr - Bad arguments: + * + */ + +static OMXResult armVCM4P10_InterMEMB( + const OMX_U8 *pSrcCurrBuf, + OMX_S32 SrcCurrStep, + const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], + OMX_S32 SrcRefStep, + const OMXRect *pRefRect, + const OMXVCM4P2Coordinate *pCurrPointPos, + OMX_U32 Lambda, + void *pMESpec, + const OMXVCM4P10MBInfoPtr *pMBInter, + OMXVCM4P10MBInfoPtr pSrcDstMBCurr, + OMX_U32 *pDstCost) +{ + OMX_S32 i, j, x, y, mode; + OMX_U32 Block8x8, XPerMB, YPerMB, Block2x, Block2y; + OMX_S32 PartStartX = 0, PartStartY = 0; + OMX_S32 PartWidth = 8, PartHeight = 8, BlockWidth = 4, BlockHeight = 4; + const OMX_U32 BlkSz [4][2] = {{4,4}, {4,8}, {8,4}}; + const OMX_U32 PartSz [4][2] = {{8,8}, {8,16}, {16,8}, {16,16}}; + const OMXVCM4P10SubMacroblockType + ModeSubMBType4x4 [] = {OMX_VC_SUB_P_4x4, OMX_VC_SUB_P_4x8, + OMX_VC_SUB_P_8x4, OMX_VC_SUB_P_8x8}; + const OMXVCM4P10MacroblockType + ModeMBType [] = {OMX_VC_P_8x8, OMX_VC_P_8x16, OMX_VC_P_16x8, OMX_VC_P_16x16}; + + OMXVCM4P10MEParams *pMBOptions; + /* + * RefFrArr and MVArr will be used for temporary storage of Reference frame index and MVs + * It will store RefIndex and MVs of 6 MBs as shown below + * + * |------|------|------| + * |Tp-Lt |Top |Tp-R | + * | MB | MB | MB | + * |------|------|------| + * |Left | Curr | | + * | MB | MB | | + * |------|------|------| + */ + OMX_S32 RefFrArr [4][6]; + OMXVCMotionVector MVArr [8][12]; + OMXVCMotionVector MVPredArr [4][4]; + + /* + * IndexToLoc will translate pMBInter index into spacial arrangement of MBs + */ + OMX_S32 IndexToLoc [] = {2,1,3,0}; + OMX_U32 part, MaxPart; + OMX_S32 Cost, MotionCost8x8 [4], MBCost, BestCost; + + /* + * Update neighbouring MV array and Ref frame array which will be used for + * prediction of MVs and Ref frames. + */ + + /* Set cost to a high value */ + Cost = BestCost = ARM_VCM4P10_MAX_COST; + + for (y = 0; y < 8; y++) + { + for (x = 0; x < 12; x++) + { + i = 3 * (y >> 2) + (x >> 2); + if ((y < 4 || x < 4) && (pMBInter[IndexToLoc[i]] != NULL)) + { + MVArr [y][x].dx = + pMBInter[IndexToLoc[i]]->pMV0[y % 4][x % 4].dx; + MVArr [y][x].dy = + pMBInter[IndexToLoc[i]]->pMV0[y % 4][x % 4].dy; + } + else + { + MVArr [y][x].dx = 0; + MVArr [y][x].dy = 0; + } + } + } + + for (y = 0; y < 4; y++) + { + for (x = 0; x < 6; x++) + { + i = 3 * (y >> 1) + (x >> 1); + if ((y < 2 || x < 2) && (pMBInter[IndexToLoc[i]] != NULL)) + { + RefFrArr [y][x] = + pMBInter[IndexToLoc[i]]->pRefL0Idx [(y % 2) * 2 + (x % 2)]; + } + else + { + RefFrArr [y][x] = ARM_VCM4P10_INVALID_BLOCK; + } + } + } + + for (y = 0; y < 4; y++) + { + for (x = 0; x < 4; x++) + { + MVPredArr [y][x].dx = 0; + MVPredArr [y][x].dy = 0; + } + } + /* + * Motion Estimation for 8x8 MB Partition + */ + + for (i = 0; i < 4; i++) + { + MotionCost8x8 [i] = 0; + } + + pMBOptions = (OMXVCM4P10MEParams *) pMESpec; + + if (pMBOptions->blockSplitEnable8x8 == 1 && + pMBOptions->blockSplitEnable4x4 == 1) + { + pSrcDstMBCurr->mbType = OMX_VC_P_8x8; + + PartWidth = PartSz [0][0]; + PartHeight = PartSz [0][1]; + + /* For each 8x8 partitions */ + for (Block8x8 = 0; Block8x8 < 4; Block8x8++) + { + PartStartX = (Block8x8 % 2) << 3; + PartStartY = (Block8x8 / 2) << 3; + + Block2x = (Block8x8 & 1) << 1; + Block2y = (Block8x8 >> 1) << 1; + + BestCost = ARM_VCM4P10_MAX_COST; + for (mode = 0; mode < 3; mode++) + { + BlockWidth = BlkSz [mode][0]; + BlockHeight = BlkSz [mode][1]; + + armVCM4P10_PartitionME ( + pSrcCurrBuf, + SrcCurrStep, + pSrcRefBufList, + SrcRefStep, + pRefRect, + pCurrPointPos, + pMESpec, + + PartWidth, + PartHeight, + BlockWidth, + BlockHeight, + PartStartX, + PartStartY, + + MVArr, + RefFrArr, + MVPredArr, + + Lambda, + &Cost); + + if (Cost <= BestCost) + { + /* Update cost */ + BestCost = Cost; + + /* Update MBCurr struct */ + pSrcDstMBCurr->subMBType [Block8x8] = ModeSubMBType4x4 [mode]; + + pSrcDstMBCurr->pRefL0Idx [Block8x8] = RefFrArr [2 + (PartStartY >> 3)][2 + (PartStartX >> 3)]; + + /* Update pMV0 and pMVPred of MBCurr struct */ + for (j = 0; j < 2; j++) + { + for (i = 0; i < 2; i++) + { + pSrcDstMBCurr->pMV0 [Block2y + j][Block2x + i].dx = + MVArr [4 + Block2y + j][4 + Block2x + i].dx; + pSrcDstMBCurr->pMV0 [Block2y + j][Block2x + i].dy = + MVArr [4 + Block2y + j][4 + Block2x + i].dy; + + pSrcDstMBCurr->pMVPred [Block2y + j][Block2x + i].dx = + MVPredArr [Block2y + j][Block2x + i].dx; + pSrcDstMBCurr->pMVPred [Block2y + j][Block2x + i].dy = + MVPredArr [Block2y + j][Block2x + i].dy; + } + } + } + } + + /* Update cost */ + MotionCost8x8 [Block8x8] = BestCost; + } + + /* Cost for mbType OMX_VC_P_8x8 */ + BestCost = 0; + for (i = 0; i < 4; i++) + { + BestCost += MotionCost8x8 [i]; + } + } + else + { + /* Set sub MB type to 8x8 */ + for (i = 0; i < 4; i++) + { + pSrcDstMBCurr->subMBType [i] = OMX_VC_SUB_P_8x8; + } + } + + /* + * Motion Estimation for 8x8, 8x16, 16x8 and 16x16 MB Partition + * If pMBOptions->b8x8BlockSplitEnable is 0, do only 16x16 ME (mode 3) + */ + for (mode = (pMBOptions->blockSplitEnable8x8 == 1 ? 0 : 3); mode < 4; mode++) + { + BlockWidth = PartWidth = PartSz [mode][0]; + BlockHeight = PartHeight = PartSz [mode][1]; + + XPerMB = 16 / PartWidth; + YPerMB = 16 / PartHeight; + MaxPart = XPerMB * YPerMB; + + MBCost = 0; + + /* part size 4, 2, 2 and 1 corresponding to 8x8, 8x16, 16x8 and 16x16 MB */ + for (part = 0; part < MaxPart; part++) + { + PartStartX = (part % XPerMB) * PartWidth; + PartStartY = (part / XPerMB) * PartHeight; + + armVCM4P10_PartitionME ( + pSrcCurrBuf, + SrcCurrStep, + pSrcRefBufList, + SrcRefStep, + pRefRect, + pCurrPointPos, + pMESpec, + + PartWidth, + PartHeight, + BlockWidth, + BlockHeight, + PartStartX, + PartStartY, + + MVArr, + RefFrArr, + MVPredArr, + + Lambda, + &Cost); + + MBCost += Cost; + } + + if (MBCost <= BestCost) + { + /* Update cost */ + BestCost = MBCost; + + /* Update mbType of MBCurr struct */ + pSrcDstMBCurr->mbType = ModeMBType [mode]; + + /* Update pMV0 and pMVPred of MBCurr struct */ + for (j = 0; j < 4; j++) + { + for (i = 0; i < 4; i++) + { + pSrcDstMBCurr->pMV0 [j][i].dx = MVArr [4+j][4+i].dx; + pSrcDstMBCurr->pMV0 [j][i].dy = MVArr [4+j][4+i].dy; + pSrcDstMBCurr->pMVPred [j][i].dx = MVPredArr [j][i].dx; + pSrcDstMBCurr->pMVPred [j][i].dy = MVPredArr [j][i].dy; + } + } + for (j = 0; j < 2; j++) + { + for (i = 0; i < 2; i++) + { + pSrcDstMBCurr->pRefL0Idx [j*2+i] = RefFrArr [2+j][2+i]; + } + } + } + + } + + /* Update Best Cost */ + *pDstCost = BestCost; + + return OMX_Sts_NoErr; +} + +/** + * Function: omxVCM4P10_MotionEstimationMB (6.3.5.3.1) + * + * Description: + * Performs MB-level motion estimation and selects best motion estimation + * strategy from the set of modes supported in baseline profile [ISO14496-10]. + * + * Input Arguments: + * + * pSrcCurrBuf - Pointer to the current position in original picture plane; + * 16-byte alignment required + * pSrcRefBufList - Pointer to an array with 16 entries. Each entry points + * to the top-left corner of the co-located MB in a reference + * picture. The array is filled from low-to-high with valid + * reference frame pointers; the unused high entries should be set + * to NULL. Ordering of the reference frames should follow + * [ISO14496-10] subclause 8.2.4 Decoding Process for Reference + * Picture Lists. The entries must be 16-byte aligned. + * pSrcRecBuf - Pointer to the top-left corner of the co-located MB in the + * reconstructed picture; must be 16-byte aligned. + * SrcCurrStep - Width of the original picture plane in terms of full + * pixels; must be a multiple of 16. + * SrcRefStep - Width of the reference picture plane in terms of full + * pixels; must be a multiple of 16. + * SrcRecStep - Width of the reconstructed picture plane in terms of full + * pixels; must be a multiple of 16. + * pRefRect - Pointer to the valid reference rectangle; relative to the + * image origin. + * pCurrPointPos - Position of the current macroblock in the current plane. + * Lambda - Lagrange factor for computing the cost function + * pMESpec - Pointer to the motion estimation specification structure; must + * have been allocated and initialized prior to calling this + * function. + * pMBInter - Array, of dimension four, containing pointers to information + * associated with four adjacent type INTER MBs (Left, Top, + * Top-Left, Top-Right). Any pointer in the array may be set equal + * to NULL if the corresponding MB doesn t exist or is not of type + * INTER. pMBInter[0] - Pointer to left MB information pMBInter[1] + * - Pointer to top MB information pMBInter[2] - Pointer to + * top-left MB information pMBInter[3] - Pointer to top-right MB + * information + * pMBIntra - Array, of dimension four, containing pointers to information + * associated with four adjacent type INTRA MBs (Left, Top, + * Top-Left, Top-Right). Any pointer in the array may be set equal + * to NULL if the corresponding MB doesn t exist or is not of type + * INTRA. pMBIntra[0] - Pointer to left MB information pMBIntra[1] + * - Pointer to top MB information pMBIntra[2] - Pointer to + * top-left MB information pMBIntra[3] - Pointer to top-right MB + * information + * pSrcDstMBCurr - Pointer to information structure for the current MB. + * The following entries should be set prior to calling the + * function: sliceID - the number of the slice the to which the + * current MB belongs. + * + * Output Arguments: + * + * pDstCost - Pointer to the minimum motion cost for the current MB. + * pDstBlockSAD - Pointer to the array of SADs for each of the sixteen luma + * 4x4 blocks in each MB. The block SADs are in scan order for + * each MB. For implementations that cannot compute the SAD values + * individually, the maximum possible value (0xffff) is returned + * for each of the 16 block SAD entries. + * pSrcDstMBCurr - Pointer to updated information structure for the current + * MB after MB-level motion estimation has been completed. The + * following fields are updated by the ME function. The following + * parameter set quantifies the MB-level ME search results: MbType + * subMBType[4] pMV0[4][4] pMVPred[4][4] pRefL0Idx[4] + * Intra16x16PredMode pIntra4x4PredMode[4][4] + * + * Return Value: + * OMX_Sts_NoErr, if the function runs without error. + * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs: + * - One of more of the following pointers is NULL: pSrcCurrBuf, + * pSrcRefBufList, pSrcRecBuf, pRefRect, pCurrPointPos, pMESpec, + * pMBInter, pMBIntra,pSrcDstMBCurr, pDstCost, pSrcRefBufList[0] + * - SrcRefStep, SrcRecStep are not multiples of 16 + * - iBlockWidth or iBlockHeight are values other than 4, 8, or 16. + * - Any alignment restrictions are violated + * + */ + +OMXResult omxVCM4P10_MotionEstimationMB( + const OMX_U8 *pSrcCurrBuf, + OMX_S32 SrcCurrStep, + const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES], + OMX_S32 SrcRefStep, + const OMX_U8 *pSrcRecBuf, + OMX_S32 SrcRecStep, + const OMXRect *pRefRect, + const OMXVCM4P2Coordinate *pCurrPointPos, + OMX_U32 Lambda, + void *pMESpec, + const OMXVCM4P10MBInfoPtr *pMBInter, + const OMXVCM4P10MBInfoPtr *pMBIntra, + OMXVCM4P10MBInfo *pSrcDstMBCurr, + OMX_INT *pDstCost, + OMX_U16 *pDstBlockSAD) +{ + OMX_U32 Cost, i, IntraFlag = 1; + OMXVCM4P10MEParams *pMEParams; + + /* check for argument error */ + armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pSrcRefBufList == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pSrcRecBuf == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pMESpec == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pMBInter == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pMBIntra == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pSrcDstMBCurr == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(pDstCost == NULL, OMX_Sts_BadArgErr) + armRetArgErrIf(SrcRefStep <= 0 || SrcRefStep & 15, OMX_Sts_BadArgErr) + armRetArgErrIf(SrcRecStep <= 0 || SrcRecStep & 15, OMX_Sts_BadArgErr) + armRetArgErrIf(SrcCurrStep <= 0 || SrcCurrStep & 15, OMX_Sts_BadArgErr) + + armRetArgErrIf(armNot16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr) + armRetArgErrIf(armNot16ByteAligned(pSrcRecBuf), OMX_Sts_BadArgErr) + + for (i = 0; i < ARM_VCM4P10_MAX_FRAMES; i++) + { + armRetArgErrIf(pSrcRefBufList [i] != NULL && + armNot16ByteAligned(pSrcRefBufList [i]), OMX_Sts_BadArgErr) + + /* Check if current MB needs INTER cost calculations */ + if (pSrcRefBufList [i] != NULL && IntraFlag == 1) + { + IntraFlag = 0; + } + } + + *pDstCost = ARM_VCM4P10_MAX_COST; + /* + * Inter cost calculations + */ + + /* check this MB can be Inter */ + if (IntraFlag != 1) + { + armVCM4P10_InterMEMB( + pSrcCurrBuf, + SrcCurrStep, + pSrcRefBufList, + SrcRefStep, + pRefRect, + pCurrPointPos, + Lambda, + pMESpec, + pMBInter, + pSrcDstMBCurr, + &Cost + ); + + *pDstCost = Cost; + } + + pMEParams = (OMXVCM4P10MEParams *)pMESpec; + + if (pMEParams->intraEnable4x4 == 1) + { + /* + * Intra 4x4 cost calculations + */ + armVCM4P10_Intra4x4Estimation( + pSrcCurrBuf, + SrcCurrStep, + pSrcRecBuf, + SrcRecStep, + pMBIntra, + pSrcDstMBCurr, + &Cost + ); + + if (Cost <= *pDstCost) + { + *pDstCost = Cost; + pSrcDstMBCurr->mbType = OMX_VC_INTRA_4x4; + + } + + } + + /* + * Cost for Intra 16x16 mode + */ + + armVCM4P10_Intra16x16Estimation( + pSrcCurrBuf, + SrcCurrStep, + pSrcRecBuf, + SrcRecStep, + pCurrPointPos, + pMBInter, + pMBIntra, + pSrcDstMBCurr, + &Cost + ); + + if (Cost <= *pDstCost) + { + *pDstCost = Cost; + pSrcDstMBCurr->mbType = OMX_VC_INTRA_16x16; + } + + /* + * Update pDstBlockSAD to max value + */ + armVCM4P10_CalculateBlockSAD( pSrcDstMBCurr, + pSrcCurrBuf, + SrcCurrStep, + pSrcRefBufList, + SrcRefStep, + pSrcRecBuf, + SrcRecStep, + pRefRect, + pCurrPointPos, + pMBInter, + pMBIntra, + pDstBlockSAD); + + + return OMX_Sts_NoErr; +} + + +/***************************************************************************** + * END OF FILE + *****************************************************************************/ |