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
87static 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 */
491static 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 */
617static 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 */
793static 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 */
937static 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
1128static 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
1233static 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
1389static 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
1761OMXResult 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