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