blob: 4ffda107ba8ac2f72cb40753e3a9c0c8204f9c72 [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_Half.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_Half
*
* Description:
* Performs a 16x16 block match with half-pixel resolution. Returns the estimated
* motion vector and associated minimum SAD. This function estimates the half-pixel
* motion vector by interpolating the integer resolution motion vector referenced
* by the input parameter pSrcDstMV, i.e., the initial integer MV is generated
* externally. The input parameters pSrcRefBuf and pSearchPointRefPos should be
* shifted by the winning MV of 16x16 integer search prior to calling BlockMatch_Half_16x16.
* The function BlockMatch_Integer_16x16 may be used for integer motion estimation.
*
* 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 reference plane valid region rectangle
* [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane
* (linear array, 256 entries); must be aligned on an 8-byte boundary.
* [in] pSearchPointRefPos position of the starting point for half pixel search (specified
* in terms of integer pixel units) in the reference plane.
* [in] rndVal rounding control bit for half pixel motion estimation;
* 0=rounding control disabled; 1=rounding control enabled
* [in] pSrcDstMV pointer to the initial MV estimate; typically generated during a prior
* 16X16 integer search and its unit is half pixel.
* [in] BlockSize MacroBlock Size i.e either 16x16 or 8x8.
* [out]pSrcDstMV 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_Half(
const OMX_U8 *pSrcRefBuf,
OMX_INT refWidth,
const OMXRect *pRefRect,
const OMX_U8 *pSrcCurrBuf,
const OMXVCM4P2Coordinate *pSearchPointRefPos,
OMX_INT rndVal,
OMXVCMotionVector *pSrcDstMV,
OMX_INT *pDstSAD,
OMX_U8 BlockSize
)
{
OMX_INT outer, inner, count, index;
OMX_S16 halfPelX = 0, halfPelY = 0, x, y;
OMX_INT candSAD, refSAD = 0;
OMX_INT minSAD, fromX, toX, fromY, toY;
/* Offset to the reference at the begining of the bounding box */
const OMX_U8 *pTempSrcRefBuf;
OMX_U8 tempPel;
/* Argument error checks */
armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pSearchPointRefPos == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pSrcDstMV == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
/* Positioning the pointer */
pTempSrcRefBuf = pSrcRefBuf + (refWidth * (pSrcDstMV->dy/2)) + (pSrcDstMV->dx/2);
/* Copy the candidate to the temporary linear array */
for (outer = 0, count = 0,index = 0;
outer < BlockSize;
outer++, index += refWidth - BlockSize)
{
for (inner = 0; inner < BlockSize; inner++, count++, index++)
{
refSAD += armAbs (pTempSrcRefBuf[index] - pSrcCurrBuf[count]);
}
}
/* Set the minSad as reference SAD */
minSAD = refSAD;
*pDstSAD = refSAD;
/* Check for valid region */
fromX = 1;
toX = 1;
fromY = 1;
toY = 1;
if ((pSearchPointRefPos->x - 1) < pRefRect->x)
{
fromX = 0;
}
if ((pSearchPointRefPos->x + BlockSize + 1) > (pRefRect->x + pRefRect->width))
{
toX = 0;
}
if ((pSearchPointRefPos->y - 1) < pRefRect->y)
{
fromY = 0;
}
if ((pSearchPointRefPos->y + BlockSize + 1) > (pRefRect->y + pRefRect->height))
{
toY = 0;
}
/* Looping on y- axis */
for (y = -fromY; y <= toY; y++)
{
/* Looping on x- axis */
for (x = -fromX; x <= toX; x++)
{
/* check for integer position */
if ( x == 0 && y == 0)
{
continue;
}
/* Positioning the pointer */
pTempSrcRefBuf = pSrcRefBuf + (refWidth * (pSrcDstMV->dy/2))
+ (pSrcDstMV->dx/2);
/* Interpolate the pixel and calculate the SAD*/
for (outer = 0, count = 0, candSAD = 0,index = 0;
outer < BlockSize;
outer++, index += refWidth - BlockSize)
{
for (inner = 0; inner < BlockSize; inner++, count++,index++)
{
tempPel = (
pTempSrcRefBuf[index]
+ pTempSrcRefBuf[index + x] * armAbs(x)
+ pTempSrcRefBuf[index + refWidth * y] * armAbs(y)
+ pTempSrcRefBuf[index + refWidth * y + x]
* armAbs(x*y)
+ armAbs (x) + armAbs (y) - rndVal
) / (2 * (armAbs (x) + armAbs (y)));
candSAD += armAbs (tempPel - pSrcCurrBuf[count]);
}
}
/* Result calculations */
if (armVCM4P2_CompareMV (x, y, candSAD, halfPelX, halfPelY, minSAD))
{
*pDstSAD = candSAD;
minSAD = candSAD;
halfPelX = x;
halfPelY = y;
}
} /* End of x- axis */
} /* End of y-axis */
pSrcDstMV->dx += halfPelX;
pSrcDstMV->dy += halfPelY;
return OMX_Sts_NoErr;
}
/* End of file */