blob: 2b0566063851ecb39772017ae47ba99fd6e596c0 [file] [log] [blame]
/*
* Copyright (C) 2007-2008 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
*
* File Name: armVCM4P2_BlockMatch_Integer.c
* OpenMAX DL: v1.0.2
* Revision: 9641
* Date: Thursday, February 7, 2008
*
*
*
*
* Description:
* Contains modules for Block matching, a full search algorithm
* is implemented
*
*/
#include "omxtypes.h"
#include "armOMX.h"
#include "omxVC.h"
#include "armVC.h"
#include "armCOMM.h"
/**
* Function: armVCM4P2_BlockMatch_Integer
*
* Description:
* Performs a 16x16 block search; estimates motion vector and associated minimum SAD.
* Both the input and output motion vectors are represented using half-pixel units, and
* therefore a shift left or right by 1 bit may be required, respectively, to match the
* input or output MVs with other functions that either generate output MVs or expect
* input MVs represented using integer pixel units.
*
* Remarks:
*
* Parameters:
* [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that
* corresponds to the location of the current macroblock in the current
* plane.
* [in] refWidth width of the reference plane
* [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin.
* It's not limited to the image boundary, but depended on the padding. For example,
* if you pad 4 pixels outside the image border, then the value for left border
* can be -4
* [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array,
* 256 entries); must be aligned on an 8-byte boundary.
* [in] pCurrPointPos position of the current macroblock in the current plane
* [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV
* [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV)
* [in] searchRange search range for 16X16 integer block,the units of it is full pixel,the search range
* is the same in all directions.It is in inclusive of the boundary and specified in
* terms of integer pixel units.
* [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated
* and then initialized using omxVCM4P2_MEInit prior to calling the block matching
* function.
* [out] pDstMV pointer to estimated MV
* [out] pDstSAD pointer to minimum SAD
*
* Return Value:
* OMX_Sts_NoErr ¨C no error.
* OMX_Sts_BadArgErr ¨C bad arguments
*
*/
OMXResult armVCM4P2_BlockMatch_Integer(
const OMX_U8 *pSrcRefBuf,
OMX_INT refWidth,
const OMXRect *pRefRect,
const OMX_U8 *pSrcCurrBuf,
const OMXVCM4P2Coordinate *pCurrPointPos,
const OMXVCMotionVector *pSrcPreMV,
const OMX_INT *pSrcPreSAD,
void *pMESpec,
OMXVCMotionVector *pDstMV,
OMX_INT *pDstSAD,
OMX_U8 BlockSize
)
{
/* Definitions and Initializations*/
OMX_INT outer, inner, count,index;
OMX_INT candSAD;
/*(256*256 +1) this is to make the SAD max initially*/
OMX_INT minSAD = 0x10001, fromX, toX, fromY, toY;
/* Offset to the reference at the begining of the bounding box */
const OMX_U8 *pTempSrcRefBuf;
OMX_S16 x, y;
OMX_INT searchRange;
/* Argument error checks */
armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pMESpec == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pDstMV == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
searchRange = ((OMXVCM4P2MEParams *)pMESpec)->searchRange;
/* Check for valid region */
fromX = searchRange;
toX = searchRange;
fromY = searchRange;
toY = searchRange;
if ((pCurrPointPos->x - searchRange) < pRefRect->x)
{
fromX = pCurrPointPos->x - pRefRect->x;
}
if ((pCurrPointPos->x + BlockSize + searchRange) > (pRefRect->x + pRefRect->width))
{
toX = pRefRect->width - (pCurrPointPos->x - pRefRect->x) - BlockSize;
}
if ((pCurrPointPos->y - searchRange) < pRefRect->y)
{
fromY = pCurrPointPos->y - pRefRect->y;
}
if ((pCurrPointPos->y + BlockSize + searchRange) > (pRefRect->y + pRefRect->height))
{
toY = pRefRect->width - (pCurrPointPos->y - pRefRect->y) - BlockSize;
}
pDstMV->dx = -fromX;
pDstMV->dy = -fromY;
/* Looping on y- axis */
for (y = -fromY; y <= toY; y++)
{
/* Looping on x- axis */
for (x = -fromX; x <= toX; x++)
{
/* Positioning the pointer */
pTempSrcRefBuf = pSrcRefBuf + (refWidth * y) + x;
/* Calculate the SAD */
for (outer = 0, count = 0, index = 0, candSAD = 0;
outer < BlockSize;
outer++, index += refWidth - BlockSize)
{
for (inner = 0; inner < BlockSize; inner++, count++, index++)
{
candSAD += armAbs (pTempSrcRefBuf[index] - pSrcCurrBuf[count]);
}
}
/* Result calculations */
if (armVCM4P2_CompareMV (x, y, candSAD, pDstMV->dx/2, pDstMV->dy/2, minSAD))
{
*pDstSAD = candSAD;
minSAD = candSAD;
pDstMV->dx = x*2;
pDstMV->dy = y*2;
}
} /* End of x- axis */
} /* End of y-axis */
return OMX_Sts_NoErr;
}
/* End of file */