blob: c993f736dd61fb1f0926b9eff32eb85f961cd47b [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_ACDCPredict.c
* OpenMAX DL: v1.0.2
* Revision: 9641
* Date: Thursday, February 7, 2008
*
*
*
*
* Description:
* Contains module for DC/AC coefficient prediction
*
*/
#include "omxtypes.h"
#include "armOMX.h"
#include "armVC.h"
#include "armCOMM.h"
/**
* Function: armVCM4P2_ACDCPredict
*
* Description:
* Performs adaptive DC/AC coefficient prediction for an intra block. Prior
* to the function call, prediction direction (predDir) should be selected
* as specified in subclause 7.4.3.1 of ISO/IEC 14496-2.
*
* Remarks:
*
* Parameters:
* [in] pSrcDst pointer to the coefficient buffer which contains
* the quantized coefficient residuals (PQF) of the
* current block
* [in] pPredBufRow pointer to the coefficient row buffer
* [in] pPredBufCol pointer to the coefficient column buffer
* [in] curQP quantization parameter of the current block. curQP
* may equal to predQP especially when the current
* block and the predictor block are in the same
* macroblock.
* [in] predQP quantization parameter of the predictor block
* [in] predDir indicates the prediction direction which takes one
* of the following values:
* OMX_VC_HORIZONTAL predict horizontally
* OMX_VC_VERTICAL predict vertically
* [in] ACPredFlag a flag indicating if AC prediction should be
* performed. It is equal to ac_pred_flag in the bit
* stream syntax of MPEG-4
* [in] videoComp video component type (luminance, chrominance or
* alpha) of the current block
* [in] flag This flag defines the if one wants to use this functions to
* calculate PQF (set 1, prediction) or QF (set 0, reconstruction)
* [out] pPreACPredict pointer to the predicted coefficients buffer.
* Filled ONLY if it is not NULL
* [out] pSrcDst pointer to the coefficient buffer which contains
* the quantized coefficients (QF) of the current
* block
* [out] pPredBufRow pointer to the updated coefficient row buffer
* [out] pPredBufCol pointer to the updated coefficient column buffer
* [out] pSumErr pointer to the updated sum of the difference
* between predicted and unpredicted coefficients
* If this is NULL, do not update
*
* Return Value:
* Standard OMXResult result. See enumeration for possible result codes.
*
*/
OMXResult armVCM4P2_ACDCPredict(
OMX_S16 * pSrcDst,
OMX_S16 * pPreACPredict,
OMX_S16 * pPredBufRow,
OMX_S16 * pPredBufCol,
OMX_INT curQP,
OMX_INT predQP,
OMX_INT predDir,
OMX_INT ACPredFlag,
OMXVCM4P2VideoComponent videoComp,
OMX_U8 flag,
OMX_INT *pSumErr
)
{
OMX_INT dcScaler, i;
OMX_S16 tempPred;
/* Argument error checks */
armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pPredBufRow == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(pPredBufCol == NULL, OMX_Sts_BadArgErr);
armRetArgErrIf(curQP <= 0, OMX_Sts_BadArgErr);
armRetArgErrIf(predQP <= 0, OMX_Sts_BadArgErr);
armRetArgErrIf((predDir != 1) && (predDir != 2), OMX_Sts_BadArgErr);
armRetArgErrIf(!armIs4ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
armRetArgErrIf(!armIs4ByteAligned(pPredBufRow), OMX_Sts_BadArgErr);
armRetArgErrIf(!armIs4ByteAligned(pPredBufCol), OMX_Sts_BadArgErr);
/* Set DC scaler value to avoid some compilers giving a warning. */
dcScaler=0;
/* Calculate the DC scaler value */
if (videoComp == OMX_VC_LUMINANCE)
{
if (curQP >= 1 && curQP <= 4)
{
dcScaler = 8;
}
else if (curQP >= 5 && curQP <= 8)
{
dcScaler = 2 * curQP;
}
else if (curQP >= 9 && curQP <= 24)
{
dcScaler = curQP + 8;
}
else
{
dcScaler = (2 * curQP) - 16;
}
}
else if (videoComp == OMX_VC_CHROMINANCE)
{
if (curQP >= 1 && curQP <= 4)
{
dcScaler = 8;
}
else if (curQP >= 5 && curQP <= 24)
{
dcScaler = (curQP + 13)/2;
}
else
{
dcScaler = curQP - 6;
}
}
if (pPreACPredict != NULL)
{
pPreACPredict[0] = predDir;
}
if (predDir == OMX_VC_VERTICAL)
{
/* F[0][0]//dc_scaler */
tempPred = armIntDivAwayFromZero(pPredBufRow[0], dcScaler);
}
else
{
/* F[0][0]//dc_scaler */
tempPred = armIntDivAwayFromZero(pPredBufCol[0], dcScaler);
}
/* Updating the DC value to the row and col buffer */
*(pPredBufRow - 8) = *pPredBufCol;
if (flag)
{
/* Cal and store F[0][0] into the col buffer */
*pPredBufCol = pSrcDst[0] * dcScaler;
/* PQF = QF - F[0][0]//dc_scaler */
pSrcDst[0] -= tempPred;
}
else
{
/* QF = PQF + F[0][0]//dc_scaler */
pSrcDst[0] += tempPred;
/* Saturate */
pSrcDst[0] = armClip (-2048, 2047, pSrcDst[0]);
/* Cal and store F[0][0] into the col buffer */
*pPredBufCol = pSrcDst[0] * dcScaler;
}
if (ACPredFlag == 1)
{
if (predDir == OMX_VC_VERTICAL)
{
for (i = 1; i < 8; i++)
{
tempPred = armIntDivAwayFromZero \
(pPredBufRow[i] * predQP, curQP);
if (flag)
{
/* Updating QF to the row buff */
pPredBufRow[i] = pSrcDst[i];
/*PQFX[v][0] = QFX[v][0] - (QFA[v][0] * QPA) // QPX */
pSrcDst[i] -= tempPred;
/* Sum of absolute values of AC prediction error, this can
be used as a reference to choose whether to use
AC prediction */
*pSumErr += armAbs(pSrcDst[i]);
/* pPreACPredict[1~7] store the error signal
after AC prediction */
pPreACPredict[i] = pSrcDst[i];
}
else
{
/*QFX[v][0] = PQFX[v][0] + (QFA[v][0] * QPA) // QPX */
pSrcDst[i] += tempPred;
/* Saturate */
pSrcDst[i] = armClip (-2048, 2047, pSrcDst[i]);
/* Updating QF to the row buff */
pPredBufRow[i] = pSrcDst[i];
}
}
}
else
{
for (i = 8; i < 64; i += 8)
{
tempPred = armIntDivAwayFromZero \
(pPredBufCol[i>>3] * predQP, curQP);
if (flag)
{
/* Updating QF to col buff */
pPredBufCol[i>>3] = pSrcDst[i];
/*PQFX[0][u] = QFX[0][u] - (QFA[0][u] * QPA) // QPX */
pSrcDst[i] -= tempPred;
/* Sum of absolute values of AC prediction error, this can
be used as a reference to choose whether to use AC
prediction */
*pSumErr += armAbs(pSrcDst[i]);
/* pPreACPredict[1~7] store the error signal
after AC prediction */
pPreACPredict[i>>3] = pSrcDst[i];
}
else
{
/*QFX[0][u] = PQFX[0][u] + (QFA[0][u] * QPA) // QPX */
pSrcDst[i] += tempPred;
/* Saturate */
pSrcDst[i] = armClip (-2048, 2047, pSrcDst[i]);
/* Updating QF to col buff */
pPredBufCol[i>>3] = pSrcDst[i];
}
}
}
}
return OMX_Sts_NoErr;
}
/*End of File*/