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