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 /**
     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  */
     73 static 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  */
    153 static 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 
    280 OMXResult 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