1/**
2 *
3 * File Name:  armVCM4P2_BlockMatch_Integer.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_Integer
27 *
28 * Description:
29 * Performs a 16x16 block search; estimates motion vector and associated minimum SAD.
30 * Both the input and output motion vectors are represented using half-pixel units, and
31 * therefore a shift left or right by 1 bit may be required, respectively, to match the
32 * input or output MVs with other functions that either generate output MVs or expect
33 * input MVs represented using integer pixel units.
34 *
35 * Remarks:
36 *
37 * Parameters:
38 * [in]	pSrcRefBuf		pointer to the reference Y plane; points to the reference MB that
39 *                    corresponds to the location of the current macroblock in the current
40 *                    plane.
41 * [in]	refWidth		  width of the reference plane
42 * [in]	pRefRect		  pointer to the valid rectangular in reference plane. Relative to image origin.
43 *                    It's not limited to the image boundary, but depended on the padding. For example,
44 *                    if you pad 4 pixels outside the image border, then the value for left border
45 *                    can be -4
46 * [in]	pSrcCurrBuf		pointer to the current macroblock extracted from original plane (linear array,
47 *                    256 entries); must be aligned on an 8-byte boundary.
48 * [in] pCurrPointPos	position of the current macroblock in the current plane
49 * [in] pSrcPreMV		  pointer to predicted motion vector; NULL indicates no predicted MV
50 * [in] pSrcPreSAD		pointer to SAD associated with the predicted MV (referenced by pSrcPreMV)
51 * [in] searchRange		search range for 16X16 integer block,the units of it is full pixel,the search range
52 *                    is the same in all directions.It is in inclusive of the boundary and specified in
53 *                    terms of integer pixel units.
54 * [in] pMESpec			  vendor-specific motion estimation specification structure; must have been allocated
55 *                    and then initialized using omxVCM4P2_MEInit prior to calling the block matching
56 *                    function.
57 * [out]	pDstMV			pointer to estimated MV
58 * [out]	pDstSAD			pointer to minimum SAD
59 *
60 * Return Value:
61 * OMX_Sts_NoErr ¨C no error.
62 * OMX_Sts_BadArgErr ¨C bad arguments
63 *
64 */
65
66OMXResult armVCM4P2_BlockMatch_Integer(
67     const OMX_U8 *pSrcRefBuf,
68     OMX_INT refWidth,
69     const OMXRect *pRefRect,
70     const OMX_U8 *pSrcCurrBuf,
71     const OMXVCM4P2Coordinate *pCurrPointPos,
72     const OMXVCMotionVector *pSrcPreMV,
73     const OMX_INT *pSrcPreSAD,
74     void *pMESpec,
75     OMXVCMotionVector *pDstMV,
76     OMX_INT *pDstSAD,
77     OMX_U8 BlockSize
78)
79{
80
81    /* Definitions and Initializations*/
82
83    OMX_INT     outer, inner, count,index;
84    OMX_INT     candSAD;
85    /*(256*256 +1) this is to make the SAD max initially*/
86    OMX_INT     minSAD = 0x10001, fromX, toX, fromY, toY;
87    /* Offset to the reference at the begining of the bounding box */
88    const OMX_U8      *pTempSrcRefBuf;
89    OMX_S16     x, y;
90    OMX_INT searchRange;
91
92    /* Argument error checks */
93    armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
94    armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
95    armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
96    armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr);
97    armRetArgErrIf(pMESpec == NULL, OMX_Sts_BadArgErr);
98    armRetArgErrIf(pDstMV == NULL, OMX_Sts_BadArgErr);
99    armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
100
101    searchRange = ((OMXVCM4P2MEParams *)pMESpec)->searchRange;
102    /* Check for valid region */
103    fromX = searchRange;
104    toX   = searchRange;
105    fromY = searchRange;
106    toY   = searchRange;
107
108    if ((pCurrPointPos->x - searchRange) < pRefRect->x)
109    {
110        fromX =  pCurrPointPos->x - pRefRect->x;
111    }
112
113    if ((pCurrPointPos->x + BlockSize + searchRange) > (pRefRect->x + pRefRect->width))
114    {
115        toX   = pRefRect->width - (pCurrPointPos->x - pRefRect->x) - BlockSize;
116    }
117
118    if ((pCurrPointPos->y - searchRange) < pRefRect->y)
119    {
120        fromY = pCurrPointPos->y - pRefRect->y;
121    }
122
123    if ((pCurrPointPos->y + BlockSize + searchRange) > (pRefRect->y + pRefRect->height))
124    {
125        toY   = pRefRect->width - (pCurrPointPos->y - pRefRect->y) - BlockSize;
126    }
127
128    pDstMV->dx = -fromX;
129    pDstMV->dy = -fromY;
130    /* Looping on y- axis */
131    for (y = -fromY; y <= toY; y++)
132    {
133
134        /* Looping on x- axis */
135        for (x = -fromX; x <= toX; x++)
136        {
137            /* Positioning the pointer */
138            pTempSrcRefBuf = pSrcRefBuf + (refWidth * y) + x;
139
140            /* Calculate the SAD */
141            for (outer = 0, count = 0, index = 0, candSAD = 0;
142                 outer < BlockSize;
143                 outer++, index += refWidth - BlockSize)
144            {
145                for (inner = 0; inner < BlockSize; inner++, count++, index++)
146                {
147                    candSAD += armAbs (pTempSrcRefBuf[index] - pSrcCurrBuf[count]);
148                }
149            }
150
151            /* Result calculations */
152            if (armVCM4P2_CompareMV (x, y, candSAD, pDstMV->dx/2, pDstMV->dy/2, minSAD))
153            {
154                *pDstSAD = candSAD;
155                minSAD   = candSAD;
156                pDstMV->dx = x*2;
157                pDstMV->dy = y*2;
158            }
159
160        } /* End of x- axis */
161    } /* End of y-axis */
162
163    return OMX_Sts_NoErr;
164
165}
166
167/* End of file */
168