blob: 33f0cf56463037c4a0964b6e2ec6aad54887adf4 [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: omxVCM4P2_MCReconBlock.c
* OpenMAX DL: v1.0.2
* Revision: 9641
* Date: Thursday, February 7, 2008
*
*
*
* Description:
* MPEG4 motion compensation prediction for an 8x8 block using
* interpolation
*
*/
#include "omxtypes.h"
#include "armOMX.h"
#include "omxVC.h"
#include "armCOMM.h"
/**
* Function: armVCM4P2_HalfPelVer
*
* Description:
* Performs half pel motion compensation for an 8x8 block using vertical
* interpolation described in ISO/IEC 14496-2, subclause 7.6.2.
*
* Remarks:
*
* Parameters:
* [in] pSrc pointer to the block in the reference plane.
* [in] srcStep distance between the start of consecutive lines
* in the reference plane, in bytes; must be a multiple
* of 8.
* [in] rndVal rounding control parameter: 0 - disabled; 1 - enabled.
* [out] pDst pointer to the linaer 8x8 destination buffer;
*
*/
static OMXVoid armVCM4P2_HalfPelVer(
const OMX_U8 *pSrc,
OMX_INT srcStep,
OMX_U8 *pDst,
OMX_INT rndVal)
{
const OMX_U8 *pTempSrc1;
const OMX_U8 *pTempSrc2;
OMX_INT y, x;
pTempSrc1 = pSrc;
pTempSrc2 = pSrc + srcStep;
srcStep -= 8;
for (y = 0; y < 8; y++)
{
for (x = 0; x < 8; x++)
{
*pDst++ = ((*pTempSrc1++ + *pTempSrc2++) + 1 - rndVal) >> 1;
}
pTempSrc1 += srcStep;
pTempSrc2 += srcStep;
}
}
/**
* Function: armVCM4P2_HalfPelHor
*
* Description:
* Performs half pel motion compensation for an 8x8 block using horizontal
* interpolation described in ISO/IEC 14496-2, subclause 7.6.2.
*
* Remarks:
*
* Parameters:
* [in] pSrc pointer to the block in the reference plane.
* [in] srcStep distance between the start of consecutive lines
* in the reference plane, in bytes; must be a multiple
* of 8.
* [in] rndVal rounding control parameter: 0 - disabled; 1 - enabled.
* [out] pDst pointer to the linaer 8x8 destination buffer;
*
*/
static OMXVoid armVCM4P2_HalfPelHor(
const OMX_U8 *pSrc,
OMX_INT srcStep,
OMX_U8 *pDst,
OMX_INT rndVal)
{
const OMX_U8 *pTempSrc1;
const OMX_U8 *pTempSrc2;
OMX_INT y, x;
pTempSrc1 = pSrc;
pTempSrc2 = pTempSrc1 + 1;
srcStep -= 8;
for (y=0; y<8; y++)
{
for (x=0; x<8; x++)
{
*pDst++ = ((*pTempSrc1++ + *pTempSrc2++) + 1 - rndVal) >> 1;
}
pTempSrc1 += srcStep;
pTempSrc2 += srcStep;
}
}
/**
* Function: armVCM4P2_HalfPelVerHor
*
* Description:
* Performs half pel motion compensation for an 8x8 block using both
* horizontal and vertical interpolation described in ISO/IEC 14496-2,
* subclause 7.6.2.
*
* Remarks:
*
* Parameters:
* [in] pSrc pointer to the block in the reference plane.
* [in] srcStep distance between the start of consecutive lines
* in the reference plane, in bytes; must be a multiple
* of 8.
* [in] rndVal rounding control parameter: 0 - disabled; 1 - enabled.
* [out] pDst pointer to the linaer 8x8 destination buffer;
*
*/
static OMXVoid armVCM4P2_HalfPelVerHor(
const OMX_U8 *pSrc,
OMX_INT srcStep,
OMX_U8 *pDst,
OMX_INT rndVal)
{
const OMX_U8 *pTempSrc1;
const OMX_U8 *pTempSrc2;
const OMX_U8 *pTempSrc3;
const OMX_U8 *pTempSrc4;
OMX_INT y, x;
pTempSrc1 = pSrc;
pTempSrc2 = pSrc + srcStep;
pTempSrc3 = pSrc + 1;
pTempSrc4 = pSrc + srcStep + 1;
srcStep -= 8;
for (y=0; y<8; y++)
{
for (x=0; x<8; x++)
{
*pDst++ = ((*pTempSrc1++ + *pTempSrc2++ + *pTempSrc3++ + *pTempSrc4++) +
2 - rndVal) >> 2;
}
pTempSrc1 += srcStep;
pTempSrc2 += srcStep;
pTempSrc3 += srcStep;
pTempSrc4 += srcStep;
}
}
/**
* Function: armVCM4P2_MCReconBlock_NoRes
*
* Description:
* Do motion compensation and copy the result to the current block.
*
* Remarks:
*
* Parameters:
* [in] pSrc pointer to the block in the reference plane.
* [in] srcStep distance between the start of consecutive lines
* in the reference plane, in bytes; must be a multiple
* of 8.
* [in] dstStep distance between the start of consecutive lines in the
* destination plane, in bytes; must be a multiple of 8.
* [in] predictType bilinear interpolation type, as defined in section 6.2.1.2.
* [in] rndVal rounding control parameter: 0 - disabled; 1 - enabled.
* [out] pDst pointer to the destination buffer; must be 8-byte aligned.
* If prediction residuals are added then output intensities
* are clipped to the range [0,255].
*
*/
static OMXVoid armVCM4P2_MCReconBlock_NoRes(
const OMX_U8 *pSrc,
OMX_INT srcStep,
OMX_U8 *pDst,
OMX_INT dstStep)
{
OMX_U8 x,y,count,index;
/* Copying the ref 8x8 blk to the curr blk */
for (y = 0, count = 0, index = 0; y < 8; y++,index += (srcStep -8), count += (dstStep - 8))
{
for (x = 0; x < 8; x++, count++,index++)
{
pDst[count] = pSrc[index];
}
}
}
/**
* Function: armVCM4P2_MCReconBlock_Res
*
* Description:
* Reconstructs INTER block by summing the motion compensation results
* and the results of the inverse transformation (prediction residuals).
* Output intensities are clipped to the range [0,255].
*
* Remarks:
*
* Parameters:
* [in] pSrc pointer to the block in the reference plane.
* [in] pSrcResidue pointer to a buffer containing the 16-bit prediction
* residuals. If the pointer is NULL,then no prediction
* is done, only motion compensation, i.e., the block is
* moved with interpolation.
* [in] dstStep distance between the start of consecutive lines in the
* destination plane, in bytes; must be a multiple of 8.
* [out] pDst pointer to the destination buffer; must be 8-byte aligned.
* If prediction residuals are added then output intensities
* are clipped to the range [0,255].
*
*/
static OMXVoid armVCM4P2_MCReconBlock_Res(
const OMX_U8 *pSrc,
const OMX_S16 *pSrcResidue,
OMX_U8 *pDst,
OMX_INT dstStep)
{
OMX_U8 x,y;
OMX_INT temp;
for(y = 0; y < 8; y++)
{
for(x = 0; x < 8; x++)
{
temp = pSrc[x] + pSrcResidue[x];
pDst[x] = armClip(0,255,temp);
}
pDst += dstStep;
pSrc += 8;
pSrcResidue += 8;
}
}
/**
* Function: omxVCM4P2_MCReconBlock (6.2.5.5.1)
*
* Description:
* Performs motion compensation prediction for an 8x8 block using
* interpolation described in [ISO14496-2], subclause 7.6.2.
*
* Input Arguments:
*
* pSrc - pointer to the block in the reference plane.
* srcStep - distance between the start of consecutive lines in the
* reference plane, in bytes; must be a multiple of 8.
* dstStep - distance between the start of consecutive lines in the
* destination plane, in bytes; must be a multiple of 8.
* pSrcResidue - pointer to a buffer containing the 16-bit prediction
* residuals; must be 16-byte aligned. If the pointer is NULL, then
* no prediction is done, only motion compensation, i.e., the block
* is moved with interpolation.
* predictType - bilinear interpolation type, as defined in section
* 6.2.1.2.
* rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
*
* Output Arguments:
*
* pDst - pointer to the destination buffer; must be 8-byte aligned. If
* prediction residuals are added then output intensities are
* clipped to the range [0,255].
*
* Return Value:
*
* OMX_Sts_NoErr - no error
* OMX_Sts_BadArgErr - bad arguments; returned under any of the following
* conditions:
* - pDst is not 8-byte aligned.
* - pSrcResidue is not 16-byte aligned.
* - one or more of the following pointers is NULL: pSrc or pDst.
* - either srcStep or dstStep is not a multiple of 8.
* - invalid type specified for the parameter predictType.
* - the parameter rndVal is not equal either to 0 or 1.
*
*/
OMXResult omxVCM4P2_MCReconBlock(
const OMX_U8 *pSrc,
OMX_INT srcStep,
const OMX_S16 *pSrcResidue,
OMX_U8 *pDst,
OMX_INT dstStep,
OMX_INT predictType,
OMX_INT rndVal)
{
/* Definitions and Initializations*/
OMX_U8 pTempDst[64];
/* Argument error checks */
armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(!armIs8ByteAligned(pDst), OMX_Sts_BadArgErr);
armRetArgErrIf(!armIs16ByteAligned(pSrcResidue), OMX_Sts_BadArgErr);
armRetArgErrIf(((dstStep % 8) || (srcStep % 8)), OMX_Sts_BadArgErr);
armRetArgErrIf(((predictType != OMX_VC_INTEGER_PIXEL) &&
(predictType != OMX_VC_HALF_PIXEL_X) &&
(predictType != OMX_VC_HALF_PIXEL_Y) &&
(predictType != OMX_VC_HALF_PIXEL_XY)
),OMX_Sts_BadArgErr);
armRetArgErrIf(((rndVal != 0) && (rndVal != 1)),OMX_Sts_BadArgErr);
switch(predictType)
{
case OMX_VC_INTEGER_PIXEL:
armVCM4P2_MCReconBlock_NoRes(pSrc,
srcStep,
&(pTempDst[0]),
8);
break;
case OMX_VC_HALF_PIXEL_X:
armVCM4P2_HalfPelHor(pSrc,
srcStep,
&(pTempDst[0]),
rndVal);
break;
case OMX_VC_HALF_PIXEL_Y:
armVCM4P2_HalfPelVer(pSrc,
srcStep,
&(pTempDst[0]),
rndVal);
break;
case OMX_VC_HALF_PIXEL_XY:
armVCM4P2_HalfPelVerHor(pSrc,
srcStep,
&(pTempDst[0]),
rndVal);
break;
}
if(pSrcResidue == NULL)
{
armVCM4P2_MCReconBlock_NoRes(&(pTempDst[0]),
8,
pDst,
dstStep);
}
else
{
armVCM4P2_MCReconBlock_Res(&(pTempDst[0]),
pSrcResidue,
pDst,
dstStep);
}
return OMX_Sts_NoErr;
}