Home | History | Annotate | Download | only in src
      1 /**
      2  *
      3  * File Name:  armVCM4P2_BlockMatch_Half.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 modules for Block matching, a full search algorithm
     14  * is implemented
     15  *
     16  */
     17 
     18 #include "omxtypes.h"
     19 #include "armOMX.h"
     20 #include "omxVC.h"
     21 
     22 #include "armVC.h"
     23 #include "armCOMM.h"
     24 
     25 /**
     26  * Function: armVCM4P2_BlockMatch_Half
     27  *
     28  * Description:
     29  * Performs a 16x16 block match with half-pixel resolution.  Returns the estimated
     30  * motion vector and associated minimum SAD.  This function estimates the half-pixel
     31  * motion vector by interpolating the integer resolution motion vector referenced
     32  * by the input parameter pSrcDstMV, i.e., the initial integer MV is generated
     33  * externally.  The input parameters pSrcRefBuf and pSearchPointRefPos should be
     34  * shifted by the winning MV of 16x16 integer search prior to calling BlockMatch_Half_16x16.
     35  * The function BlockMatch_Integer_16x16 may be used for integer motion estimation.
     36  *
     37  * Remarks:
     38  *
     39  * Parameters:
     40  * [in]	pSrcRefBuf		pointer to the reference Y plane; points to the reference MB
     41  *                    that corresponds to the location of the current macroblock in
     42  *                    the	current plane.
     43  * [in]	refWidth		  width of the reference plane
     44  * [in]	pRefRect		  reference plane valid region rectangle
     45  * [in]	pSrcCurrBuf		pointer to the current macroblock extracted from original plane
     46  *                    (linear array, 256 entries); must be aligned on an 8-byte boundary.
     47  * [in]	pSearchPointRefPos	position of the starting point for half pixel search (specified
     48  *                          in terms of integer pixel units) in the reference plane.
     49  * [in]	rndVal			  rounding control bit for half pixel motion estimation;
     50  *                    0=rounding control disabled; 1=rounding control enabled
     51  * [in]	pSrcDstMV		pointer to the initial MV estimate; typically generated during a prior
     52  *                  16X16 integer search and its unit is half pixel.
     53  * [in] BlockSize     MacroBlock Size i.e either 16x16 or 8x8.
     54  * [out]pSrcDstMV		pointer to estimated MV
     55  * [out]pDstSAD			pointer to minimum SAD
     56  *
     57  * Return Value:
     58  * OMX_Sts_NoErr C no error
     59  * OMX_Sts_BadArgErr C bad arguments
     60  *
     61  */
     62 
     63 OMXResult armVCM4P2_BlockMatch_Half(
     64      const OMX_U8 *pSrcRefBuf,
     65      OMX_INT refWidth,
     66      const OMXRect *pRefRect,
     67      const OMX_U8 *pSrcCurrBuf,
     68      const OMXVCM4P2Coordinate *pSearchPointRefPos,
     69      OMX_INT rndVal,
     70      OMXVCMotionVector *pSrcDstMV,
     71      OMX_INT *pDstSAD,
     72      OMX_U8 BlockSize
     73 )
     74 {
     75     OMX_INT     outer, inner, count, index;
     76     OMX_S16     halfPelX = 0, halfPelY = 0, x, y;
     77     OMX_INT     candSAD, refSAD = 0;
     78     OMX_INT     minSAD, fromX, toX, fromY, toY;
     79     /* Offset to the reference at the begining of the bounding box */
     80     const OMX_U8      *pTempSrcRefBuf;
     81     OMX_U8 tempPel;
     82 
     83     /* Argument error checks */
     84     armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
     85     armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
     86     armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
     87     armRetArgErrIf(pSearchPointRefPos == NULL, OMX_Sts_BadArgErr);
     88     armRetArgErrIf(pSrcDstMV == NULL, OMX_Sts_BadArgErr);
     89     armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
     90 
     91     /* Positioning the pointer */
     92     pTempSrcRefBuf = pSrcRefBuf + (refWidth * (pSrcDstMV->dy/2)) + (pSrcDstMV->dx/2);
     93 
     94     /* Copy the candidate to the temporary linear array */
     95     for (outer = 0, count = 0,index = 0;
     96          outer < BlockSize;
     97          outer++, index += refWidth - BlockSize)
     98     {
     99         for (inner = 0; inner < BlockSize; inner++, count++, index++)
    100         {
    101             refSAD += armAbs (pTempSrcRefBuf[index] - pSrcCurrBuf[count]);
    102         }
    103     }
    104 
    105     /* Set the minSad as reference SAD */
    106     minSAD = refSAD;
    107     *pDstSAD = refSAD;
    108 
    109     /* Check for valid region */
    110     fromX = 1;
    111     toX   = 1;
    112     fromY = 1;
    113     toY   = 1;
    114     if ((pSearchPointRefPos->x - 1) < pRefRect->x)
    115     {
    116         fromX = 0;
    117     }
    118 
    119     if ((pSearchPointRefPos->x + BlockSize + 1) > (pRefRect->x + pRefRect->width))
    120     {
    121         toX   = 0;
    122     }
    123 
    124     if ((pSearchPointRefPos->y - 1) < pRefRect->y)
    125     {
    126         fromY = 0;
    127     }
    128 
    129     if ((pSearchPointRefPos->y + BlockSize + 1) > (pRefRect->y + pRefRect->height))
    130     {
    131         toY   = 0;
    132     }
    133 
    134     /* Looping on y- axis */
    135     for (y = -fromY; y <= toY; y++)
    136     {
    137         /* Looping on x- axis */
    138         for (x = -fromX; x <= toX; x++)
    139         {
    140             /* check for integer position */
    141             if ( x == 0 && y == 0)
    142             {
    143                 continue;
    144             }
    145             /* Positioning the pointer */
    146             pTempSrcRefBuf = pSrcRefBuf + (refWidth * (pSrcDstMV->dy/2))
    147                              + (pSrcDstMV->dx/2);
    148 
    149             /* Interpolate the pixel and calculate the SAD*/
    150             for (outer = 0, count = 0, candSAD = 0,index = 0;
    151                  outer < BlockSize;
    152                  outer++, index += refWidth - BlockSize)
    153             {
    154                 for (inner = 0; inner < BlockSize; inner++, count++,index++)
    155                 {
    156                     tempPel = (
    157                                 pTempSrcRefBuf[index]
    158                                 + pTempSrcRefBuf[index + x] * armAbs(x)
    159                                 + pTempSrcRefBuf[index + refWidth * y] * armAbs(y)
    160                                 + pTempSrcRefBuf[index + refWidth * y + x]
    161                                   * armAbs(x*y)
    162                                 + armAbs (x) + armAbs (y) - rndVal
    163                               ) / (2 * (armAbs (x) + armAbs (y)));
    164                     candSAD += armAbs (tempPel - pSrcCurrBuf[count]);
    165                 }
    166             }
    167 
    168             /* Result calculations */
    169             if (armVCM4P2_CompareMV (x, y, candSAD, halfPelX, halfPelY, minSAD))
    170             {
    171                 *pDstSAD = candSAD;
    172                 minSAD   = candSAD;
    173                 halfPelX = x;
    174                 halfPelY = y;
    175             }
    176 
    177         } /* End of x- axis */
    178     } /* End of y-axis */
    179 
    180     pSrcDstMV->dx += halfPelX;
    181     pSrcDstMV->dy += halfPelY;
    182 
    183     return OMX_Sts_NoErr;
    184 
    185 }
    186 
    187 /* End of file */
    188