armVCM4P2_BlockMatch_Half.c revision 0c1bc742181ded4930842b46e9507372f0b1b963
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
63OMXResult 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