Home | History | Annotate | Download | only in src
      1 /**                                                                            x
      2  *
      3  * File Name:  omxVCM4P10_MotionEstimationMB.c
      4  * OpenMAX DL: v1.0.2
      5  * Revision:   9641
      6  * Date:       Thursday, February 7, 2008
      7  *
      8  * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
      9  *
     10  *
     11  * Description:
     12  * This function perform MB level motion estimation
     13  *
     14  */
     15 
     16 #include "omxtypes.h"
     17 #include "armOMX.h"
     18 #include "omxVC.h"
     19 
     20 #include "armCOMM.h"
     21 #include "armVC.h"
     22 
     23 #define  ARM_VCM4P10_MAX_FRAMES     (15)
     24 #define  ARM_VCM4P10_MAX_4x4_SAD		(0xffff)
     25 #define  ARM_VCM4P10_MAX_MODE_VALUE     (0xffffffff)
     26 #define  ARM_VCM4P10_MAX_MODES          (16)
     27 #define  ARM_VCM4P10_MB_BLOCK_SIZE      (16)
     28 #define  ARM_VCM4P10_MEDIAN(a,b,c)      (a>b?a>c?b>c?b:c:a:b>c?a>c?a:c:b)
     29 #define  ARM_VCM4P10_SHIFT_QP           (12)
     30 
     31 #define  ARM_VCM4P10_MVPRED_MEDIAN      (0)
     32 #define  ARM_VCM4P10_MVPRED_L           (1)
     33 #define  ARM_VCM4P10_MVPRED_U           (2)
     34 #define  ARM_VCM4P10_MVPRED_UR          (3)
     35 
     36 #define ARM_VCM4P10_MB_BLOCK_SIZE       (16)
     37 #define ARM_VCM4P10_BLOCK_SIZE          (4)
     38 #define ARM_VCM4P10_MAX_COST            (1 << 30)
     39 #define  ARM_VCM4P10_INVALID_BLOCK      (-2)
     40 
     41 
     42 /**
     43  * Function: armVCM4P10_CalculateBlockSAD
     44  *
     45  * Description:
     46  *    Calculate SAD value for the selected MB encoding mode and update
     47  * pDstBlockSAD parameter. These SAD values are calculated 4x4 blocks at
     48  * a time and in the scan order.
     49  *
     50  * Remarks:
     51  *
     52  * Parameters:
     53  * [in] pSrcMBInfo    -
     54  * [in] pSrcCurrBuf   -
     55  * [in] SrcCurrStep   -
     56  * [in] pSrcRefBufList-
     57  * [in] SrcRefStep    -
     58  * [in] pSrcRecBuf    -
     59  * [in] SrcRecStep    -
     60  * [in] pRefRect      -
     61  * [in] pCurrPointPos -
     62  * [in] Lambda        -
     63  * [in] pMESpec       -
     64  * [in] pMBInter      -
     65  * [in] pMBIntra      -
     66  * [out] pDstBlockSAD - pointer to 16 element array for SAD corresponding to 4x4 blocks
     67  * Return Value:
     68  * None
     69  *
     70  */
     71 
     72 static OMXResult armVCM4P10_CalculateBlockSAD(
     73 	OMXVCM4P10MBInfo *pSrcMBInfo,
     74     const OMX_U8 *pSrcCurrBuf,
     75 	OMX_S32 SrcCurrStep,
     76 	const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES],
     77 	OMX_S32 SrcRefStep,
     78 	const OMX_U8 *pSrcRecBuf,
     79 	OMX_S32 SrcRecStep,
     80 	const OMXRect *pRefRect,
     81 	const OMXVCM4P2Coordinate *pCurrPointPos,
     82 	const OMXVCM4P10MBInfoPtr *pMBInter,
     83 	const OMXVCM4P10MBInfoPtr *pMBIntra,
     84 	OMX_U16 *pDstBlockSAD)
     85 {
     86 	OMX_INT		InvalidSAD = 0;
     87 	OMX_INT		i;
     88 
     89 	OMX_U8		Buffer [16*16 + 15];
     90 	OMX_U8		*pTempDstBuf;
     91 	OMX_S32		TempDstStep;
     92 	OMX_U8		*pTempRefBuf;
     93 	OMX_S32		TempRefStep;
     94 
     95 	/* Temporary buffer to store the predicted mb coefficients */
     96 	pTempDstBuf = armAlignTo16Bytes(Buffer);
     97 	TempDstStep = 16;
     98 
     99 	/* Update pDstBlockSAD if MB is a valid type */
    100 	if (pSrcMBInfo)
    101 	{
    102 	    OMX_U32     Width=0, Height=0, MaxXPart, MaxYPart,MaxSubXPart,MaxSubYPart;
    103 
    104 		/* Depending on type of MB, do prediction and fill temp buffer */
    105 		switch (pSrcMBInfo->mbType)
    106 		{
    107 		case OMX_VC_P_16x16:
    108 				Width = 16;
    109 				Height = 16;
    110 				break;
    111 		case OMX_VC_P_16x8:
    112 				Width = 16;
    113 				Height = 8;
    114 				break;
    115 		case OMX_VC_P_8x16:
    116 				Width = 8;
    117 				Height = 16;
    118 				break;
    119 		case OMX_VC_P_8x8:
    120 				Width = 8;
    121 				Height = 8;
    122 				break;
    123 		case OMX_VC_INTRA_4x4:
    124 			{
    125 				/* Create predicted MB Intra4x4 mode */
    126 				OMX_S32     PredIntra4x4Mode [5][9];
    127 				OMX_S32		x, y, Block8x8, Block4x4, BlockX, BlockY;
    128 				OMX_U8      pSrcYBuff [(16*3)*(16*2)];
    129 				OMX_U8		*pSrcY;
    130 				OMX_S32     StepSrcY;
    131 				OMX_S32		availability;
    132 
    133 				for (y = 0; y < 5; y++)
    134 				{
    135 					for (x = 0; x < 9; x++)
    136 					{
    137 						/*
    138 						 * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this
    139 						 * 4x4 block is not available
    140 						 */
    141 						PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK;
    142 					}
    143 				}
    144 
    145 				/* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/
    146 				for (x = 0; x < 4; x++)
    147 				{
    148 					/* Store values of b0, b1, b2, b3 */
    149 					if (pMBIntra[1] != NULL)
    150 					{
    151 						PredIntra4x4Mode [0][x + 1] =
    152 							pMBIntra[1]->pIntra4x4PredMode[3*4 + x];
    153 					}
    154 
    155 					/* Store values of d0, d1, d2, d3 */
    156 					if (pMBIntra[3] != NULL)
    157 					{
    158 						PredIntra4x4Mode [0][x + 5] =
    159 							pMBIntra[3]->pIntra4x4PredMode[3*4 + x];
    160 					}
    161 				}
    162 
    163 				/* Store values of c3 */
    164 				if (pMBIntra[2] != NULL)
    165 				{
    166 					PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15];
    167 				}
    168 
    169 				for (y = 0; y < 4; y++)
    170 				{
    171 					/* Store values of a0, a1, a2, a3 */
    172 					if (pMBIntra[0] != NULL)
    173 					{
    174 						PredIntra4x4Mode [y + 1][0] =
    175 							pMBIntra[0]->pIntra4x4PredMode[y*4 + 3];
    176 					}
    177 				}
    178 
    179 				/*
    180 				 * Update neighbouring Pred mode array which will be used for
    181 				 * prediction of Intra4x4 modes.
    182 				 */
    183 
    184 				pSrcY = pSrcYBuff;
    185 				StepSrcY = 16 * 3;
    186 				for (y = 0; y < (16 * 2); y++)
    187 				{
    188 					for (x = 0; x < (16 * 3); x++)
    189 					{
    190 						pSrcY [StepSrcY * y + x] =
    191 							pSrcRecBuf [SrcRecStep * (y - 16) + x - 16];
    192 					}
    193 				}
    194 
    195 
    196 				/* for each 8x8 block */
    197 				for (Block8x8 = 0; Block8x8 < 4; Block8x8++)
    198 				{
    199 					/* for each 4x4 block inside 8x8 block */
    200 					for (Block4x4 = 0; Block4x4 < 4; Block4x4++)
    201 					{
    202 						/* Get block cordinates from 8x8 block index and 4x4 block index */
    203 						BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1);
    204 						BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1);
    205 
    206 						/* Add offset to point to start of current MB in the array pIntra4x4PredMode */
    207 						x = BlockX + 1;
    208 						y = BlockY + 1;
    209 
    210 						availability = 0;
    211 
    212 						/* Check for availability of LEFT Block */
    213 						if (PredIntra4x4Mode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK)
    214 						{
    215 							availability |= OMX_VC_LEFT;
    216 						}
    217 
    218 						/* Check for availability of UPPER Block */
    219 						if (PredIntra4x4Mode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK)
    220 						{
    221 							availability |= OMX_VC_UPPER;
    222 						}
    223 
    224 						/* Check for availability of UPPER LEFT Block */
    225 						if (PredIntra4x4Mode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK)
    226 						{
    227 							availability |= OMX_VC_UPPER_LEFT;
    228 						}
    229 
    230 						PredIntra4x4Mode [y][x] = pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX];
    231 						x = BlockX * 4;
    232 						y = BlockY * 4;
    233 
    234 						pSrcY = pSrcYBuff + 16 * StepSrcY + 16 + y * StepSrcY + x;
    235 
    236 						omxVCM4P10_PredictIntra_4x4(
    237 							 pSrcY - 1,
    238 							 pSrcY - StepSrcY,
    239 							 pSrcY - StepSrcY - 1,
    240 							 pTempDstBuf + x + y * TempDstStep,
    241 							 StepSrcY,
    242 							 TempDstStep,
    243 							 pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX],
    244 							 availability);
    245 
    246 						for (BlockY=0;BlockY<4;BlockY++)
    247 						{
    248 							for(BlockX=0;BlockX<4;BlockX++)
    249 							{
    250 								pSrcY [BlockY * StepSrcY + BlockX] =
    251 									(OMX_U8)(*(pTempDstBuf + x + y * TempDstStep + BlockY * TempDstStep + BlockX));
    252 							}
    253 						}
    254 
    255 					}
    256 				}
    257 				break;
    258 			}
    259 		case OMX_VC_INTRA_16x16:
    260 			{
    261 				OMX_U32     MBPosX = pCurrPointPos->x >> 4;
    262 				OMX_U32     MBPosY = pCurrPointPos->y >> 4;
    263 				OMX_U32		availability = 0;
    264 
    265 				/* Check for availability of LEFT MB */
    266 				if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0))
    267 				{
    268 					availability |= OMX_VC_LEFT;
    269 				}
    270 
    271 				/* Check for availability of UP MB */
    272 				if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0))
    273 				{
    274 					availability |= OMX_VC_UPPER;
    275 				}
    276 
    277 				/* Check for availability of UP-LEFT MB */
    278 				if ((MBPosX > 0) && (MBPosY > 0) &&
    279 					(pMBIntra [2] != 0 || pMBInter [2] != 0))
    280 				{
    281 					availability |= OMX_VC_UPPER_LEFT;
    282 				}
    283 
    284 				omxVCM4P10_PredictIntra_16x16(
    285 						pSrcRecBuf - 1,
    286 						pSrcRecBuf - SrcRecStep,
    287 						pSrcRecBuf - SrcRecStep - 1,
    288 						pTempDstBuf,
    289 						SrcRecStep,
    290 						TempDstStep,
    291 						pSrcMBInfo->Intra16x16PredMode,
    292 						availability);
    293 
    294 				break;
    295 			}
    296 
    297 		case OMX_VC_INTER_SKIP:
    298 		case OMX_VC_PREF0_8x8:
    299 		case OMX_VC_INTRA_PCM:
    300 		default:
    301 			/* These cases will update pDstBlockSAD with MAX value */
    302 			InvalidSAD = 1;
    303 			break;
    304 		}
    305 
    306 		/* INTER MB */
    307 		if ((pSrcMBInfo->mbType == OMX_VC_P_16x16) ||
    308 			(pSrcMBInfo->mbType == OMX_VC_P_8x16) ||
    309 			(pSrcMBInfo->mbType == OMX_VC_P_16x8) ||
    310 			(pSrcMBInfo->mbType == OMX_VC_P_8x8))
    311 		{
    312         	const OMX_U8		*pTempSrcBuf;
    313         	OMX_S32		TempSrcStep;
    314         	OMX_S32		mvx,mvy;
    315         	OMX_U32		PartX, PartY, SubPartX, SubPartY;
    316 
    317 			TempSrcStep = SrcRefStep;
    318 
    319 			MaxXPart = 16/Width;
    320 			MaxYPart = 16/Height;
    321 
    322 
    323 			for (PartY = 0; PartY < MaxYPart; PartY++)
    324 			{
    325 				for (PartX = 0; PartX < MaxXPart; PartX++)
    326 				{
    327 
    328 					pTempSrcBuf = pSrcRefBufList[pSrcMBInfo->pRefL0Idx[PartY * 2 + PartX]];
    329 
    330 					if (MaxXPart == 2 && MaxYPart == 2)
    331 					{
    332         				switch (pSrcMBInfo->subMBType[PartY*2+PartX])
    333         				{
    334         				    case OMX_VC_SUB_P_8x8:
    335 								Width = 8;
    336 								Height = 8;
    337             				    break;
    338         				    case OMX_VC_SUB_P_8x4:
    339 								Width = 8;
    340 								Height = 4;
    341             				    break;
    342         				    case OMX_VC_SUB_P_4x8:
    343 								Width = 4;
    344 								Height = 8;
    345             				    break;
    346         				    case OMX_VC_SUB_P_4x4:
    347 								Width = 4;
    348 								Height = 4;
    349             				    break;
    350         				    default:
    351 								/* Default */
    352 								Width = 4;
    353 								Height = 4;
    354         				    break;
    355         				}
    356 
    357     				    MaxSubXPart = 8/Width;
    358     				    MaxSubYPart = 8/Height;
    359 
    360 						for (SubPartY = 0; SubPartY < MaxSubYPart; SubPartY++)
    361 						{
    362 							for (SubPartX = 0; SubPartX < MaxSubXPart; SubPartX++)
    363 							{
    364 								mvx = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dx;
    365 								mvy = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dy;
    366 								armVCM4P10_Interpolate_Luma(
    367 									pTempSrcBuf + (8*PartX + 4*SubPartX + (mvx/4)) + (8*PartY + 4*SubPartY + (mvy/4)) * TempSrcStep,
    368 									TempSrcStep,
    369 									pTempDstBuf + (8*PartX + 4*SubPartX) + (8*PartY + 4*SubPartY) * TempDstStep,
    370 									TempDstStep,
    371 									Width,
    372 									Height,
    373 									mvx & 3,
    374 									mvy & 3
    375 									);
    376 							}
    377 						}
    378 					}
    379 					else
    380 					{
    381 
    382 						mvx = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dx;
    383 						mvy = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dy;
    384 						armVCM4P10_Interpolate_Luma(
    385 							pTempSrcBuf + (8*PartX + (mvx/4)) + (8*PartY + (mvy/4)) * TempSrcStep,
    386 							TempSrcStep,
    387 							pTempDstBuf + (8*PartX) + (8*PartY) * TempDstStep,
    388 							TempDstStep,
    389 							Width,
    390 							Height,
    391 							mvx & 3,
    392 							mvy & 3
    393 							);
    394 
    395 					}
    396 				}
    397 			}
    398 		}
    399 	}
    400 	else
    401 	{
    402 		InvalidSAD = 1;
    403 	}
    404 
    405 	/* Calculate SAD from predicted buffer */
    406 	if (!InvalidSAD)
    407 	{
    408 	    OMX_U32     x8x8, y8x8, x4x4, y4x4, Block8x8, Block4x4;
    409 	    OMX_S32     SAD;
    410 
    411 		pTempRefBuf = pTempDstBuf;
    412 		TempRefStep = 16;
    413 
    414 		/* SAD for each 4x4 block in scan order */
    415 		for (Block8x8 = 0; Block8x8 < 4; Block8x8++)
    416 		{
    417 			x8x8 = 8*(Block8x8 & 1);
    418 			y8x8 = 8*(Block8x8 >> 1);
    419 			for (Block4x4 = 0; Block4x4 < 4; Block4x4++)
    420 			{
    421 				x4x4 = 4*(Block4x4 & 1);
    422 				y4x4 = 4*(Block4x4 >> 1);
    423 
    424 				armVCCOMM_SAD(
    425 					pSrcCurrBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * SrcCurrStep,
    426 					SrcCurrStep,
    427 					pTempRefBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * TempRefStep,
    428 					TempRefStep,
    429     				&SAD,
    430     				4, /* Height */
    431     				4); /* Width */
    432                 *(pDstBlockSAD + 4 * Block8x8 + Block4x4) = (SAD < 0x7fff) ? (OMX_U16) SAD : ARM_VCM4P10_MAX_MODE_VALUE;
    433  			}
    434 		}
    435 	}
    436 	else
    437 	{
    438 		/* Fill SADs with max values and return*/
    439 		for (i = 0; i < 16; i++)
    440 		{
    441 			pDstBlockSAD [i] = ARM_VCM4P10_MAX_4x4_SAD;
    442 		}
    443 	}
    444 	return OMX_Sts_NoErr;
    445 }
    446 
    447 
    448 
    449 /**
    450  * Function: armVCM4P10_Mode4x4Decision
    451  *
    452  * Description:
    453  *    Intra 4x4 Mode decision by calculating cost for all possible modes and
    454  * choosing the best mode
    455  *
    456  * Remarks:
    457  *
    458  * Parameters:
    459  * [in] pSrcCurrBuf    - Pointer to the start of current Macroblock
    460  * [in] SrcCurrStep - Step size of the pointer pSrcCurrBuf
    461  * [in/out] pSrcDstMBCurr - Pointer to the OMXVCM4P10MBInfo which will be updated for
    462  *                    field pIntra4x4PredMode of the current block.
    463  * [in] Block8x8    - Index 8x8 block in which current 4x4 block belongs
    464  * [in] Block4x4    - Index of current 4x4 block
    465  * [in/out] pPredIntra4x4SrcY - Pointer to current block location in buffer
    466  *                    with reconstructed values. This will be modified by this
    467  *                    function with best mode predicted values
    468  * [in] StepPredIntra4x4SrcY  - Step size of the pointer pPredIntra4x4SrcY
    469  * [in] pIntra4x4PredMode     - Array of Intra 4x4 prediction mode for the MB.
    470  *                              Current MB modes starts at [1,1].
    471  * [in] pBestCost   - Cost for the Best Intra 4x4 mode
    472  * Return Value:
    473  * None
    474  *
    475  */
    476 static OMXVoid armVCM4P10_Mode4x4Decision (
    477     const OMX_U8* pSrcCurrBuf,
    478     OMX_S32 SrcCurrStep,
    479     OMXVCM4P10MBInfo *pSrcDstMBCurr,
    480     OMX_S32 Block8x8,
    481     OMX_S32 Block4x4,
    482     OMX_U8  *pPredIntra4x4SrcY,
    483     OMX_S32 StepPredIntra4x4SrcY,
    484     OMX_S32 pIntra4x4PredMode [][9],
    485     OMX_S32 *pBestCost
    486 )
    487 {
    488     OMX_S32     i, j, x, y, BlockX, BlockY, mode;
    489     OMX_S32     Cost, BestCost;
    490     OMX_U8      *pSrcY;
    491     OMX_S32     StepSrcY;
    492     OMX_S32     availability = 0;
    493     OMX_U8      pPredBlock [4*4];
    494     OMXResult   Ret = OMX_Sts_Err;
    495 
    496     /* Get block cordinates from 8x8 block index and 4x4 block index */
    497     BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1);
    498     BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1);
    499 
    500     /* Add offset to point to start of current MB in the array pIntra4x4PredMode */
    501     x = BlockX + 1;
    502     y = BlockY + 1;
    503 
    504     /* Check for availability of LEFT Block */
    505     if (pIntra4x4PredMode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK)
    506     {
    507         availability |= OMX_VC_LEFT;
    508     }
    509 
    510     /* Check for availability of UPPER Block */
    511     if (pIntra4x4PredMode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK)
    512     {
    513         availability |= OMX_VC_UPPER;
    514     }
    515 
    516     /* Check for availability of UPPER LEFT Block */
    517     if (pIntra4x4PredMode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK)
    518     {
    519         availability |= OMX_VC_UPPER_LEFT;
    520     }
    521 
    522     pSrcY = pPredIntra4x4SrcY +
    523             StepPredIntra4x4SrcY * (BlockY << 2) +
    524             (BlockX << 2);
    525 
    526     StepSrcY = StepPredIntra4x4SrcY;
    527 
    528     x = BlockX * 4;
    529     y = BlockY * 4;
    530 
    531     Cost = BestCost = ARM_VCM4P10_MAX_COST;
    532 
    533     /* Go through each mode for minim cost */
    534     for (mode = 0; mode < 9; mode++)
    535     {
    536         Ret = omxVCM4P10_PredictIntra_4x4(
    537              pSrcY - 1,
    538              pSrcY - StepSrcY,
    539              pSrcY - StepSrcY - 1,
    540              pPredBlock,
    541              StepSrcY,
    542              4,
    543              (OMXVCM4P10Intra4x4PredMode) mode,
    544              availability);
    545 
    546         if (Ret == OMX_Sts_NoErr)
    547         {
    548             armVCCOMM_SAD(
    549                 pSrcCurrBuf + (y * SrcCurrStep) + x,
    550                 SrcCurrStep,
    551                 pPredBlock,
    552                 4,
    553                 &Cost,
    554                 4,
    555                 4);
    556 
    557             if (Cost < BestCost)
    558             {
    559                 BestCost = Cost;
    560 
    561                 pIntra4x4PredMode [BlockY + 1][BlockX + 1] =
    562                     (OMXVCM4P10Intra4x4PredMode) mode;
    563                 pSrcDstMBCurr->pIntra4x4PredMode [BlockY * 4 + BlockX] =
    564                     (OMXVCM4P10Intra4x4PredMode) mode;
    565 
    566                 for (j = 0; j < 4; j++)
    567                 {
    568                     for (i = 0; i < 4; i++)
    569                     {
    570                         pSrcY [StepSrcY * j + i] = pPredBlock [4 * j + i];
    571                     }
    572                 }
    573             }
    574         }
    575     }
    576 
    577     *pBestCost = BestCost;
    578     return;
    579 }
    580 
    581 /**
    582  * Function: armVCM4P10_SetMotionVectorPredictor
    583  *
    584  * Description:
    585  *    This function will do the MV Prediction for Inter MBs
    586  *
    587  * Parameters:
    588  * [in] BlockStartX - Start X index in integer pels in current Block
    589  * [in] BlockStartY - Start Y index in integer pels in current Block
    590  * [in] BlockSizeX  - Width of current block
    591  * [in] BlockSizeY  - Height of current block
    592  * [in] RefFrame    - Index of the reference frame for prediction
    593  * [in] pRefFrArr   - Pointer to Ref array storing neighbouring MVs for MV prediction
    594  * [in] pMVArr      - Pointer to MV array storing neighbouring MVs for MV prediction
    595  * [out] pMVPred    - Pointer to predicted MVs
    596  * Remarks:
    597  *
    598  * Return Value:
    599  * None
    600  *
    601  */
    602 static OMXVoid armVCM4P10_SetMotionVectorPredictor(
    603     OMX_U32 BlockStartX,
    604     OMX_U32 BlockStartY,
    605     OMX_U32 BlockSizex,
    606     OMX_U32 BlockSizey,
    607     OMX_S32 RefFrame,
    608     OMX_S32 pRefFrArr[][6],
    609     OMXVCMotionVector pMVArr[][12],
    610     OMXVCMotionVector *pMVPred
    611 )
    612 {
    613     OMX_S32     RFrameL;       /* Left */
    614     OMX_S32     RFrameU;       /* Up */
    615     OMX_S32     RFrameUR;      /* Up-Right */
    616 
    617     OMX_S32     BlockX, BlockY, BlockXFr, BlockYFr, MVPredType;
    618     OMX_S32     BlockXPlusOff, BlockXPlusOffFr, BlockXMin1Fr, BlockYMin1Fr;
    619 
    620     BlockX = 4 + (BlockStartX >> 2);
    621     BlockY = 4 + (BlockStartY >> 2);
    622     BlockXPlusOff = BlockX + (BlockSizex >> 2);
    623 
    624     BlockXFr = BlockX >> 1;
    625     BlockYFr = BlockY >> 1;
    626     BlockXMin1Fr = (BlockX - 1) >> 1;
    627     BlockYMin1Fr = (BlockY - 1) >> 1;
    628     BlockXPlusOffFr = BlockXPlusOff >> 1;
    629 
    630     MVPredType = ARM_VCM4P10_MVPRED_MEDIAN;
    631 
    632     RFrameL = pRefFrArr [BlockYFr][BlockXMin1Fr];
    633     RFrameU = pRefFrArr [BlockYMin1Fr][BlockXFr];
    634     RFrameUR = pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr];
    635 
    636     if (RFrameUR == ARM_VCM4P10_INVALID_BLOCK)
    637     {
    638         RFrameUR = pRefFrArr [BlockYMin1Fr][BlockXMin1Fr];
    639     }
    640 
    641     /*
    642      * Prediction if only one of the neighbors uses the reference frame
    643      * we are checking
    644      */
    645 
    646     if (RFrameL == RefFrame && RFrameU != RefFrame && RFrameUR != RefFrame)
    647     {
    648         MVPredType = ARM_VCM4P10_MVPRED_L;
    649     }
    650     else if(RFrameL != RefFrame && RFrameU == RefFrame && RFrameUR != RefFrame)
    651     {
    652         MVPredType = ARM_VCM4P10_MVPRED_U;
    653     }
    654     else if(RFrameL != RefFrame && RFrameU != RefFrame && RFrameUR == RefFrame)
    655     {
    656         MVPredType = ARM_VCM4P10_MVPRED_UR;
    657     }
    658 
    659     /* Directional predictions  */
    660     else if(BlockSizex == 8 && BlockSizey == 16)
    661     {
    662         if(BlockStartX == 0)
    663         {
    664             if(RFrameL == RefFrame)
    665             {
    666                 MVPredType = ARM_VCM4P10_MVPRED_L;
    667             }
    668         }
    669         else
    670         {
    671             if (RFrameUR == RefFrame)
    672             {
    673                 MVPredType = ARM_VCM4P10_MVPRED_UR;
    674             }
    675         }
    676     }
    677     else if(BlockSizex == 16 && BlockSizey == 8)
    678     {
    679         if(BlockStartY == 0)
    680         {
    681             if(RFrameU == RefFrame)
    682             {
    683                 MVPredType = ARM_VCM4P10_MVPRED_U;
    684             }
    685         }
    686         else
    687         {
    688             if(RFrameL == RefFrame)
    689             {
    690                 MVPredType = ARM_VCM4P10_MVPRED_L;
    691             }
    692         }
    693     }
    694 
    695     switch (MVPredType)
    696     {
    697     case ARM_VCM4P10_MVPRED_MEDIAN:
    698         if (!(pRefFrArr [BlockYMin1Fr][BlockXMin1Fr] == ARM_VCM4P10_INVALID_BLOCK ||
    699               pRefFrArr [BlockYMin1Fr][BlockXFr] == ARM_VCM4P10_INVALID_BLOCK ||
    700               pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr] == ARM_VCM4P10_INVALID_BLOCK))
    701         {
    702             pMVPred->dx = pMVArr [BlockY][BlockX - 1].dx;
    703             pMVPred->dy = pMVArr [BlockY][BlockX - 1].dy;
    704         }
    705         else
    706         {
    707             pMVPred->dx =
    708                 ARM_VCM4P10_MEDIAN(pMVArr [BlockY][BlockX - 1].dx,
    709                 pMVArr [BlockY - 1][BlockX].dx,
    710                 pMVArr [BlockY - 1][BlockXPlusOff].dx);
    711             pMVPred->dy =
    712                 ARM_VCM4P10_MEDIAN(pMVArr [BlockY][BlockX - 1].dy,
    713                 pMVArr [BlockY - 1][BlockX].dy,
    714                 pMVArr [BlockY - 1][BlockXPlusOff].dy);
    715         }
    716         break;
    717 
    718     case ARM_VCM4P10_MVPRED_L:
    719         pMVPred->dx = pMVArr [BlockY][BlockX - 1].dx;
    720         pMVPred->dy = pMVArr [BlockY][BlockX - 1].dy;
    721         break;
    722     case ARM_VCM4P10_MVPRED_U:
    723         pMVPred->dx = pMVArr [BlockY - 1][BlockX].dx;
    724         pMVPred->dy = pMVArr [BlockY - 1][BlockX].dy;
    725         break;
    726     case ARM_VCM4P10_MVPRED_UR:
    727         if (pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr] != ARM_VCM4P10_INVALID_BLOCK)
    728         {
    729             pMVPred->dx = pMVArr [BlockY - 1][BlockXPlusOff].dx;
    730             pMVPred->dy = pMVArr [BlockY - 1][BlockXPlusOff].dy;
    731         }
    732         else
    733         {
    734             pMVPred->dx = pMVArr [BlockY - 1][BlockX - 1].dx;
    735             pMVPred->dy = pMVArr [BlockY - 1][BlockX - 1].dy;
    736         }
    737         break;
    738     default:
    739         break;
    740     }
    741 
    742     return;
    743 }
    744 
    745 /**
    746  * Function: armVCM4P10_BlockMotionSearch
    747  *
    748  * Description:
    749  *    Gets best MV for the current block
    750  *
    751  * Parameters:
    752  * [in] pSrcCurrBuf    - Pointer to the start of luma component of current Macroblock
    753  * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
    754  * [in] pSrcRefY    - Pointer to the start of luma component of co-located reference MB
    755  * [in] nSrcRefStep - Step size for the pointer pSrcRefY
    756  * [in] pRefRect   Pointer to the valid reference rectangle; relative to the image origin.
    757  * [in] pCurrPointPos   Position of the current macroblock in the current plane.
    758  * [in] pMESpec     - Motion estimation structure
    759  * [in] pMBInter    - Array, of dimension four, containing pointers to information associated with four
    760  *                    adjacent type INTER MBs (Left, Top, Top-Left, Top-Right).
    761  * [in] nLamda      - For calculating the cost
    762  * [out] pBestCost  - Minimum cost for encoding current block
    763  * [out] pBestMV    - MV corresponding to best cost
    764  * [in] BlockStartX - Block start X index in integer pels
    765  * [in] BlockStartY - Block start Y index in integer pels
    766  * [in] BlockSizeX  - Width of current block
    767  * [in] BlockSizeY  - Height of current block
    768  * [in] RefFrame    - Index of the reference frame for prediction
    769  * [in] pRefFrArr   - Pointer to reference frame array storing neighbouring MVs for prediction
    770  * [in] pMVArr      - Pointer to MV array storing neighbouring MVs for MV prediction
    771  * [in] pMVPred     - Pointer to MV predicted from neighbour MVs
    772  * Remarks:
    773  *
    774  * Return Value:
    775  * OMXResult
    776  *
    777  */
    778 static OMXResult armVCM4P10_BlockMotionSearch(
    779     const OMX_U8* pSrcCurrBuf,
    780     OMX_S32 SrcCurrStep,
    781     const OMX_U8* pSrcRefY,
    782     OMX_S32 nSrcRefStep,
    783 	const OMXRect *pRefRect,
    784 	const OMXVCM4P2Coordinate *pCurrPointPos,
    785     void* pMESpec,
    786 
    787     OMX_S32 nLamda,
    788     OMX_S32* pBestCost,
    789     OMXVCMotionVector *pBestMV,
    790 
    791     OMX_U32 BlockStartX,
    792     OMX_U32 BlockStartY,
    793     OMX_U32 BlockSizeX,
    794     OMX_U32 BlockSizeY,
    795     OMX_S32 RefFrame,
    796     OMX_S32 pRefFrArr [][6],
    797     OMXVCMotionVector pMVArr [][12],
    798     OMXVCMotionVector *pMVPred
    799    )
    800 {
    801 
    802     OMXVCMotionVector   MVCalculated, MVCandidate;
    803     OMX_S32             Cost;
    804     OMXResult           RetValue;
    805     OMXVCM4P10MEParams  *pMEParams;
    806 	OMXVCM4P2Coordinate CurrBlockPos;
    807 
    808     /* Get Predicted Motion Vectors */
    809     armVCM4P10_SetMotionVectorPredictor (
    810         BlockStartX,
    811         BlockStartY,
    812         BlockSizeX,
    813         BlockSizeY,
    814         RefFrame,
    815         pRefFrArr,
    816         pMVArr,
    817         pMVPred);
    818 
    819     /* Initialize candidate MV */
    820     MVCandidate.dx = 0;
    821     MVCandidate.dy = 0;
    822 
    823     CurrBlockPos.x = pCurrPointPos->x + BlockStartX;
    824     CurrBlockPos.y = pCurrPointPos->y + BlockStartY;
    825 
    826     /* Block Match Integer */
    827     RetValue = omxVCM4P10_BlockMatch_Integer (
    828         pSrcCurrBuf,
    829         SrcCurrStep,
    830         pSrcRefY,
    831         nSrcRefStep,
    832         pRefRect,
    833         &CurrBlockPos,
    834         BlockSizeX,
    835         BlockSizeY,
    836         nLamda,
    837         pMVPred,
    838         &MVCandidate,
    839         &MVCalculated,
    840         &Cost,
    841         pMESpec);
    842 
    843     /* updated BestMV*/
    844     /**pBestCost = Cost;
    845     pBestMV->dx = MVCalculated.dx;
    846     pBestMV->dy = MVCalculated.dy;*/
    847 
    848     pMEParams = (OMXVCM4P10MEParams *) pMESpec;
    849 
    850     /* Block Match Half pel */
    851     if (pMEParams->halfSearchEnable)
    852     {
    853         RetValue = omxVCM4P10_BlockMatch_Half(
    854             pSrcCurrBuf,
    855             SrcCurrStep,
    856             pSrcRefY,
    857             nSrcRefStep,
    858             BlockSizeX,
    859             BlockSizeY,
    860             nLamda,
    861             pMVPred,
    862             &MVCalculated,        /* input/output*/
    863             &Cost);
    864     }
    865 
    866     /* Block Match Quarter pel */
    867     if (pMEParams->quarterSearchEnable)
    868     {
    869         RetValue = omxVCM4P10_BlockMatch_Quarter(
    870             pSrcCurrBuf,
    871             SrcCurrStep,
    872             pSrcRefY,
    873             nSrcRefStep,
    874             BlockSizeX,
    875             BlockSizeY,
    876             nLamda,
    877             pMVPred,
    878             &MVCalculated,
    879             &Cost);
    880     }
    881 
    882     /* updated Best Cost and Best MV */
    883     *pBestCost = Cost;
    884     pBestMV->dx = MVCalculated.dx;
    885     pBestMV->dy = MVCalculated.dy;
    886 
    887     /*
    888      * Skip MB cost calculations of 16x16 inter mode
    889      */
    890     return RetValue;
    891 }
    892 
    893 /**
    894  * Function: armVCM4P10_PartitionME
    895  *
    896  * Description:
    897  *    Gets best cost for the current partition
    898  *
    899  * Parameters:
    900  * [in] pSrcCurrBuf    - Pointer to the start of luma component of current Macroblock
    901  * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
    902  * [in] pSrcRefBufList    - Pointer to List of ref buffer of co-located reference MB
    903  * [in] nSrcRefStep - Step size for the pointer pSrcRefY
    904  * [in] pRefRect   Pointer to the valid reference rectangle; relative to the image origin.
    905  * [in] pCurrPointPos   Position of the current macroblock in the current plane.
    906  * [in] pMESpec     - Motion estimation structure
    907  * [in] PartWidth   - Width of current partition
    908  * [in] PartHeight  - Height of current partition
    909  * [in] BlockWidth  - Width of current block
    910  * [in] BlockHeight - Height of current block
    911  * [in] PartStartX  - Partition start X index in integer pels
    912  * [in] PartStartY  - Partition start Y index in integer pels
    913  * [in] pMVArr      - Pointer to MV array storing neighbouring MVs for MV prediction
    914  * [in] pRefFrArr   - Pointer to reference frame array storing neighbouring MVs for prediction
    915  * [in] Lambda      - For calculating the cost
    916  * [out] pCost      - Pointer to cost for Inter MB
    917  *
    918  * Return Value:
    919  * OMXResult
    920  *
    921  */
    922 static OMXResult armVCM4P10_PartitionME (
    923     const OMX_U8* pSrcCurrBuf,
    924     OMX_S32 SrcCurrStep,
    925 	const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES],
    926 	OMX_S32 SrcRefStep,
    927 	const OMXRect *pRefRect,
    928 	const OMXVCM4P2Coordinate *pCurrPointPos,
    929     void* pMESpec,
    930 
    931     OMX_S32 PartWidth,
    932     OMX_S32 PartHeight,
    933     OMX_S32 BlockWidth,
    934     OMX_S32 BlockHeight,
    935     OMX_S32 PartStartX,
    936     OMX_S32 PartStartY,
    937 
    938     OMXVCMotionVector pMVArr [][12],
    939     OMX_S32 pRefFrArr [][6],
    940     OMXVCMotionVector pMVPredArr [][4],
    941 
    942     OMX_S32 Lambda,
    943     OMX_S32 *pCost
    944 )
    945 {
    946     OMX_U32     x, y, i, j, ref, OffX, OffY, OffSrc, OffRef;
    947     OMX_S32     BlockCost, PartitionCost, BestCost;
    948     OMX_S32     BestRefFrame=0;
    949     OMXVCMotionVector   BestMV [4][4];
    950     OMXVCMotionVector   BestMVPred [4][4];
    951     OMXVCMotionVector   MVPred;
    952     OMXVCMotionVector   DstMV;
    953 
    954     BestCost = ARM_VCM4P10_MAX_COST;
    955 
    956     for (ref = 0; ref < ARM_VCM4P10_MAX_FRAMES; ref++)
    957     {
    958         if (pSrcRefBufList [ref] == NULL)
    959         {
    960         	/* No reference frame, continue */
    961         	continue;
    962         }
    963 
    964         PartitionCost = 0;
    965 
    966         for (y = 0; y < PartHeight; y += BlockHeight)
    967         {
    968             for (x = 0; x < PartWidth; x += BlockWidth)
    969             {
    970             	OffSrc = SrcCurrStep * (PartStartY + y) + PartStartX + x;
    971             	OffRef = SrcRefStep * (PartStartY + y) + PartStartX + x;
    972                 armVCM4P10_BlockMotionSearch (
    973                     pSrcCurrBuf + OffSrc,
    974                     SrcCurrStep,
    975                     pSrcRefBufList [ref] + OffRef,
    976                     SrcRefStep,
    977                     pRefRect,
    978                     pCurrPointPos,
    979                     pMESpec,
    980 
    981                     Lambda,
    982                     &BlockCost,
    983                     &DstMV,
    984 
    985                     x + PartStartX,
    986                     y + PartStartY,
    987                     BlockWidth,
    988                     BlockHeight,
    989                     ref,
    990                     pRefFrArr,
    991                     pMVArr,
    992                     &MVPred);
    993 
    994                 PartitionCost += BlockCost;
    995 
    996 				OffX = (PartStartX + x) >> 2;
    997 				OffY = (PartStartY + y) >> 2;
    998 
    999 	            for (j = 0; j < (BlockHeight >> 2); j++)
   1000 	            {
   1001 	                for (i = 0; i < (BlockWidth >> 2); i++)
   1002 	                {
   1003 	                    pMVArr [4 + OffY + j][4 + OffX + i].dx = DstMV.dx;
   1004 	                    pMVArr [4 + OffY + j][4 + OffX + i].dy = DstMV.dy;
   1005 	                    pMVPredArr [OffY + j][OffX + i].dx = MVPred.dx;
   1006 	                    pMVPredArr [OffY + j][OffX + i].dy = MVPred.dy;
   1007 	                }
   1008 	            }
   1009 
   1010 				pRefFrArr [2 + (OffY >> 1)][2 + (OffX >> 1)] = ref;
   1011 	            for (j = 0; j < (BlockHeight >> 3); j++)
   1012 	            {
   1013 	                for (i = 0; i < (BlockWidth >> 3); i++)
   1014 	                {
   1015 			            pRefFrArr [2 + (OffY >> 1) + j][2 + (OffX >> 1) + i] = ref;
   1016 	                }
   1017 	            }
   1018 
   1019             }
   1020         }
   1021 
   1022 		/*
   1023 		 * If PartitionCost is less for this reference frame, motion vectors needs to be backedup
   1024 		 */
   1025         if (PartitionCost <= BestCost)
   1026         {
   1027             BestCost = PartitionCost;
   1028             BestRefFrame = ref;
   1029 
   1030             for (y = 0; y < (PartHeight/BlockHeight); y++)
   1031             {
   1032                 for (x = 0; x < (PartWidth/BlockWidth); x++)
   1033                 {
   1034 					OffX = (PartStartX + x * BlockWidth) >> 2;
   1035 					OffY = (PartStartY + y * BlockHeight) >> 2;
   1036 
   1037                     BestMV[y][x].dx = pMVArr [4 + OffY][4 + OffX].dx;
   1038                     BestMV[y][x].dy = pMVArr [4 + OffY][4 + OffX].dy;
   1039                     BestMVPred[y][x].dx = pMVPredArr [OffY][OffX].dx;
   1040                     BestMVPred[y][x].dy = pMVPredArr [OffY][OffX].dy;
   1041                 }
   1042             }
   1043         }
   1044 
   1045     }
   1046 
   1047 	/*
   1048 	 * Copy back best reference frame, motion vectors and cost.
   1049 	 */
   1050     for (y = 0; y < (PartHeight/BlockHeight); y++)
   1051     {
   1052         for (x = 0; x < (PartWidth/BlockWidth); x++)
   1053         {
   1054 			OffX = (PartStartX + x * BlockWidth) >> 2;
   1055 			OffY = (PartStartY + y * BlockHeight) >> 2;
   1056 
   1057             for (j = 0; j < (BlockHeight >> 2); j++)
   1058             {
   1059                 for (i = 0; i < (BlockWidth >> 2); i++)
   1060                 {
   1061                     pMVArr [4 + OffY + j][4 + OffX + i].dx = BestMV[y][x].dx;
   1062                     pMVArr [4 + OffY + j][4 + OffX + i].dy = BestMV[y][x].dy;
   1063                     pMVPredArr [OffY + j][OffX + i].dx = BestMVPred[y][x].dx;
   1064                     pMVPredArr [OffY + j][OffX + i].dy = BestMVPred[y][x].dy;
   1065                 }
   1066             }
   1067 
   1068             for (j = 0; j < (BlockHeight >> 3); j++)
   1069             {
   1070                 for (i = 0; i < (BlockWidth >> 3); i++)
   1071                 {
   1072 		            pRefFrArr [2 + (OffY >> 1) + j][2 + (OffX >> 1) + i] = BestRefFrame;
   1073                 }
   1074             }
   1075         }
   1076     }
   1077 
   1078 	*pCost = BestCost;
   1079     return OMX_Sts_NoErr;
   1080 
   1081 }
   1082 
   1083 /**
   1084  * Function: armVCM4P10_Intra16x16Estimation
   1085  *
   1086  * Description:
   1087  * Performs MB-level motion estimation for INTER MB type and selects best motion estimation strategy from
   1088  * the set of modes supported in baseline profile ISO/IEC 14496-10.
   1089  *
   1090  * Remarks:
   1091  *
   1092  * Parameters:
   1093  * [in] pSrcCurrBuf    - Pointer to the start of luma component of current Macroblock
   1094  * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
   1095  * [in] pSrcRecBuf    - Pointer to the start of luma component of co-located reconstructed MB
   1096  * [in] SrcRecStep - Step size for the pointer pSrcRecBuf
   1097  * [in] nMBPosX     - Position of MB in the frame w.r.t X axis
   1098  * [in] nMBPosY     - Position of MB in the frame w.r.t Y axis
   1099  * [in] pMBInter    - Array, of dimension four, containing pointers to information associated with four
   1100  *                    adjacent type INTER MBs (Left, Top, Top-Left, Top-Right).
   1101  * [in] pMBIntra    - Array, of dimension four, containing pointers to information associated with four
   1102  *                    adjacent type INTRA MBs (Left, Top, Top-Left, Top-Right).
   1103  * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB.  Following member should be set
   1104  *                    before calling this function
   1105  * [in] Lambda      - For calculating the cost
   1106  * [out] pCost      - Pointer to cost for Intra16x16
   1107  * Return Value:
   1108  * OMX_Sts_NoErr - No Error
   1109  * OMX_Sts_BadArgErr - Bad arguments:
   1110  *
   1111  */
   1112 
   1113 static OMXResult armVCM4P10_Intra16x16Estimation(
   1114     const OMX_U8* pSrcCurrBuf,
   1115     OMX_S32 SrcCurrStep,
   1116     const OMX_U8* pSrcRecBuf,
   1117     OMX_S32 SrcRecStep,
   1118 	const OMXVCM4P2Coordinate *pCurrPointPos,
   1119     const OMXVCM4P10MBInfoPtr *pMBInter,
   1120     const OMXVCM4P10MBInfoPtr *pMBIntra,
   1121     OMXVCM4P10MBInfo *pSrcDstMBCurr,
   1122     OMX_U32 *pCost)
   1123 {
   1124     OMX_U8      PredBuf [16*16 + 16];
   1125     OMX_U8      *pPred;
   1126     OMX_S32     mode;
   1127     OMX_S32     Cost;
   1128     OMX_S32     availability = 0;
   1129     OMXResult   Ret;
   1130     OMXVCM4P10Intra16x16PredMode    IntraMode16x16 [4] =
   1131         {OMX_VC_16X16_VERT, OMX_VC_16X16_HOR,
   1132         OMX_VC_16X16_DC, OMX_VC_16X16_PLANE};
   1133     OMX_U32     MBPosX = pCurrPointPos->x >> 4;
   1134     OMX_U32     MBPosY = pCurrPointPos->y >> 4;
   1135 
   1136 	pPred = armAlignTo16Bytes(PredBuf);
   1137 
   1138 	/* Check for availability of LEFT MB */
   1139     if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0))
   1140     {
   1141         availability |= OMX_VC_LEFT;
   1142     }
   1143 
   1144     /* Check for availability of UP MB */
   1145     if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0))
   1146     {
   1147         availability |= OMX_VC_UPPER;
   1148     }
   1149 
   1150     /* Check for availability of UP-LEFT MB */
   1151     if ((MBPosX > 0) && (MBPosY > 0) &&
   1152         (pMBIntra [2] != 0 || pMBInter [2] != 0))
   1153     {
   1154         availability |= OMX_VC_UPPER_LEFT;
   1155     }
   1156 
   1157     *pCost = ARM_VCM4P10_MAX_COST;
   1158     for (mode = 0; mode < 4; mode++)
   1159     {
   1160         Ret = omxVCM4P10_PredictIntra_16x16(
   1161                 pSrcRecBuf - 1,
   1162                 pSrcRecBuf - SrcRecStep,
   1163                 pSrcRecBuf - SrcRecStep - 1,
   1164                 pPred,
   1165                 SrcRecStep,
   1166                 16,
   1167                 IntraMode16x16 [mode],
   1168                 availability);
   1169         if (Ret == OMX_Sts_NoErr)
   1170         {
   1171             armVCCOMM_SAD(
   1172                 pSrcCurrBuf,
   1173                 SrcCurrStep,
   1174                 pPred,
   1175                 16,
   1176                 &Cost,
   1177                 16,
   1178                 16);
   1179             if (Cost < *pCost)
   1180             {
   1181                 *pCost = Cost;
   1182                 pSrcDstMBCurr->Intra16x16PredMode = IntraMode16x16 [mode];
   1183             }
   1184 
   1185         }
   1186 
   1187     }
   1188 
   1189     return OMX_Sts_NoErr;
   1190 }
   1191 
   1192 /**
   1193  * Function: armVCM4P10_Intra4x4Estimation
   1194  *
   1195  * Description:
   1196  * Performs MB-level motion estimation for Intra 4x4 MB type and selects
   1197  * the best set of modes supported in baseline profile.
   1198  *
   1199  * Parameters:
   1200  * [in] pSrcCurrBuf    - Pointer to the start of luma component of current Macroblock
   1201  * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
   1202  * [in] pSrcRecBuf    - Pointer to the start of luma component of co-located reconstructed MB
   1203  * [in] SrcRecStep - Step size for the pointer pSrcRecBuf
   1204  * [in] nMBPosX     - Position of MB in the frame w.r.t X axis
   1205  * [in] nMBPosY     - Position of MB in the frame w.r.t Y axis
   1206  * [in] pMBIntra    - Array, of dimension four, containing pointers to information associated with four
   1207  *                    adjacent type INTRA MBs (Left, Top, Top-Left, Top-Right).
   1208  * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB.  Following member should be set
   1209  *                    before calling this function
   1210  * [in] Lambda      - For calculating the cost
   1211  * [out] pCost      - Pointer to cost for Intra4x4
   1212  * Return Value:
   1213  * OMX_Sts_NoErr - No Error
   1214  * OMX_Sts_BadArgErr - Bad arguments:
   1215  *
   1216  */
   1217 
   1218 static OMXResult armVCM4P10_Intra4x4Estimation(
   1219     const OMX_U8* pSrcCurrBuf,
   1220     OMX_S32 SrcCurrStep,
   1221     const OMX_U8* pSrcRecBuf,
   1222     OMX_S32 SrcRecStep,
   1223     const OMXVCM4P10MBInfoPtr *pMBIntra,
   1224     OMXVCM4P10MBInfo *pSrcDstMBCurr,
   1225     OMX_U32 *pCost)
   1226 {
   1227     OMX_S32     x, y, Block4x4, Block8x8;
   1228     OMX_S32     Cost;
   1229 
   1230     /*
   1231      * PredIntra4x4Mode will store prediction modes of 4x4 blocks.
   1232      * Modes for current MB starts at index [1][1].
   1233      * Modes of nighbouring MB's will be as shown below
   1234      * A value of ARM_VCM4P10_INVALID_BLOCK for any block in this array means
   1235      * that block is not available for prediction.
   1236      *
   1237      * c3 b0 b1 b2 b3 d0 d1 d2 d3
   1238      * a0 xx xx xx xx -  -  -  -
   1239      * a1 xx xx xx xx -  -  -  -
   1240      * a2 xx xx xx xx -  -  -  -
   1241      * a3 xx xx xx xx -  -  -  -
   1242      *
   1243      */
   1244     OMX_S32     PredIntra4x4Mode [5][9];
   1245 
   1246     /*
   1247      * pSrcY stores re-construsted source array of size 3MB X 2MB as below
   1248      *
   1249      * MB11 MB12 MB13
   1250      * MB21 MB22 MB23
   1251      *
   1252      * This array will be used for local reconstruction of 4x4 blocks
   1253      * with best prediction mode within an MB
   1254      */
   1255     OMX_U8      pSrcY [(16*3)*(16*2)];
   1256     OMX_S32     StepSrcY;
   1257 
   1258     /* init */
   1259     *pCost = 0;
   1260 
   1261     for (y = 0; y < 5; y++)
   1262     {
   1263         for (x = 0; x < 9; x++)
   1264         {
   1265             /*
   1266              * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this
   1267              * 4x4 block is not available
   1268              */
   1269             PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK;
   1270         }
   1271     }
   1272 
   1273     /* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/
   1274     for (x = 0; x < 4; x++)
   1275     {
   1276         /* Store values of b0, b1, b2, b3 */
   1277         if (pMBIntra[1] != NULL)
   1278         {
   1279             PredIntra4x4Mode [0][x + 1] =
   1280                 pMBIntra[1]->pIntra4x4PredMode[3*4 + x];
   1281         }
   1282 
   1283         /* Store values of d0, d1, d2, d3 */
   1284         if (pMBIntra[3] != NULL)
   1285         {
   1286             PredIntra4x4Mode [0][x + 5] =
   1287                 pMBIntra[3]->pIntra4x4PredMode[3*4 + x];
   1288         }
   1289     }
   1290 
   1291     /* Store values of c3 */
   1292     if (pMBIntra[2] != NULL)
   1293     {
   1294         PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15];
   1295     }
   1296 
   1297     for (y = 0; y < 4; y++)
   1298     {
   1299         /* Store values of a0, a1, a2, a3 */
   1300         if (pMBIntra[0] != NULL)
   1301         {
   1302             PredIntra4x4Mode [y + 1][0] =
   1303                 pMBIntra[0]->pIntra4x4PredMode[y*4 + 3];
   1304         }
   1305     }
   1306 
   1307     /*
   1308      * Update neighbouring Pred mode array which will be used for
   1309      * prediction of Intra4x4 modes.
   1310      */
   1311 
   1312     StepSrcY = 16 * 3;
   1313     for (y = 0; y < (16 * 2); y++)
   1314     {
   1315         for (x = 0; x < (16 * 3); x++)
   1316         {
   1317             pSrcY [StepSrcY * y + x] =
   1318                 pSrcRecBuf [SrcRecStep * (y - 16) + x - 16];
   1319         }
   1320     }
   1321 
   1322     /* for each 8x8 block */
   1323     for (Block8x8 = 0; Block8x8 < 4; Block8x8++)
   1324     {
   1325         /* for each 4x4 block inside 8x8 block */
   1326         for (Block4x4 = 0; Block4x4 < 4; Block4x4++)
   1327         {
   1328             armVCM4P10_Mode4x4Decision (
   1329                 pSrcCurrBuf,
   1330                 SrcCurrStep,
   1331                 pSrcDstMBCurr,
   1332                 Block8x8,
   1333                 Block4x4,
   1334                 pSrcY + 16 * StepSrcY + 16,
   1335                 StepSrcY,
   1336                 PredIntra4x4Mode,
   1337                 &Cost);
   1338 
   1339             *pCost += Cost;
   1340         }
   1341     }
   1342     return OMX_Sts_NoErr;
   1343 }
   1344 
   1345 /**
   1346  * Function: armVCM4P10_InterMEMB
   1347  *
   1348  * Description:
   1349  * Performs MB-level motion estimation for INTER MB type and selects best motion estimation strategy from
   1350  * the set of modes supported in baseline profile ISO/IEC 14496-10.
   1351  *
   1352  * Remarks:
   1353  *
   1354  * Parameters:
   1355  * [in] pSrcCurrBuf    - Pointer to the start of luma component of current Macroblock
   1356  * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
   1357  * [in] pSrcRefBufList    - Pointer to the start of luma component of co-located reference MB
   1358  * [in] SrcRefStep - Step size for the pointer pSrcRefY
   1359  * [in] pRefRect   Pointer to the valid reference rectangle; relative to the image origin.
   1360  * [in] pCurrPointPos   Position of the current macroblock in the current plane.
   1361  * [in] pMESpec     - Motion estimation structure
   1362  * [in] pMBInter    - Array, of dimension four, containing pointers to information associated with four
   1363  *                    adjacent type INTER MBs (Left, Top, Top-Left, Top-Right).
   1364  * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB.  Following member should be set
   1365  *                    before calling this function
   1366  * [in] Lambda      - For calculating the cost
   1367  * [out] pDstCost      - Pointer to cost for Inter MB
   1368  * Return Value:
   1369  * OMX_Sts_NoErr - No Error
   1370  * OMX_Sts_BadArgErr - Bad arguments:
   1371  *
   1372  */
   1373 
   1374 static OMXResult armVCM4P10_InterMEMB(
   1375     const OMX_U8 *pSrcCurrBuf,
   1376 	OMX_S32 SrcCurrStep,
   1377 	const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES],
   1378 	OMX_S32 SrcRefStep,
   1379 	const OMXRect *pRefRect,
   1380 	const OMXVCM4P2Coordinate *pCurrPointPos,
   1381 	OMX_U32 Lambda,
   1382 	void *pMESpec,
   1383 	const OMXVCM4P10MBInfoPtr *pMBInter,
   1384     OMXVCM4P10MBInfoPtr pSrcDstMBCurr,
   1385 	OMX_U32 *pDstCost)
   1386 {
   1387     OMX_S32     i, j, x, y, mode;
   1388     OMX_U32     Block8x8, XPerMB, YPerMB, Block2x, Block2y;
   1389     OMX_S32     PartStartX = 0, PartStartY = 0;
   1390     OMX_S32     PartWidth = 8, PartHeight = 8, BlockWidth = 4, BlockHeight = 4;
   1391     const OMX_U32     BlkSz [4][2] = {{4,4}, {4,8}, {8,4}};
   1392     const OMX_U32     PartSz [4][2] = {{8,8}, {8,16}, {16,8}, {16,16}};
   1393     const OMXVCM4P10SubMacroblockType
   1394                 ModeSubMBType4x4 [] = {OMX_VC_SUB_P_4x4, OMX_VC_SUB_P_4x8,
   1395                               OMX_VC_SUB_P_8x4, OMX_VC_SUB_P_8x8};
   1396     const OMXVCM4P10MacroblockType
   1397                 ModeMBType [] = {OMX_VC_P_8x8, OMX_VC_P_8x16, OMX_VC_P_16x8, OMX_VC_P_16x16};
   1398 
   1399     OMXVCM4P10MEParams  *pMBOptions;
   1400     /*
   1401      * RefFrArr and  MVArr will be used for temporary storage of Reference frame index and MVs
   1402      * It will store RefIndex and MVs of 6 MBs as shown below
   1403      *
   1404      *     |------|------|------|
   1405      *     |Tp-Lt |Top   |Tp-R  |
   1406      *     | MB   | MB   | MB   |
   1407      *     |------|------|------|
   1408      *     |Left  | Curr |      |
   1409      *     | MB   | MB   |      |
   1410      *     |------|------|------|
   1411      */
   1412     OMX_S32     RefFrArr [4][6];
   1413     OMXVCMotionVector MVArr [8][12];
   1414     OMXVCMotionVector MVPredArr [4][4];
   1415 
   1416     /*
   1417      * IndexToLoc will translate pMBInter index into spacial arrangement of MBs
   1418      */
   1419     OMX_S32     IndexToLoc [] = {2,1,3,0};
   1420     OMX_U32     part, MaxPart;
   1421     OMX_S32     Cost, MotionCost8x8 [4], MBCost, BestCost;
   1422 
   1423     /*
   1424      * Update neighbouring MV array and Ref frame array which will be used for
   1425      * prediction of MVs and Ref frames.
   1426      */
   1427 
   1428     /* Set cost to a high value */
   1429     Cost = BestCost = ARM_VCM4P10_MAX_COST;
   1430 
   1431     for (y = 0; y < 8; y++)
   1432     {
   1433         for (x = 0; x < 12; x++)
   1434         {
   1435             i = 3 * (y >> 2) + (x >> 2);
   1436             if ((y < 4 || x < 4) && (pMBInter[IndexToLoc[i]] != NULL))
   1437             {
   1438                 MVArr [y][x].dx =
   1439                     pMBInter[IndexToLoc[i]]->pMV0[y % 4][x % 4].dx;
   1440                 MVArr [y][x].dy =
   1441                     pMBInter[IndexToLoc[i]]->pMV0[y % 4][x % 4].dy;
   1442             }
   1443             else
   1444             {
   1445                 MVArr [y][x].dx = 0;
   1446                 MVArr [y][x].dy = 0;
   1447             }
   1448         }
   1449     }
   1450 
   1451     for (y = 0; y < 4; y++)
   1452     {
   1453         for (x = 0; x < 6; x++)
   1454         {
   1455             i = 3 * (y >> 1) + (x >> 1);
   1456             if ((y < 2 || x < 2) && (pMBInter[IndexToLoc[i]] != NULL))
   1457             {
   1458                 RefFrArr [y][x] =
   1459                     pMBInter[IndexToLoc[i]]->pRefL0Idx [(y % 2) * 2 + (x % 2)];
   1460             }
   1461             else
   1462             {
   1463                 RefFrArr [y][x] = ARM_VCM4P10_INVALID_BLOCK;
   1464             }
   1465         }
   1466     }
   1467 
   1468     for (y = 0; y < 4; y++)
   1469     {
   1470         for (x = 0; x < 4; x++)
   1471         {
   1472             MVPredArr [y][x].dx = 0;
   1473             MVPredArr [y][x].dy = 0;
   1474         }
   1475     }
   1476     /*
   1477      * Motion Estimation for 8x8 MB Partition
   1478      */
   1479 
   1480     for (i = 0; i < 4; i++)
   1481     {
   1482         MotionCost8x8 [i] = 0;
   1483     }
   1484 
   1485     pMBOptions = (OMXVCM4P10MEParams *) pMESpec;
   1486 
   1487     if (pMBOptions->blockSplitEnable8x8 == 1 &&
   1488         pMBOptions->blockSplitEnable4x4 == 1)
   1489     {
   1490         pSrcDstMBCurr->mbType = OMX_VC_P_8x8;
   1491 
   1492         PartWidth = PartSz [0][0];
   1493         PartHeight = PartSz [0][1];
   1494 
   1495         /* For each 8x8 partitions */
   1496         for (Block8x8 = 0; Block8x8 < 4; Block8x8++)
   1497         {
   1498             PartStartX = (Block8x8 % 2) << 3;
   1499             PartStartY = (Block8x8 / 2) << 3;
   1500 
   1501             Block2x = (Block8x8 & 1) << 1;
   1502             Block2y = (Block8x8 >> 1) << 1;
   1503 
   1504             BestCost = ARM_VCM4P10_MAX_COST;
   1505             for (mode = 0; mode < 3; mode++)
   1506             {
   1507                 BlockWidth = BlkSz [mode][0];
   1508                 BlockHeight = BlkSz [mode][1];
   1509 
   1510                 armVCM4P10_PartitionME (
   1511                     pSrcCurrBuf,
   1512                     SrcCurrStep,
   1513                     pSrcRefBufList,
   1514                     SrcRefStep,
   1515                     pRefRect,
   1516                     pCurrPointPos,
   1517                     pMESpec,
   1518 
   1519                     PartWidth,
   1520                     PartHeight,
   1521                     BlockWidth,
   1522                     BlockHeight,
   1523                     PartStartX,
   1524                     PartStartY,
   1525 
   1526                     MVArr,
   1527                     RefFrArr,
   1528                     MVPredArr,
   1529 
   1530                     Lambda,
   1531                     &Cost);
   1532 
   1533                 if (Cost <= BestCost)
   1534                 {
   1535                     /* Update cost */
   1536                     BestCost = Cost;
   1537 
   1538                     /* Update MBCurr struct */
   1539                     pSrcDstMBCurr->subMBType [Block8x8] = ModeSubMBType4x4 [mode];
   1540 
   1541                     pSrcDstMBCurr->pRefL0Idx [Block8x8] = RefFrArr [2 + (PartStartY >> 3)][2 + (PartStartX >> 3)];
   1542 
   1543                     /* Update pMV0 and pMVPred of MBCurr struct */
   1544                     for (j = 0; j < 2; j++)
   1545                     {
   1546                         for (i = 0; i < 2; i++)
   1547                         {
   1548                             pSrcDstMBCurr->pMV0 [Block2y + j][Block2x + i].dx =
   1549                                 MVArr [4 + Block2y + j][4 + Block2x + i].dx;
   1550                             pSrcDstMBCurr->pMV0 [Block2y + j][Block2x + i].dy =
   1551                                 MVArr [4 + Block2y + j][4 + Block2x + i].dy;
   1552 
   1553                             pSrcDstMBCurr->pMVPred [Block2y + j][Block2x + i].dx =
   1554                                 MVPredArr [Block2y + j][Block2x + i].dx;
   1555                             pSrcDstMBCurr->pMVPred [Block2y + j][Block2x + i].dy =
   1556                                 MVPredArr [Block2y + j][Block2x + i].dy;
   1557                         }
   1558                     }
   1559                 }
   1560             }
   1561 
   1562             /* Update cost */
   1563             MotionCost8x8 [Block8x8] = BestCost;
   1564         }
   1565 
   1566         /* Cost for mbType OMX_VC_P_8x8 */
   1567         BestCost = 0;
   1568         for (i = 0; i < 4; i++)
   1569         {
   1570             BestCost += MotionCost8x8 [i];
   1571         }
   1572     }
   1573     else
   1574     {
   1575         /* Set sub MB type to 8x8 */
   1576         for (i = 0; i < 4; i++)
   1577         {
   1578             pSrcDstMBCurr->subMBType [i] = OMX_VC_SUB_P_8x8;
   1579         }
   1580     }
   1581 
   1582     /*
   1583      * Motion Estimation for 8x8, 8x16, 16x8 and 16x16 MB Partition
   1584      * If pMBOptions->b8x8BlockSplitEnable is 0, do only 16x16 ME (mode 3)
   1585      */
   1586     for (mode = (pMBOptions->blockSplitEnable8x8 == 1 ? 0 : 3); mode < 4; mode++)
   1587     {
   1588         BlockWidth = PartWidth = PartSz [mode][0];
   1589         BlockHeight = PartHeight = PartSz [mode][1];
   1590 
   1591         XPerMB = 16 / PartWidth;
   1592         YPerMB = 16 / PartHeight;
   1593         MaxPart = XPerMB * YPerMB;
   1594 
   1595         MBCost = 0;
   1596 
   1597         /* part size 4, 2, 2 and 1 corresponding to 8x8, 8x16, 16x8 and 16x16 MB */
   1598         for (part = 0; part < MaxPart; part++)
   1599         {
   1600         	PartStartX = (part % XPerMB) * PartWidth;
   1601         	PartStartY = (part / XPerMB) * PartHeight;
   1602 
   1603             armVCM4P10_PartitionME (
   1604                 pSrcCurrBuf,
   1605                 SrcCurrStep,
   1606                 pSrcRefBufList,
   1607                 SrcRefStep,
   1608                 pRefRect,
   1609                 pCurrPointPos,
   1610                 pMESpec,
   1611 
   1612                 PartWidth,
   1613                 PartHeight,
   1614                 BlockWidth,
   1615                 BlockHeight,
   1616                 PartStartX,
   1617                 PartStartY,
   1618 
   1619                 MVArr,
   1620                 RefFrArr,
   1621                 MVPredArr,
   1622 
   1623                 Lambda,
   1624                 &Cost);
   1625 
   1626                 MBCost += Cost;
   1627         }
   1628 
   1629         if (MBCost <= BestCost)
   1630         {
   1631             /* Update cost */
   1632             BestCost = MBCost;
   1633 
   1634             /* Update mbType of MBCurr struct */
   1635             pSrcDstMBCurr->mbType = ModeMBType [mode];
   1636 
   1637             /* Update pMV0 and pMVPred of MBCurr struct */
   1638             for (j = 0; j < 4; j++)
   1639             {
   1640                 for (i = 0; i < 4; i++)
   1641                 {
   1642                     pSrcDstMBCurr->pMV0 [j][i].dx = MVArr [4+j][4+i].dx;
   1643                     pSrcDstMBCurr->pMV0 [j][i].dy = MVArr [4+j][4+i].dy;
   1644                     pSrcDstMBCurr->pMVPred [j][i].dx = MVPredArr [j][i].dx;
   1645                     pSrcDstMBCurr->pMVPred [j][i].dy = MVPredArr [j][i].dy;
   1646                 }
   1647             }
   1648             for (j = 0; j < 2; j++)
   1649             {
   1650                 for (i = 0; i < 2; i++)
   1651                 {
   1652                     pSrcDstMBCurr->pRefL0Idx [j*2+i] = RefFrArr [2+j][2+i];
   1653                 }
   1654             }
   1655         }
   1656 
   1657     }
   1658 
   1659     /* Update Best Cost */
   1660     *pDstCost = BestCost;
   1661 
   1662     return OMX_Sts_NoErr;
   1663 }
   1664 
   1665 /**
   1666  * Function:  omxVCM4P10_MotionEstimationMB   (6.3.5.3.1)
   1667  *
   1668  * Description:
   1669  * Performs MB-level motion estimation and selects best motion estimation
   1670  * strategy from the set of modes supported in baseline profile [ISO14496-10].
   1671  *
   1672  * Input Arguments:
   1673  *
   1674  *   pSrcCurrBuf - Pointer to the current position in original picture plane;
   1675  *            16-byte alignment required
   1676  *   pSrcRefBufList - Pointer to an array with 16 entries.  Each entry points
   1677  *            to the top-left corner of the co-located MB in a reference
   1678  *            picture.  The array is filled from low-to-high with valid
   1679  *            reference frame pointers; the unused high entries should be set
   1680  *            to NULL.  Ordering of the reference frames should follow
   1681  *            [ISO14496-10] subclause 8.2.4  Decoding Process for Reference
   1682  *            Picture Lists.   The entries must be 16-byte aligned.
   1683  *   pSrcRecBuf - Pointer to the top-left corner of the co-located MB in the
   1684  *            reconstructed picture; must be 16-byte aligned.
   1685  *   SrcCurrStep - Width of the original picture plane in terms of full
   1686  *            pixels; must be a multiple of 16.
   1687  *   SrcRefStep - Width of the reference picture plane in terms of full
   1688  *            pixels; must be a multiple of 16.
   1689  *   SrcRecStep - Width of the reconstructed picture plane in terms of full
   1690  *            pixels; must be a multiple of 16.
   1691  *   pRefRect - Pointer to the valid reference rectangle; relative to the
   1692  *            image origin.
   1693  *   pCurrPointPos - Position of the current macroblock in the current plane.
   1694  *   Lambda - Lagrange factor for computing the cost function
   1695  *   pMESpec - Pointer to the motion estimation specification structure; must
   1696  *            have been allocated and initialized prior to calling this
   1697  *            function.
   1698  *   pMBInter - Array, of dimension four, containing pointers to information
   1699  *            associated with four adjacent type INTER MBs (Left, Top,
   1700  *            Top-Left, Top-Right). Any pointer in the array may be set equal
   1701  *            to NULL if the corresponding MB doesn t exist or is not of type
   1702  *            INTER. pMBInter[0] - Pointer to left MB information pMBInter[1]
   1703  *            - Pointer to top MB information pMBInter[2] - Pointer to
   1704  *            top-left MB information pMBInter[3] - Pointer to top-right MB
   1705  *            information
   1706  *   pMBIntra - Array, of dimension four, containing pointers to information
   1707  *            associated with four adjacent type INTRA MBs (Left, Top,
   1708  *            Top-Left, Top-Right). Any pointer in the array may be set equal
   1709  *            to NULL if the corresponding MB doesn t exist or is not of type
   1710  *            INTRA. pMBIntra[0] - Pointer to left MB information pMBIntra[1]
   1711  *            - Pointer to top MB information pMBIntra[2] - Pointer to
   1712  *            top-left MB information pMBIntra[3] - Pointer to top-right MB
   1713  *            information
   1714  *   pSrcDstMBCurr - Pointer to information structure for the current MB.
   1715  *            The following entries should be set prior to calling the
   1716  *            function:  sliceID - the number of the slice the to which the
   1717  *            current MB belongs.
   1718  *
   1719  * Output Arguments:
   1720  *
   1721  *   pDstCost - Pointer to the minimum motion cost for the current MB.
   1722  *   pDstBlockSAD - Pointer to the array of SADs for each of the sixteen luma
   1723  *            4x4 blocks in each MB.  The block SADs are in scan order for
   1724  *            each MB.  For implementations that cannot compute the SAD values
   1725  *            individually, the maximum possible value (0xffff) is returned
   1726  *            for each of the 16 block SAD entries.
   1727  *   pSrcDstMBCurr - Pointer to updated information structure for the current
   1728  *            MB after MB-level motion estimation has been completed.  The
   1729  *            following fields are updated by the ME function.   The following
   1730  *            parameter set quantifies the MB-level ME search results: MbType
   1731  *            subMBType[4] pMV0[4][4] pMVPred[4][4] pRefL0Idx[4]
   1732  *            Intra16x16PredMode pIntra4x4PredMode[4][4]
   1733  *
   1734  * Return Value:
   1735  *    OMX_Sts_NoErr, if the function runs without error.
   1736  *    OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
   1737  *    -   One of more of the following pointers is NULL: pSrcCurrBuf,
   1738  *           pSrcRefBufList, pSrcRecBuf, pRefRect, pCurrPointPos, pMESpec,
   1739  *           pMBInter, pMBIntra,pSrcDstMBCurr, pDstCost, pSrcRefBufList[0]
   1740  *    -    SrcRefStep, SrcRecStep are not multiples of 16
   1741  *    -    iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
   1742  *    -    Any alignment restrictions are violated
   1743  *
   1744  */
   1745 
   1746 OMXResult omxVCM4P10_MotionEstimationMB(
   1747     const OMX_U8 *pSrcCurrBuf,
   1748 	OMX_S32 SrcCurrStep,
   1749 	const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES],
   1750 	OMX_S32 SrcRefStep,
   1751 	const OMX_U8 *pSrcRecBuf,
   1752 	OMX_S32 SrcRecStep,
   1753 	const OMXRect *pRefRect,
   1754 	const OMXVCM4P2Coordinate *pCurrPointPos,
   1755 	OMX_U32 Lambda,
   1756 	void *pMESpec,
   1757 	const OMXVCM4P10MBInfoPtr *pMBInter,
   1758 	const OMXVCM4P10MBInfoPtr *pMBIntra,
   1759     OMXVCM4P10MBInfo *pSrcDstMBCurr,
   1760 	OMX_INT *pDstCost,
   1761     OMX_U16 *pDstBlockSAD)
   1762 {
   1763     OMX_U32     Cost, i, IntraFlag = 1;
   1764     OMXVCM4P10MEParams  *pMEParams;
   1765 
   1766     /* check for argument error */
   1767     armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr)
   1768     armRetArgErrIf(pSrcRefBufList == NULL, OMX_Sts_BadArgErr)
   1769     armRetArgErrIf(pSrcRecBuf == NULL, OMX_Sts_BadArgErr)
   1770     armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr)
   1771     armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr)
   1772     armRetArgErrIf(pMESpec == NULL, OMX_Sts_BadArgErr)
   1773     armRetArgErrIf(pMBInter == NULL, OMX_Sts_BadArgErr)
   1774     armRetArgErrIf(pMBIntra == NULL, OMX_Sts_BadArgErr)
   1775     armRetArgErrIf(pSrcDstMBCurr == NULL, OMX_Sts_BadArgErr)
   1776     armRetArgErrIf(pDstCost == NULL, OMX_Sts_BadArgErr)
   1777     armRetArgErrIf(SrcRefStep <= 0 || SrcRefStep & 15, OMX_Sts_BadArgErr)
   1778     armRetArgErrIf(SrcRecStep <= 0 || SrcRecStep & 15, OMX_Sts_BadArgErr)
   1779     armRetArgErrIf(SrcCurrStep <= 0 || SrcCurrStep & 15, OMX_Sts_BadArgErr)
   1780 
   1781     armRetArgErrIf(armNot16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr)
   1782     armRetArgErrIf(armNot16ByteAligned(pSrcRecBuf), OMX_Sts_BadArgErr)
   1783 
   1784     for (i = 0; i < ARM_VCM4P10_MAX_FRAMES; i++)
   1785     {
   1786         armRetArgErrIf(pSrcRefBufList [i] != NULL &&
   1787             armNot16ByteAligned(pSrcRefBufList [i]), OMX_Sts_BadArgErr)
   1788 
   1789         /* Check if current MB needs INTER cost calculations */
   1790         if (pSrcRefBufList [i] != NULL && IntraFlag == 1)
   1791         {
   1792             IntraFlag = 0;
   1793         }
   1794     }
   1795 
   1796     *pDstCost = ARM_VCM4P10_MAX_COST;
   1797     /*
   1798      * Inter cost calculations
   1799      */
   1800 
   1801      /* check this MB can be Inter */
   1802     if (IntraFlag != 1)
   1803     {
   1804          armVCM4P10_InterMEMB(
   1805              pSrcCurrBuf,
   1806              SrcCurrStep,
   1807              pSrcRefBufList,
   1808              SrcRefStep,
   1809              pRefRect,
   1810              pCurrPointPos,
   1811              Lambda,
   1812              pMESpec,
   1813              pMBInter,
   1814              pSrcDstMBCurr,
   1815              &Cost
   1816              );
   1817 
   1818         *pDstCost = Cost;
   1819     }
   1820 
   1821     pMEParams = (OMXVCM4P10MEParams *)pMESpec;
   1822 
   1823     if (pMEParams->intraEnable4x4 == 1)
   1824     {
   1825         /*
   1826          * Intra 4x4 cost calculations
   1827          */
   1828         armVCM4P10_Intra4x4Estimation(
   1829             pSrcCurrBuf,
   1830             SrcCurrStep,
   1831             pSrcRecBuf,
   1832             SrcRecStep,
   1833             pMBIntra,
   1834             pSrcDstMBCurr,
   1835             &Cost
   1836             );
   1837 
   1838         if (Cost <= *pDstCost)
   1839         {
   1840             *pDstCost = Cost;
   1841             pSrcDstMBCurr->mbType = OMX_VC_INTRA_4x4;
   1842 
   1843         }
   1844 
   1845     }
   1846 
   1847     /*
   1848      * Cost for Intra 16x16 mode
   1849      */
   1850 
   1851     armVCM4P10_Intra16x16Estimation(
   1852         pSrcCurrBuf,
   1853         SrcCurrStep,
   1854         pSrcRecBuf,
   1855         SrcRecStep,
   1856         pCurrPointPos,
   1857         pMBInter,
   1858         pMBIntra,
   1859         pSrcDstMBCurr,
   1860         &Cost
   1861         );
   1862 
   1863     if (Cost <= *pDstCost)
   1864     {
   1865         *pDstCost = Cost;
   1866         pSrcDstMBCurr->mbType = OMX_VC_INTRA_16x16;
   1867     }
   1868 
   1869     /*
   1870      * Update pDstBlockSAD to max value
   1871      */
   1872 	armVCM4P10_CalculateBlockSAD(	pSrcDstMBCurr,
   1873         pSrcCurrBuf,
   1874     	SrcCurrStep,
   1875     	pSrcRefBufList,
   1876     	SrcRefStep,
   1877     	pSrcRecBuf,
   1878     	SrcRecStep,
   1879     	pRefRect,
   1880     	pCurrPointPos,
   1881     	pMBInter,
   1882     	pMBIntra,
   1883     	pDstBlockSAD);
   1884 
   1885 
   1886 	return OMX_Sts_NoErr;
   1887 }
   1888 
   1889 
   1890 /*****************************************************************************
   1891  *                              END OF FILE
   1892  *****************************************************************************/
   1893