1/**
2 *
3 * File Name:  omxVCM4P10_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:  omxVCM4P10_BlockMatch_Integer   (6.3.5.2.1)
27 *
28 * Description:
29 * Performs integer block match.  Returns best MV and associated cost.
30 *
31 * Input Arguments:
32 *
33 *   pSrcOrgY - Pointer to the top-left corner of the current block. If
34 *            iBlockWidth==4,  4-byte alignment required. If iBlockWidth==8,
35 *            8-byte alignment required. If iBlockWidth==16, 16-byte alignment
36 *            required.
37 *   pSrcRefY - Pointer to the top-left corner of the co-located block in the
38 *            reference picture. If iBlockWidth==4,  4-byte alignment
39 *            required.  If iBlockWidth==8,  8-byte alignment required.  If
40 *            iBlockWidth==16, 16-byte alignment required.
41 *   nSrcOrgStep - Stride of the original picture plane, expressed in terms
42 *            of integer pixels; must be a multiple of iBlockWidth.
43 *   nSrcRefStep - Stride of the reference picture plane, expressed in terms
44 *            of integer pixels
45 *   pRefRect - pointer to the valid reference rectangle inside the reference
46 *            picture plane
47 *   nCurrPointPos - position of the current block in the current plane
48 *   iBlockWidth - Width of the current block, expressed in terms of integer
49 *            pixels; must be equal to either 4, 8, or 16.
50 *   iBlockHeight - Height of the current block, expressed in terms of
51 *            integer pixels; must be equal to either 4, 8, or 16.
52 *   nLamda - Lamda factor; used to compute motion cost
53 *   pMVPred - Predicted MV; used to compute motion cost, expressed in terms
54 *            of 1/4-pel units
55 *   pMVCandidate - Candidate MV; used to initialize the motion search,
56 *            expressed in terms of integer pixels
57 *   pMESpec - pointer to the ME specification structure
58 *
59 * Output Arguments:
60 *
61 *   pDstBestMV - Best MV resulting from integer search, expressed in terms
62 *            of 1/4-pel units
63 *   pBestCost - Motion cost associated with the best MV; computed as
64 *            SAD+Lamda*BitsUsedByMV
65 *
66 * Return Value:
67 *    OMX_Sts_NoErr, if the function runs without error.
68 *    OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
69 *    -    any of the following poitners are NULL:
70 *         pSrcOrgY, pSrcRefY, pRefRect, pMVPred, pMVCandidate, or pMESpec.
71 *    -    Either iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
72 *    -    Any alignment restrictions are violated
73 *
74 */
75
76 OMXResult omxVCM4P10_BlockMatch_Integer (
77     const OMX_U8 *pSrcOrgY,
78     OMX_S32 nSrcOrgStep,
79     const OMX_U8 *pSrcRefY,
80     OMX_S32 nSrcRefStep,
81	 const OMXRect *pRefRect,
82	 const OMXVCM4P2Coordinate *pCurrPointPos,
83     OMX_U8 iBlockWidth,
84     OMX_U8 iBlockHeight,
85     OMX_U32 nLamda,
86     const OMXVCMotionVector *pMVPred,
87     const OMXVCMotionVector *pMVCandidate,
88     OMXVCMotionVector *pBestMV,
89     OMX_S32 *pBestCost,
90     void *pMESpec
91)
92{
93    /* Definitions and Initializations*/
94    OMX_INT candSAD;
95    OMX_INT fromX, toX, fromY, toY;
96    /* Offset to the reference at the begining of the bounding box */
97    const OMX_U8 *pTempSrcRefY, *pTempSrcOrgY;
98    OMX_S16 x, y;
99    OMXVCMotionVector diffMV;
100    OMX_S32 nSearchRange;
101    ARMVCM4P10_MESpec *armMESpec = (ARMVCM4P10_MESpec *) pMESpec;
102
103    /* Argument error checks */
104    armRetArgErrIf((iBlockWidth ==  4) && (!armIs4ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
105    armRetArgErrIf((iBlockWidth ==  8) && (!armIs8ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
106    armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
107	armRetArgErrIf((iBlockWidth ==  4) && (!armIs4ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
108    armRetArgErrIf((iBlockWidth ==  8) && (!armIs8ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
109    armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
110    armRetArgErrIf(pSrcOrgY == NULL, OMX_Sts_BadArgErr);
111    armRetArgErrIf(pSrcRefY == NULL, OMX_Sts_BadArgErr);
112    armRetArgErrIf(pMVPred == NULL, OMX_Sts_BadArgErr);
113    armRetArgErrIf(pMVCandidate == NULL, OMX_Sts_BadArgErr);
114    armRetArgErrIf(pBestMV == NULL, OMX_Sts_BadArgErr);
115    armRetArgErrIf(pBestCost == NULL, OMX_Sts_BadArgErr);
116	armRetArgErrIf(((iBlockWidth!=4)&&(iBlockWidth!=8)&&(iBlockWidth!=16)) , OMX_Sts_BadArgErr);
117	armRetArgErrIf(((iBlockHeight!=4)&&(iBlockHeight!=8)&&(iBlockHeight!=16)) , OMX_Sts_BadArgErr);
118    armIgnore (pMESpec);
119
120    if(iBlockWidth == 4)
121    {
122        nSearchRange = armMESpec->MEParams.searchRange4x4;
123    }
124    else if(iBlockWidth == 8)
125    {
126        nSearchRange = armMESpec->MEParams.searchRange8x8;
127    }
128    else
129    {
130        nSearchRange = armMESpec->MEParams.searchRange16x16;
131    }
132    /* Check for valid region */
133    fromX = nSearchRange;
134    toX   = nSearchRange;
135    fromY = nSearchRange;
136    toY   = nSearchRange;
137
138    if ((pCurrPointPos->x - nSearchRange) < pRefRect->x)
139    {
140        fromX =  pCurrPointPos->x - pRefRect->x;
141    }
142
143    if ((pCurrPointPos->x + iBlockWidth + nSearchRange) > (pRefRect->x + pRefRect->width))
144    {
145        toX   = pRefRect->width - (pCurrPointPos->x - pRefRect->x) - iBlockWidth;
146    }
147
148    if ((pCurrPointPos->y - nSearchRange) < pRefRect->y)
149    {
150        fromY = pCurrPointPos->y - pRefRect->y;
151    }
152
153    if ((pCurrPointPos->y + iBlockWidth + nSearchRange) > (pRefRect->y + pRefRect->height))
154    {
155        toY   = pRefRect->width - (pCurrPointPos->y - pRefRect->y) - iBlockWidth;
156    }
157
158    pBestMV->dx = -fromX * 4;
159    pBestMV->dy = -fromY * 4;
160    /* Initialize to max value as a start point */
161    *pBestCost = 0x7fffffff;
162
163    /* Looping on y- axis */
164    for (y = -fromY; y <= toY; y++)
165    {
166        /* Looping on x- axis */
167        for (x = -fromX; x <= toX; x++)
168        {
169            /* Positioning the pointer */
170            pTempSrcRefY = pSrcRefY + (nSrcRefStep * y) + x;
171            pTempSrcOrgY = pSrcOrgY;
172
173            /* Calculate the SAD */
174            armVCCOMM_SAD(
175    	        pTempSrcOrgY,
176    	        nSrcOrgStep,
177    	        pTempSrcRefY,
178    	        nSrcRefStep,
179    	        &candSAD,
180    	        iBlockHeight,
181    	        iBlockWidth);
182
183            diffMV.dx = (x * 4) - pMVPred->dx;
184            diffMV.dy = (y * 4) - pMVPred->dy;
185
186            /* Result calculations */
187            armVCM4P10_CompareMotionCostToMV ((x * 4), (y * 4), diffMV, candSAD, pBestMV, nLamda, pBestCost);
188
189        } /* End of x- axis */
190    } /* End of y-axis */
191
192    return OMX_Sts_NoErr;
193
194}
195
196/* End of file */
197