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/**
18 *
19 * File Name:  omxVCM4P2_MotionEstimationMB.c
20 * OpenMAX DL: v1.0.2
21 * Revision:   9641
22 * Date:       Thursday, February 7, 2008
23 *
24 *
25 *
26 *
27 * Description:
28 * Contains module for motion search 16x16 macroblock
29 *
30 */
31
32#include "omxtypes.h"
33#include "armOMX.h"
34#include "omxVC.h"
35
36#include "armVC.h"
37#include "armCOMM.h"
38
39/**
40 * Function: armVCM4P2_BlockMatch_16x16
41 *
42 * Description:
43 * 16x16 block match wrapper function, calls omxVCM4P2_BlockMatch_Integer_16x16.
44 * If half pel search is enabled it also calls omxVCM4P2_BlockMatch_Half_16x16
45 *
46 * Remarks:
47 *
48 * Parameters:
49 * [in]	pSrcRefBuf	  pointer to the reference Y plane; points to the reference MB that
50 *                    corresponds to the location of the current macroblock in the current
51 *                    plane.
52 * [in]	srcRefStep	  width of the reference plane
53 * [in]	pRefRect	  pointer to the valid rectangular in reference plane. Relative to image origin.
54 *                    It's not limited to the image boundary, but depended on the padding. For example,
55 *                    if you pad 4 pixels outside the image border, then the value for left border
56 *                    can be -4
57 * [in]	pSrcCurrBuf	  pointer to the current macroblock extracted from original plane (linear array,
58 *                    256 entries); must be aligned on an 16-byte boundary.
59 * [in] pCurrPointPos position of the current macroblock in the current plane
60 * [in] pSrcPreMV	  pointer to predicted motion vector; NULL indicates no predicted MV
61 * [in] pSrcPreSAD	  pointer to SAD associated with the predicted MV (referenced by pSrcPreMV); may be set to NULL if unavailable.
62 * [in] pMESpec		  vendor-specific motion estimation specification structure; must have been allocated
63 *                    and then initialized using omxVCM4P2_MEInit prior to calling the block matching
64 *                    function.
65 * [out] pDstMV	      pointer to estimated MV
66 * [out] pDstSAD	  pointer to minimum SAD
67 * *
68 * Return Value:
69 * OMX_Sts_NoErr - no error
70 * OMX_Sts_BadArgErr - bad arguments
71 *
72 */
73static OMXResult armVCM4P2_BlockMatch_16x16(
74     const OMX_U8 *pSrcRefBuf,
75     const OMX_INT srcRefStep,
76     const OMXRect *pRefRect,
77     const OMX_U8 *pSrcCurrBuf,
78     const OMXVCM4P2Coordinate *pCurrPointPos,
79     OMXVCMotionVector *pSrcPreMV,
80     OMX_INT *pSrcPreSAD,
81     void *pMESpec,
82     OMXVCMotionVector *pDstMV,
83     OMX_INT *pDstSAD
84)
85{
86    OMXVCM4P2MEParams *pMEParams = (OMXVCM4P2MEParams *)pMESpec;
87    OMX_INT rndVal;
88
89    rndVal = pMEParams->rndVal;
90
91    omxVCM4P2_BlockMatch_Integer_16x16(
92        pSrcRefBuf,
93        srcRefStep,
94        pRefRect,
95        pSrcCurrBuf,
96        pCurrPointPos,
97        pSrcPreMV,
98        pSrcPreSAD,
99        pMEParams,
100        pDstMV,
101        pDstSAD);
102
103    if (pMEParams->halfPelSearchEnable)
104    {
105        omxVCM4P2_BlockMatch_Half_16x16(
106            pSrcRefBuf,
107            srcRefStep,
108            pRefRect,
109            pSrcCurrBuf,
110            pCurrPointPos,
111            rndVal,
112            pDstMV,
113            pDstSAD);
114    }
115
116    return OMX_Sts_NoErr;
117}
118
119/**
120 * Function: armVCM4P2_BlockMatch_8x8
121 *
122 * Description:
123 * 8x8 block match wrapper function, calls omxVCM4P2_BlockMatch_Integer_8x8.
124 * If half pel search is enabled it also calls omxVCM4P2_BlockMatch_Half_8x8
125 *
126 * Remarks:
127 *
128 * Parameters:
129 * [in]	pSrcRefBuf	  pointer to the reference Y plane; points to the reference MB that
130 *                    corresponds to the location of the current macroblock in the current
131 *                    plane.
132 * [in]	srcRefStep	  width of the reference plane
133 * [in]	pRefRect	  pointer to the valid rectangular in reference plane. Relative to image origin.
134 *                    It's not limited to the image boundary, but depended on the padding. For example,
135 *                    if you pad 4 pixels outside the image border, then the value for left border
136 *                    can be -4
137 * [in]	pSrcCurrBuf	  pointer to the current macroblock extracted from original plane (linear array,
138 *                    256 entries); must be aligned on an 16-byte boundary.
139 * [in] pCurrPointPos position of the current macroblock in the current plane
140 * [in] pSrcPreMV	  pointer to predicted motion vector; NULL indicates no predicted MV
141 * [in] pSrcPreSAD	  pointer to SAD associated with the predicted MV (referenced by pSrcPreMV); may be set to NULL if unavailable.
142 * [in] pMESpec		  vendor-specific motion estimation specification structure; must have been allocated
143 *                    and then initialized using omxVCM4P2_MEInit prior to calling the block matching
144 *                    function.
145 * [out] pDstMV	      pointer to estimated MV
146 * [out] pDstSAD	  pointer to minimum SAD
147 * *
148 * Return Value:
149 * OMX_Sts_NoErr - no error
150 * OMX_Sts_BadArgErr - bad arguments
151 *
152 */
153static OMXResult armVCM4P2_BlockMatch_8x8(
154     const OMX_U8 *pSrcRefBuf,
155     OMX_INT srcRefStep,
156     const OMXRect *pRefRect,
157     const OMX_U8 *pSrcCurrBuf,
158     const OMXVCM4P2Coordinate *pCurrPointPos,
159     OMXVCMotionVector *pSrcPreMV,
160     OMX_INT *pSrcPreSAD,
161     void *pMESpec,
162     OMXVCMotionVector *pSrcDstMV,
163     OMX_INT *pDstSAD
164)
165{
166    OMXVCM4P2MEParams *pMEParams = (OMXVCM4P2MEParams *)pMESpec;
167    OMX_INT rndVal;
168
169    rndVal = pMEParams->rndVal;
170
171    omxVCM4P2_BlockMatch_Integer_8x8(
172        pSrcRefBuf,
173        srcRefStep,
174        pRefRect,
175        pSrcCurrBuf,
176        pCurrPointPos,
177        pSrcPreMV,
178        pSrcPreSAD,
179        pMEParams,
180        pSrcDstMV,
181        pDstSAD);
182
183    if (pMEParams->halfPelSearchEnable)
184    {
185        omxVCM4P2_BlockMatch_Half_8x8(
186            pSrcRefBuf,
187            srcRefStep,
188            pRefRect,
189            pSrcCurrBuf,
190            pCurrPointPos,
191            rndVal,
192            pSrcDstMV,
193            pDstSAD);
194    }
195
196    return OMX_Sts_NoErr;
197}
198
199
200/**
201 * Function:  omxVCM4P2_MotionEstimationMB   (6.2.4.3.1)
202 *
203 * Description:
204 * Performs motion search for a 16x16 macroblock.  Selects best motion search
205 * strategy from among inter-1MV, inter-4MV, and intra modes.  Supports
206 * integer and half pixel resolution.
207 *
208 * Input Arguments:
209 *
210 *   pSrcCurrBuf - pointer to the top-left corner of the current MB in the
211 *            original picture plane; must be aligned on a 16-byte boundary.
212 *            The function does not expect source data outside the region
213 *            bounded by the MB to be available; for example it is not
214 *            necessary for the caller to guarantee the availability of
215 *            pSrcCurrBuf[-SrcCurrStep], i.e., the row of pixels above the MB
216 *            to be processed.
217 *   srcCurrStep - width of the original picture plane, in terms of full
218 *            pixels; must be a multiple of 16.
219 *   pSrcRefBuf - pointer to the reference Y plane; points to the reference
220 *            plane location corresponding to the location of the current
221 *            macroblock in the current plane; must be aligned on a 16-byte
222 *            boundary.
223 *   srcRefStep - width of the reference picture plane, in terms of full
224 *            pixels; must be a multiple of 16.
225 *   pRefRect - reference plane valid region rectangle, specified relative to
226 *            the image origin
227 *   pCurrPointPos - position of the current macroblock in the current plane
228 *   pMESpec - pointer to the vendor-specific motion estimation specification
229 *            structure; must be allocated and then initialized using
230 *            omxVCM4P2_MEInit prior to calling this function.
231 *   pMBInfo - array, of dimension four, containing pointers to information
232 *            associated with four nearby MBs:
233 *            -   pMBInfo[0] - pointer to left MB information
234 *            -   pMBInfo[1] - pointer to top MB information
235 *            -   pMBInfo[2] - pointer to top-left MB information
236 *            -   pMBInfo[3] - pointer to top-right MB information
237 *            Any pointer in the array may be set equal to NULL if the
238 *            corresponding MB doesn't exist.  For each MB, the following structure
239 *            members are used:
240 *            -   mbType - macroblock type, either OMX_VC_INTRA, OMX_VC_INTER, or
241 *                OMX_VC_INTER4V
242 *            -   pMV0[2][2] - estimated motion vectors; represented
243 *                in 1/2 pixel units
244 *            -   sliceID - number of the slice to which the MB belongs
245 *   pSrcDstMBCurr - pointer to information structure for the current MB.
246 *            The following entries should be set prior to calling the
247 *            function: sliceID - the number of the slice the to which the
248 *            current MB belongs.  The structure elements cbpy and cbpc are
249 *            ignored.
250 *
251 * Output Arguments:
252 *
253 *   pSrcDstMBCurr - pointer to updated information structure for the current
254 *            MB after MB-level motion estimation has been completed.  The
255 *            following structure members are updated by the ME function:
256 *              -  mbType - macroblock type: OMX_VC_INTRA, OMX_VC_INTER, or
257 *                 OMX_VC_INTER4V.
258 *              -  pMV0[2][2] - estimated motion vectors; represented in
259 *                 terms of 1/2 pel units.
260 *              -  pMVPred[2][2] - predicted motion vectors; represented
261 *                 in terms of 1/2 pel units.
262 *            The structure members cbpy and cbpc are not updated by the function.
263 *   pDstSAD - pointer to the minimum SAD for INTER1V, or sum of minimum SADs
264 *            for INTER4V
265 *   pDstBlockSAD - pointer to an array of SAD values for each of the four
266 *            8x8 luma blocks in the MB.  The block SADs are in scan order for
267 *            each MB.
268 *
269 * Return Value:
270 *
271 *    OMX_Sts_NoErr - no error
272 *    OMX_Sts_BadArgErr - bad arguments.  Returned if one or more of the
273 *              following conditions is true:
274 *    -    at least one of the following pointers is NULL: pSrcCurrBuf,
275 *              pSrcRefBuf, pRefRect, pCurrPointPos, pMBInter, pMBIntra,
276 *              pSrcDstMBCurr, or pDstSAD.
277 *
278 */
279
280OMXResult omxVCM4P2_MotionEstimationMB (
281    const OMX_U8 *pSrcCurrBuf,
282    OMX_S32 srcCurrStep,
283    const OMX_U8 *pSrcRefBuf,
284    OMX_S32 srcRefStep,
285    const OMXRect*pRefRect,
286    const OMXVCM4P2Coordinate *pCurrPointPos,
287    void *pMESpec,
288    const OMXVCM4P2MBInfoPtr *pMBInfo,
289    OMXVCM4P2MBInfo *pSrcDstMBCurr,
290    OMX_U16 *pDstSAD,
291    OMX_U16 *pDstBlockSAD
292)
293{
294
295    OMX_INT intraSAD, average, count, index, x, y;
296    OMXVCMotionVector dstMV16x16;
297    OMX_INT           dstSAD16x16;
298    OMX_INT           dstSAD8x8;
299    OMXVCM4P2MEParams  *pMEParams;
300	OMXVCM4P2Coordinate TempCurrPointPos;
301    OMXVCM4P2Coordinate *pTempCurrPointPos;
302    OMX_U8 aTempSrcCurrBuf[271];
303    OMX_U8 *pTempSrcCurrBuf;
304    OMX_U8 *pDst;
305    OMX_U8 aDst[71];
306    OMX_S32 dstStep = 8;
307    OMX_INT predictType;
308	OMX_S32 Sad;
309    const OMX_U8 *pTempSrcRefBuf;
310    OMXVCMotionVector* pSrcCandMV1[4];
311    OMXVCMotionVector* pSrcCandMV2[4];
312    OMXVCMotionVector* pSrcCandMV3[4];
313
314    /* Argument error checks */
315    armRetArgErrIf(!armIs16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr);
316	armRetArgErrIf(!armIs16ByteAligned(pSrcRefBuf), OMX_Sts_BadArgErr);
317    armRetArgErrIf(((srcCurrStep % 16) || (srcRefStep % 16)), OMX_Sts_BadArgErr);
318	armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
319	armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
320    armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
321    armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr);
322    armRetArgErrIf(pSrcDstMBCurr == NULL, OMX_Sts_BadArgErr);
323    armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
324
325
326    pTempCurrPointPos = &(TempCurrPointPos);
327    pTempSrcCurrBuf = armAlignTo16Bytes(aTempSrcCurrBuf);
328    pMEParams = (OMXVCM4P2MEParams *)pMESpec;
329    pTempCurrPointPos->x = pCurrPointPos->x;
330    pTempCurrPointPos->y = pCurrPointPos->y;
331    pSrcDstMBCurr->mbType = OMX_VC_INTER;
332
333    /* Preparing a linear buffer for block match */
334    for (y = 0, index = count = 0; y < 16; y++, index += srcCurrStep - 16)
335    {
336        for(x = 0; x < 16; x++, count++, index++)
337        {
338            pTempSrcCurrBuf[count] = pSrcCurrBuf[index];
339        }
340    }
341    for(y = 0, index = 0; y < 2; y++)
342    {
343        for(x = 0; x < 2; x++,index++)
344        {
345            if((pMBInfo[0] != NULL) && (pMBInfo[0]->mbType != OMX_VC_INTRA))
346            {
347               pSrcCandMV1[index] = &(pMBInfo[0]->pMV0[y][x]);
348            }
349            else
350            {
351               pSrcCandMV1[index] = NULL;
352            }
353            if((pMBInfo[1] != NULL) && (pMBInfo[1]->mbType != OMX_VC_INTRA))
354            {
355               pSrcCandMV2[index] = &(pMBInfo[1]->pMV0[y][x]);
356            }
357            else
358            {
359               pSrcCandMV2[index] = NULL;
360            }
361            if((pMBInfo[3] != NULL) && (pMBInfo[3]->mbType != OMX_VC_INTRA))
362            {
363               pSrcCandMV3[index] = &(pMBInfo[3]->pMV0[y][x]);
364            }
365            else
366            {
367               pSrcCandMV3[index] = NULL;
368            }
369        }
370    }
371	/* Calculating SAD at MV(0,0) */
372	armVCCOMM_SAD(pTempSrcCurrBuf,
373					  16,
374					  pSrcRefBuf,
375					  srcRefStep,
376					  &Sad,
377					  16,
378					  16);
379	*pDstSAD = Sad;
380
381    /* Mode decision for NOT_CODED MB */
382	if(*pDstSAD == 0)
383	{
384        pSrcDstMBCurr->pMV0[0][0].dx = 0;
385        pSrcDstMBCurr->pMV0[0][0].dy = 0;
386        *pDstSAD   = 0;
387		return OMX_Sts_NoErr;
388	}
389
390    omxVCM4P2_FindMVpred(
391                    &(pSrcDstMBCurr->pMV0[0][0]),
392                    pSrcCandMV1[0],
393                    pSrcCandMV2[0],
394                    pSrcCandMV3[0],
395                    &(pSrcDstMBCurr->pMVPred[0][0]),
396                    NULL,
397                    0);
398
399    /* Inter 1 MV */
400    armVCM4P2_BlockMatch_16x16(
401        pSrcRefBuf,
402        srcRefStep,
403        pRefRect,
404        pTempSrcCurrBuf,
405        pCurrPointPos,
406        &(pSrcDstMBCurr->pMVPred[0][0]),
407        NULL,
408        pMEParams,
409        &dstMV16x16,
410        &dstSAD16x16);
411
412    /* Initialize all with 1 MV values */
413    pSrcDstMBCurr->pMV0[0][0].dx = dstMV16x16.dx;
414    pSrcDstMBCurr->pMV0[0][0].dy = dstMV16x16.dy;
415    pSrcDstMBCurr->pMV0[0][1].dx = dstMV16x16.dx;
416    pSrcDstMBCurr->pMV0[0][1].dy = dstMV16x16.dy;
417    pSrcDstMBCurr->pMV0[1][0].dx = dstMV16x16.dx;
418    pSrcDstMBCurr->pMV0[1][0].dy = dstMV16x16.dy;
419    pSrcDstMBCurr->pMV0[1][1].dx = dstMV16x16.dx;
420    pSrcDstMBCurr->pMV0[1][1].dy = dstMV16x16.dy;
421
422    *pDstSAD   = dstSAD16x16;
423
424    if (pMEParams->searchEnable8x8)
425    {
426        /* Inter 4MV */
427        armVCM4P2_BlockMatch_8x8 (pSrcRefBuf,
428                                      srcRefStep, pRefRect,
429                                      pTempSrcCurrBuf, pTempCurrPointPos,
430                                      &(pSrcDstMBCurr->pMVPred[0][0]), NULL,
431                                      pMEParams, &(pSrcDstMBCurr->pMV0[0][0]),
432                                      &dstSAD8x8
433                                      );
434        pDstBlockSAD[0] = dstSAD8x8;
435        *pDstSAD = dstSAD8x8;
436        pTempCurrPointPos->x += 8;
437        pSrcRefBuf += 8;
438        omxVCM4P2_FindMVpred(
439                    &(pSrcDstMBCurr->pMV0[0][1]),
440                    pSrcCandMV1[1],
441                    pSrcCandMV2[1],
442                    pSrcCandMV3[1],
443                    &(pSrcDstMBCurr->pMVPred[0][1]),
444                    NULL,
445                    1);
446
447        armVCM4P2_BlockMatch_8x8 (pSrcRefBuf,
448                                      srcRefStep, pRefRect,
449                                      pTempSrcCurrBuf, pTempCurrPointPos,
450                                      &(pSrcDstMBCurr->pMVPred[0][1]), NULL,
451                                      pMEParams, &(pSrcDstMBCurr->pMV0[0][1]),
452                                      &dstSAD8x8
453                                      );
454        pDstBlockSAD[1] = dstSAD8x8;
455        *pDstSAD += dstSAD8x8;
456        pTempCurrPointPos->x -= 8;
457        pTempCurrPointPos->y += 8;
458        pSrcRefBuf += (srcRefStep * 8) - 8;
459
460        omxVCM4P2_FindMVpred(
461                    &(pSrcDstMBCurr->pMV0[1][0]),
462                    pSrcCandMV1[2],
463                    pSrcCandMV2[2],
464                    pSrcCandMV3[2],
465                    &(pSrcDstMBCurr->pMVPred[1][0]),
466                    NULL,
467                    2);
468        armVCM4P2_BlockMatch_8x8 (pSrcRefBuf,
469                                      srcRefStep, pRefRect,
470                                      pTempSrcCurrBuf, pTempCurrPointPos,
471                                      &(pSrcDstMBCurr->pMVPred[1][0]), NULL,
472                                      pMEParams, &(pSrcDstMBCurr->pMV0[1][0]),
473                                      &dstSAD8x8
474                                      );
475        pDstBlockSAD[2] = dstSAD8x8;
476        *pDstSAD += dstSAD8x8;
477        pTempCurrPointPos->x += 8;
478        pSrcRefBuf += 8;
479        omxVCM4P2_FindMVpred(
480                    &(pSrcDstMBCurr->pMV0[1][1]),
481                    pSrcCandMV1[3],
482                    pSrcCandMV2[3],
483                    pSrcCandMV3[3],
484                    &(pSrcDstMBCurr->pMVPred[1][1]),
485                    NULL,
486                    3);
487        armVCM4P2_BlockMatch_8x8 (pSrcRefBuf,
488                                      srcRefStep, pRefRect,
489                                      pTempSrcCurrBuf, pTempCurrPointPos,
490                                      &(pSrcDstMBCurr->pMVPred[1][1]), NULL,
491                                      pMEParams, &(pSrcDstMBCurr->pMV0[1][1]),
492                                      &dstSAD8x8
493                                      );
494        pDstBlockSAD[3] = dstSAD8x8;
495        *pDstSAD += dstSAD8x8;
496
497
498        /* Checking if 4MV is equal to 1MV */
499        if (
500            (pSrcDstMBCurr->pMV0[0][0].dx != dstMV16x16.dx) ||
501            (pSrcDstMBCurr->pMV0[0][0].dy != dstMV16x16.dy) ||
502            (pSrcDstMBCurr->pMV0[0][1].dx != dstMV16x16.dx) ||
503            (pSrcDstMBCurr->pMV0[0][1].dy != dstMV16x16.dy) ||
504            (pSrcDstMBCurr->pMV0[1][0].dx != dstMV16x16.dx) ||
505            (pSrcDstMBCurr->pMV0[1][0].dy != dstMV16x16.dy) ||
506            (pSrcDstMBCurr->pMV0[1][1].dx != dstMV16x16.dx) ||
507            (pSrcDstMBCurr->pMV0[1][1].dy != dstMV16x16.dy)
508           )
509        {
510            /* select the 4 MV */
511            pSrcDstMBCurr->mbType = OMX_VC_INTER4V;
512        }
513    }
514
515    /* finding the error in intra mode */
516    for (count = 0, average = 0; count < 256 ; count++)
517    {
518        average = average + pTempSrcCurrBuf[count];
519    }
520    average = average/256;
521
522	intraSAD = 0;
523
524    /* Intra SAD calculation */
525    for (count = 0; count < 256 ; count++)
526    {
527        intraSAD += armAbs ((pTempSrcCurrBuf[count]) - (average));
528    }
529
530	/* Using the MPEG4 VM formula for intra/inter mode decision
531	   Var < (SAD - 2*NB) where NB = N^2 is the number of pixels
532	   of the macroblock.*/
533
534    if (intraSAD <= (*pDstSAD - 512))
535    {
536        pSrcDstMBCurr->mbType = OMX_VC_INTRA;
537        pSrcDstMBCurr->pMV0[0][0].dx = 0;
538        pSrcDstMBCurr->pMV0[0][0].dy = 0;
539        *pDstSAD   = intraSAD;
540        pDstBlockSAD[0] = 0xFFFF;
541        pDstBlockSAD[1] = 0xFFFF;
542        pDstBlockSAD[2] = 0xFFFF;
543        pDstBlockSAD[3] = 0xFFFF;
544    }
545
546    if(pSrcDstMBCurr->mbType == OMX_VC_INTER)
547    {
548      pTempSrcRefBuf = pSrcRefBuf + (srcRefStep * dstMV16x16.dy) + dstMV16x16.dx;
549
550      if((dstMV16x16.dx & 0x1) && (dstMV16x16.dy & 0x1))
551      {
552        predictType = OMX_VC_HALF_PIXEL_XY;
553      }
554      else if(dstMV16x16.dx & 0x1)
555      {
556        predictType = OMX_VC_HALF_PIXEL_X;
557      }
558      else if(dstMV16x16.dy & 0x1)
559      {
560        predictType = OMX_VC_HALF_PIXEL_Y;
561      }
562      else
563      {
564        predictType = OMX_VC_INTEGER_PIXEL;
565      }
566
567      pDst = armAlignTo8Bytes(&(aDst[0]));
568      /* Calculating Block SAD at MV(dstMV16x16.dx,dstMV16x16.dy) */
569	  /* Block 0 */
570      omxVCM4P2_MCReconBlock(pTempSrcRefBuf,
571	                             srcRefStep,
572                                 NULL,
573                                 pDst,
574                                 dstStep,
575                                 predictType,
576                                 pMEParams->rndVal);
577
578      armVCCOMM_SAD(pTempSrcCurrBuf,
579                        16,
580                        pDst,
581                        dstStep,
582                        &Sad,
583                        8,
584                        8);
585      pDstBlockSAD[0] = Sad;
586
587      /* Block 1 */
588      omxVCM4P2_MCReconBlock(pTempSrcRefBuf + 8,
589                                 srcRefStep,
590                                 NULL,
591                                 pDst,
592                                 dstStep,
593                                 predictType,
594                                 pMEParams->rndVal);
595
596      armVCCOMM_SAD(pTempSrcCurrBuf + 8,
597                        16,
598                        pDst,
599                        dstStep,
600                        &Sad,
601                        8,
602                        8);
603      pDstBlockSAD[1] = Sad;
604
605      /* Block 2 */
606      omxVCM4P2_MCReconBlock(pTempSrcRefBuf + (srcRefStep*8),
607                                 srcRefStep,
608                                 NULL,
609                                 pDst,
610                                 dstStep,
611                                 predictType,
612                                 pMEParams->rndVal);
613
614      armVCCOMM_SAD(pTempSrcCurrBuf + (16*8),
615                        16,
616                        pDst,
617                        dstStep,
618                        &Sad,
619                        8,
620                        8);
621      pDstBlockSAD[2] = Sad;
622
623	  /* Block 3 */
624      omxVCM4P2_MCReconBlock(pTempSrcRefBuf + (srcRefStep*8) + 8,
625                                 srcRefStep,
626                                 NULL,
627                                 pDst,
628                                 dstStep,
629                                 predictType,
630                                 pMEParams->rndVal);
631
632      armVCCOMM_SAD(pTempSrcCurrBuf + (16*8) + 8,
633                        16,
634                        pDst,
635                        dstStep,
636                        &Sad,
637                        8,
638                        8);
639      pDstBlockSAD[3] = Sad;
640    }
641    return OMX_Sts_NoErr;
642}
643
644/* End of file */
645
646