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