blob: 2b3e7f0018c6bf819d67814ab89b9f1ef1670481 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* 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.
*/
/*------------------------------------------------------------------------------
Table of contents
1. Include headers
2. External compiler flags
3. Module defines
4. Local function prototypes
5. Functions
h264bsdDecodeMacroblockLayer
h264bsdMbPartPredMode
h264bsdNumMbPart
h264bsdNumSubMbPart
DecodeMbPred
DecodeSubMbPred
DecodeResidual
DetermineNc
CbpIntra16x16
h264bsdPredModeIntra16x16
h264bsdDecodeMacroblock
ProcessResidual
h264bsdSubMbPartMode
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include "h264bsd_macroblock_layer.h"
#include "h264bsd_slice_header.h"
#include "h264bsd_util.h"
#include "h264bsd_vlc.h"
#include "h264bsd_cavlc.h"
#include "h264bsd_nal_unit.h"
#include "h264bsd_neighbour.h"
#include "h264bsd_transform.h"
#include "h264bsd_intra_prediction.h"
#include "h264bsd_inter_prediction.h"
#ifdef H264DEC_OMXDL
#include "omxtypes.h"
#include "omxVC.h"
#include "armVC.h"
#endif /* H264DEC_OMXDL */
/*------------------------------------------------------------------------------
2. External compiler flags
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
3. Module defines
------------------------------------------------------------------------------*/
#ifdef H264DEC_OMXDL
static const u32 chromaIndex[8] = { 256, 260, 288, 292, 320, 324, 352, 356 };
static const u32 lumaIndex[16] = { 0, 4, 64, 68,
8, 12, 72, 76,
128, 132, 192, 196,
136, 140, 200, 204 };
#endif
/* mapping of dc coefficients array to luma blocks */
static const u32 dcCoeffIndex[16] =
{0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15};
/*------------------------------------------------------------------------------
4. Local function prototypes
------------------------------------------------------------------------------*/
static u32 DecodeMbPred(strmData_t *pStrmData, mbPred_t *pMbPred,
mbType_e mbType, u32 numRefIdxActive);
static u32 DecodeSubMbPred(strmData_t *pStrmData, subMbPred_t *pSubMbPred,
mbType_e mbType, u32 numRefIdxActive);
static u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual,
mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern);
#ifdef H264DEC_OMXDL
static u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, u8 *pTotalCoeff);
#else
static u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, i16 *pTotalCoeff);
#endif
static u32 CbpIntra16x16(mbType_e mbType);
#ifdef H264DEC_OMXDL
static u32 ProcessIntra4x4Residual(mbStorage_t *pMb, u8 *data, u32 constrainedIntraPred,
macroblockLayer_t *mbLayer, const u8 **pSrc, image_t *image);
static u32 ProcessChromaResidual(mbStorage_t *pMb, u8 *data, const u8 **pSrc );
static u32 ProcessIntra16x16Residual(mbStorage_t *pMb, u8 *data, u32 constrainedIntraPred,
u32 intraChromaPredMode, const u8 **pSrc, image_t *image);
#else
static u32 ProcessResidual(mbStorage_t *pMb, i32 residualLevel[][16], u32 *);
#endif
/*------------------------------------------------------------------------------
Function name: h264bsdDecodeMacroblockLayer
Functional description:
Parse macroblock specific information from bit stream.
Inputs:
pStrmData pointer to stream data structure
pMb pointer to macroblock storage structure
sliceType type of the current slice
numRefIdxActive maximum reference index
Outputs:
pMbLayer stores the macroblock data parsed from stream
Returns:
HANTRO_OK success
HANTRO_NOK end of stream or error in stream
------------------------------------------------------------------------------*/
u32 h264bsdDecodeMacroblockLayer(strmData_t *pStrmData,
macroblockLayer_t *pMbLayer, mbStorage_t *pMb, u32 sliceType,
u32 numRefIdxActive)
{
/* Variables */
u32 tmp, i, value;
i32 itmp;
mbPartPredMode_e partMode;
/* Code */
ASSERT(pStrmData);
ASSERT(pMbLayer);
#ifdef H264DEC_NEON
h264bsdClearMbLayer(pMbLayer, ((sizeof(macroblockLayer_t) + 63) & ~0x3F));
#else
H264SwDecMemset(pMbLayer, 0, sizeof(macroblockLayer_t));
#endif
tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
if (IS_I_SLICE(sliceType))
{
if ((value + 6) > 31 || tmp != HANTRO_OK)
return(HANTRO_NOK);
pMbLayer->mbType = (mbType_e)(value + 6);
}
else
{
if ((value + 1) > 31 || tmp != HANTRO_OK)
return(HANTRO_NOK);
pMbLayer->mbType = (mbType_e)(value + 1);
}
if (pMbLayer->mbType == I_PCM)
{
i32 *level;
while( !h264bsdIsByteAligned(pStrmData) )
{
/* pcm_alignment_zero_bit */
tmp = h264bsdGetBits(pStrmData, 1);
if (tmp)
return(HANTRO_NOK);
}
level = pMbLayer->residual.level[0];
for (i = 0; i < 384; i++)
{
value = h264bsdGetBits(pStrmData, 8);
if (value == END_OF_STREAM)
return(HANTRO_NOK);
*level++ = (i32)value;
}
}
else
{
partMode = h264bsdMbPartPredMode(pMbLayer->mbType);
if ( (partMode == PRED_MODE_INTER) &&
(h264bsdNumMbPart(pMbLayer->mbType) == 4) )
{
tmp = DecodeSubMbPred(pStrmData, &pMbLayer->subMbPred,
pMbLayer->mbType, numRefIdxActive);
}
else
{
tmp = DecodeMbPred(pStrmData, &pMbLayer->mbPred,
pMbLayer->mbType, numRefIdxActive);
}
if (tmp != HANTRO_OK)
return(tmp);
if (partMode != PRED_MODE_INTRA16x16)
{
tmp = h264bsdDecodeExpGolombMapped(pStrmData, &value,
(u32)(partMode == PRED_MODE_INTRA4x4));
if (tmp != HANTRO_OK)
return(tmp);
pMbLayer->codedBlockPattern = value;
}
else
{
pMbLayer->codedBlockPattern = CbpIntra16x16(pMbLayer->mbType);
}
if ( pMbLayer->codedBlockPattern ||
(partMode == PRED_MODE_INTRA16x16) )
{
tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
if (tmp != HANTRO_OK || (itmp < -26) || (itmp > 25) )
return(HANTRO_NOK);
pMbLayer->mbQpDelta = itmp;
tmp = DecodeResidual(pStrmData, &pMbLayer->residual, pMb,
pMbLayer->mbType, pMbLayer->codedBlockPattern);
pStrmData->strmBuffReadBits =
(u32)(pStrmData->pStrmCurrPos - pStrmData->pStrmBuffStart) * 8 +
pStrmData->bitPosInWord;
if (tmp != HANTRO_OK)
return(tmp);
}
}
return(HANTRO_OK);
}
/*------------------------------------------------------------------------------
Function: h264bsdMbPartPredMode
Functional description:
Returns the prediction mode of a macroblock type
------------------------------------------------------------------------------*/
mbPartPredMode_e h264bsdMbPartPredMode(mbType_e mbType)
{
/* Variables */
/* Code */
ASSERT(mbType <= 31);
if ((mbType <= P_8x8ref0))
return(PRED_MODE_INTER);
else if (mbType == I_4x4)
return(PRED_MODE_INTRA4x4);
else
return(PRED_MODE_INTRA16x16);
}
/*------------------------------------------------------------------------------
Function: h264bsdNumMbPart
Functional description:
Returns the amount of macroblock partitions in a macroblock type
------------------------------------------------------------------------------*/
u32 h264bsdNumMbPart(mbType_e mbType)
{
/* Variables */
/* Code */
ASSERT(h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER);
switch (mbType)
{
case P_L0_16x16:
case P_Skip:
return(1);
case P_L0_L0_16x8:
case P_L0_L0_8x16:
return(2);
/* P_8x8 or P_8x8ref0 */
default:
return(4);
}
}
/*------------------------------------------------------------------------------
Function: h264bsdNumSubMbPart
Functional description:
Returns the amount of sub-partitions in a sub-macroblock type
------------------------------------------------------------------------------*/
u32 h264bsdNumSubMbPart(subMbType_e subMbType)
{
/* Variables */
/* Code */
ASSERT(subMbType <= P_L0_4x4);
switch (subMbType)
{
case P_L0_8x8:
return(1);
case P_L0_8x4:
case P_L0_4x8:
return(2);
/* P_L0_4x4 */
default:
return(4);
}
}
/*------------------------------------------------------------------------------
Function: DecodeMbPred
Functional description:
Parse macroblock prediction information from bit stream and store
in 'pMbPred'.
------------------------------------------------------------------------------*/
u32 DecodeMbPred(strmData_t *pStrmData, mbPred_t *pMbPred, mbType_e mbType,
u32 numRefIdxActive)
{
/* Variables */
u32 tmp, i, j, value;
i32 itmp;
/* Code */
ASSERT(pStrmData);
ASSERT(pMbPred);
switch (h264bsdMbPartPredMode(mbType))
{
case PRED_MODE_INTER: /* PRED_MODE_INTER */
if (numRefIdxActive > 1)
{
for (i = h264bsdNumMbPart(mbType), j = 0; i--; j++)
{
tmp = h264bsdDecodeExpGolombTruncated(pStrmData, &value,
(u32)(numRefIdxActive > 2));
if (tmp != HANTRO_OK || value >= numRefIdxActive)
return(HANTRO_NOK);
pMbPred->refIdxL0[j] = value;
}
}
for (i = h264bsdNumMbPart(mbType), j = 0; i--; j++)
{
tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
if (tmp != HANTRO_OK)
return(tmp);
pMbPred->mvdL0[j].hor = (i16)itmp;
tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
if (tmp != HANTRO_OK)
return(tmp);
pMbPred->mvdL0[j].ver = (i16)itmp;
}
break;
case PRED_MODE_INTRA4x4:
for (itmp = 0, i = 0; itmp < 2; itmp++)
{
value = h264bsdShowBits32(pStrmData);
tmp = 0;
for (j = 8; j--; i++)
{
pMbPred->prevIntra4x4PredModeFlag[i] =
value & 0x80000000 ? HANTRO_TRUE : HANTRO_FALSE;
value <<= 1;
if (!pMbPred->prevIntra4x4PredModeFlag[i])
{
pMbPred->remIntra4x4PredMode[i] = value>>29;
value <<= 3;
tmp++;
}
}
if (h264bsdFlushBits(pStrmData, 8 + 3*tmp) == END_OF_STREAM)
return(HANTRO_NOK);
}
/* fall-through */
case PRED_MODE_INTRA16x16:
tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
if (tmp != HANTRO_OK || value > 3)
return(HANTRO_NOK);
pMbPred->intraChromaPredMode = value;
break;
}
return(HANTRO_OK);
}
/*------------------------------------------------------------------------------
Function: DecodeSubMbPred
Functional description:
Parse sub-macroblock prediction information from bit stream and
store in 'pMbPred'.
------------------------------------------------------------------------------*/
u32 DecodeSubMbPred(strmData_t *pStrmData, subMbPred_t *pSubMbPred,
mbType_e mbType, u32 numRefIdxActive)
{
/* Variables */
u32 tmp, i, j, value;
i32 itmp;
/* Code */
ASSERT(pStrmData);
ASSERT(pSubMbPred);
ASSERT(h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER);
for (i = 0; i < 4; i++)
{
tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
if (tmp != HANTRO_OK || value > 3)
return(HANTRO_NOK);
pSubMbPred->subMbType[i] = (subMbType_e)value;
}
if ( (numRefIdxActive > 1) && (mbType != P_8x8ref0) )
{
for (i = 0; i < 4; i++)
{
tmp = h264bsdDecodeExpGolombTruncated(pStrmData, &value,
(u32)(numRefIdxActive > 2));
if (tmp != HANTRO_OK || value >= numRefIdxActive)
return(HANTRO_NOK);
pSubMbPred->refIdxL0[i] = value;
}
}
for (i = 0; i < 4; i++)
{
j = 0;
for (value = h264bsdNumSubMbPart(pSubMbPred->subMbType[i]);
value--; j++)
{
tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
if (tmp != HANTRO_OK)
return(tmp);
pSubMbPred->mvdL0[i][j].hor = (i16)itmp;
tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
if (tmp != HANTRO_OK)
return(tmp);
pSubMbPred->mvdL0[i][j].ver = (i16)itmp;
}
}
return(HANTRO_OK);
}
#ifdef H264DEC_OMXDL
/*------------------------------------------------------------------------------
Function: DecodeResidual
Functional description:
Parse residual information from bit stream and store in 'pResidual'.
------------------------------------------------------------------------------*/
u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual,
mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern)
{
/* Variables */
u32 i, j;
u32 blockCoded;
u32 blockIndex;
u32 is16x16;
OMX_INT nc;
OMXResult omxRes;
OMX_U8 *pPosCoefBuf;
/* Code */
ASSERT(pStrmData);
ASSERT(pResidual);
pPosCoefBuf = pResidual->posCoefBuf;
/* luma DC is at index 24 */
if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16)
{
nc = (OMX_INT)DetermineNc(pMb, 0, pResidual->totalCoeff);
#ifndef H264DEC_NEON
omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC(
(const OMX_U8 **) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[24],
&pPosCoefBuf,
nc,
16);
#else
omxRes = armVCM4P10_DecodeCoeffsToPair(
(const OMX_U8 **) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[24],
&pPosCoefBuf,
nc,
16);
#endif
if (omxRes != OMX_Sts_NoErr)
return(HANTRO_NOK);
is16x16 = HANTRO_TRUE;
}
else
is16x16 = HANTRO_FALSE;
for (i = 4, blockIndex = 0; i--;)
{
/* luma cbp in bits 0-3 */
blockCoded = codedBlockPattern & 0x1;
codedBlockPattern >>= 1;
if (blockCoded)
{
for (j = 4; j--; blockIndex++)
{
nc = (OMX_INT)DetermineNc(pMb,blockIndex,pResidual->totalCoeff);
if (is16x16)
{
#ifndef H264DEC_NEON
omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC(
(const OMX_U8 **) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[blockIndex],
&pPosCoefBuf,
nc,
15);
#else
omxRes = armVCM4P10_DecodeCoeffsToPair(
(const OMX_U8 **) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[blockIndex],
&pPosCoefBuf,
nc,
15);
#endif
}
else
{
#ifndef H264DEC_NEON
omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC(
(const OMX_U8 **) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[blockIndex],
&pPosCoefBuf,
nc,
16);
#else
omxRes = armVCM4P10_DecodeCoeffsToPair(
(const OMX_U8 **) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[blockIndex],
&pPosCoefBuf,
nc,
16);
#endif
}
if (omxRes != OMX_Sts_NoErr)
return(HANTRO_NOK);
}
}
else
blockIndex += 4;
}
/* chroma DC block are at indices 25 and 26 */
blockCoded = codedBlockPattern & 0x3;
if (blockCoded)
{
#ifndef H264DEC_NEON
omxRes = omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC(
(const OMX_U8**) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[25],
&pPosCoefBuf);
#else
omxRes = armVCM4P10_DecodeCoeffsToPair(
(const OMX_U8**) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[25],
&pPosCoefBuf,
17,
4);
#endif
if (omxRes != OMX_Sts_NoErr)
return(HANTRO_NOK);
#ifndef H264DEC_NEON
omxRes = omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC(
(const OMX_U8**) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[26],
&pPosCoefBuf);
#else
omxRes = armVCM4P10_DecodeCoeffsToPair(
(const OMX_U8**) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[26],
&pPosCoefBuf,
17,
4);
#endif
if (omxRes != OMX_Sts_NoErr)
return(HANTRO_NOK);
}
/* chroma AC */
blockCoded = codedBlockPattern & 0x2;
if (blockCoded)
{
for (i = 8; i--;blockIndex++)
{
nc = (OMX_INT)DetermineNc(pMb, blockIndex, pResidual->totalCoeff);
#ifndef H264DEC_NEON
omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC(
(const OMX_U8 **) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[blockIndex],
&pPosCoefBuf,
nc,
15);
#else
omxRes = armVCM4P10_DecodeCoeffsToPair(
(const OMX_U8 **) (&pStrmData->pStrmCurrPos),
(OMX_S32*) (&pStrmData->bitPosInWord),
&pResidual->totalCoeff[blockIndex],
&pPosCoefBuf,
nc,
15);
#endif
if (omxRes != OMX_Sts_NoErr)
return(HANTRO_NOK);
}
}
return(HANTRO_OK);
}
#else
/*------------------------------------------------------------------------------
Function: DecodeResidual
Functional description:
Parse residual information from bit stream and store in 'pResidual'.
------------------------------------------------------------------------------*/
u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual,
mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern)
{
/* Variables */
u32 i, j, tmp;
i32 nc;
u32 blockCoded;
u32 blockIndex;
u32 is16x16;
i32 (*level)[16];
/* Code */
ASSERT(pStrmData);
ASSERT(pResidual);
level = pResidual->level;
/* luma DC is at index 24 */
if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16)
{
nc = (i32)DetermineNc(pMb, 0, pResidual->totalCoeff);
tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[24], nc, 16);
if ((tmp & 0xF) != HANTRO_OK)
return(tmp);
pResidual->totalCoeff[24] = (tmp >> 4) & 0xFF;
is16x16 = HANTRO_TRUE;
}
else
is16x16 = HANTRO_FALSE;
for (i = 4, blockIndex = 0; i--;)
{
/* luma cbp in bits 0-3 */
blockCoded = codedBlockPattern & 0x1;
codedBlockPattern >>= 1;
if (blockCoded)
{
for (j = 4; j--; blockIndex++)
{
nc = (i32)DetermineNc(pMb, blockIndex, pResidual->totalCoeff);
if (is16x16)
{
tmp = h264bsdDecodeResidualBlockCavlc(pStrmData,
level[blockIndex] + 1, nc, 15);
pResidual->coeffMap[blockIndex] = tmp >> 15;
}
else
{
tmp = h264bsdDecodeResidualBlockCavlc(pStrmData,
level[blockIndex], nc, 16);
pResidual->coeffMap[blockIndex] = tmp >> 16;
}
if ((tmp & 0xF) != HANTRO_OK)
return(tmp);
pResidual->totalCoeff[blockIndex] = (tmp >> 4) & 0xFF;
}
}
else
blockIndex += 4;
}
/* chroma DC block are at indices 25 and 26 */
blockCoded = codedBlockPattern & 0x3;
if (blockCoded)
{
tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[25], -1, 4);
if ((tmp & 0xF) != HANTRO_OK)
return(tmp);
pResidual->totalCoeff[25] = (tmp >> 4) & 0xFF;
tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[25]+4, -1, 4);
if ((tmp & 0xF) != HANTRO_OK)
return(tmp);
pResidual->totalCoeff[26] = (tmp >> 4) & 0xFF;
}
/* chroma AC */
blockCoded = codedBlockPattern & 0x2;
if (blockCoded)
{
for (i = 8; i--;blockIndex++)
{
nc = (i32)DetermineNc(pMb, blockIndex, pResidual->totalCoeff);
tmp = h264bsdDecodeResidualBlockCavlc(pStrmData,
level[blockIndex] + 1, nc, 15);
if ((tmp & 0xF) != HANTRO_OK)
return(tmp);
pResidual->totalCoeff[blockIndex] = (tmp >> 4) & 0xFF;
pResidual->coeffMap[blockIndex] = (tmp >> 15);
}
}
return(HANTRO_OK);
}
#endif
/*------------------------------------------------------------------------------
Function: DetermineNc
Functional description:
Returns the nC of a block.
------------------------------------------------------------------------------*/
#ifdef H264DEC_OMXDL
u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, u8 *pTotalCoeff)
#else
u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, i16 *pTotalCoeff)
#endif
{
/*lint -e702 */
/* Variables */
u32 tmp;
i32 n;
const neighbour_t *neighbourA, *neighbourB;
u8 neighbourAindex, neighbourBindex;
/* Code */
ASSERT(blockIndex < 24);
/* if neighbour block belongs to current macroblock totalCoeff array
* mbStorage has not been set/updated yet -> use pTotalCoeff */
neighbourA = h264bsdNeighbour4x4BlockA(blockIndex);
neighbourB = h264bsdNeighbour4x4BlockB(blockIndex);
neighbourAindex = neighbourA->index;
neighbourBindex = neighbourB->index;
if (neighbourA->mb == MB_CURR && neighbourB->mb == MB_CURR)
{
n = (pTotalCoeff[neighbourAindex] +
pTotalCoeff[neighbourBindex] + 1)>>1;
}
else if (neighbourA->mb == MB_CURR)
{
n = pTotalCoeff[neighbourAindex];
if (h264bsdIsNeighbourAvailable(pMb, pMb->mbB))
{
n = (n + pMb->mbB->totalCoeff[neighbourBindex] + 1) >> 1;
}
}
else if (neighbourB->mb == MB_CURR)
{
n = pTotalCoeff[neighbourBindex];
if (h264bsdIsNeighbourAvailable(pMb, pMb->mbA))
{
n = (n + pMb->mbA->totalCoeff[neighbourAindex] + 1) >> 1;
}
}
else
{
n = tmp = 0;
if (h264bsdIsNeighbourAvailable(pMb, pMb->mbA))
{
n = pMb->mbA->totalCoeff[neighbourAindex];
tmp = 1;
}
if (h264bsdIsNeighbourAvailable(pMb, pMb->mbB))
{
if (tmp)
n = (n + pMb->mbB->totalCoeff[neighbourBindex] + 1) >> 1;
else
n = pMb->mbB->totalCoeff[neighbourBindex];
}
}
return((u32)n);
/*lint +e702 */
}
/*------------------------------------------------------------------------------
Function: CbpIntra16x16
Functional description:
Returns the coded block pattern for intra 16x16 macroblock.
------------------------------------------------------------------------------*/
u32 CbpIntra16x16(mbType_e mbType)
{
/* Variables */
u32 cbp;
u32 tmp;
/* Code */
ASSERT(mbType >= I_16x16_0_0_0 && mbType <= I_16x16_3_2_1);
if (mbType >= I_16x16_0_0_1)
cbp = 15;
else
cbp = 0;
/* tmp is 0 for I_16x16_0_0_0 mb type */
/* ignore lint warning on arithmetic on enum's */
tmp = /*lint -e(656)*/(mbType - I_16x16_0_0_0) >> 2;
if (tmp > 2)
tmp -= 3;
cbp += tmp << 4;
return(cbp);
}
/*------------------------------------------------------------------------------
Function: h264bsdPredModeIntra16x16
Functional description:
Returns the prediction mode for intra 16x16 macroblock.
------------------------------------------------------------------------------*/
u32 h264bsdPredModeIntra16x16(mbType_e mbType)
{
/* Variables */
u32 tmp;
/* Code */
ASSERT(mbType >= I_16x16_0_0_0 && mbType <= I_16x16_3_2_1);
/* tmp is 0 for I_16x16_0_0_0 mb type */
/* ignore lint warning on arithmetic on enum's */
tmp = /*lint -e(656)*/(mbType - I_16x16_0_0_0);
return(tmp & 0x3);
}
/*------------------------------------------------------------------------------
Function: h264bsdDecodeMacroblock
Functional description:
Decode one macroblock and write into output image.
Inputs:
pMb pointer to macroblock specific information
mbLayer pointer to current macroblock data from stream
currImage pointer to output image
dpb pointer to decoded picture buffer
qpY pointer to slice QP
mbNum current macroblock number
constrainedIntraPred flag specifying if neighbouring inter
macroblocks are used in intra prediction
Outputs:
pMb structure is updated with current macroblock
currImage decoded macroblock is written into output image
Returns:
HANTRO_OK success
HANTRO_NOK error in macroblock decoding
------------------------------------------------------------------------------*/
u32 h264bsdDecodeMacroblock(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
image_t *currImage, dpbStorage_t *dpb, i32 *qpY, u32 mbNum,
u32 constrainedIntraPredFlag, u8* data)
{
/* Variables */
u32 i, tmp;
mbType_e mbType;
#ifdef H264DEC_OMXDL
const u8 *pSrc;
#endif
/* Code */
ASSERT(pMb);
ASSERT(pMbLayer);
ASSERT(currImage);
ASSERT(qpY && *qpY < 52);
ASSERT(mbNum < currImage->width*currImage->height);
mbType = pMbLayer->mbType;
pMb->mbType = mbType;
pMb->decoded++;
h264bsdSetCurrImageMbPointers(currImage, mbNum);
if (mbType == I_PCM)
{
u8 *pData = (u8*)data;
#ifdef H264DEC_OMXDL
u8 *tot = pMb->totalCoeff;
#else
i16 *tot = pMb->totalCoeff;
#endif
i32 *lev = pMbLayer->residual.level[0];
pMb->qpY = 0;
/* if decoded flag > 1 -> mb has already been successfully decoded and
* written to output -> do not write again */
if (pMb->decoded > 1)
{
for (i = 24; i--;)
*tot++ = 16;
return HANTRO_OK;
}
for (i = 24; i--;)
{
*tot++ = 16;
for (tmp = 16; tmp--;)
*pData++ = (u8)(*lev++);
}
h264bsdWriteMacroblock(currImage, (u8*)data);
return(HANTRO_OK);
}
else
{
#ifdef H264DEC_OMXDL
if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER)
{
tmp = h264bsdInterPrediction(pMb, pMbLayer, dpb, mbNum,
currImage, (u8*)data);
if (tmp != HANTRO_OK) return (tmp);
}
#endif
if (mbType != P_Skip)
{
H264SwDecMemcpy(pMb->totalCoeff,
pMbLayer->residual.totalCoeff,
27*sizeof(*pMb->totalCoeff));
/* update qpY */
if (pMbLayer->mbQpDelta)
{
*qpY = *qpY + pMbLayer->mbQpDelta;
if (*qpY < 0) *qpY += 52;
else if (*qpY >= 52) *qpY -= 52;
}
pMb->qpY = (u32)*qpY;
#ifdef H264DEC_OMXDL
pSrc = pMbLayer->residual.posCoefBuf;
if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER)
{
OMXResult res;
u8 *p;
u8 *totalCoeff = pMb->totalCoeff;
for (i = 0; i < 16; i++, totalCoeff++)
{
p = data + lumaIndex[i];
if (*totalCoeff)
{
res = omxVCM4P10_DequantTransformResidualFromPairAndAdd(
&pSrc, p, 0, p, 16, 16, *qpY, *totalCoeff);
if (res != OMX_Sts_NoErr)
return (HANTRO_NOK);
}
}
}
else if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA4x4)
{
tmp = ProcessIntra4x4Residual(pMb,
data,
constrainedIntraPredFlag,
pMbLayer,
&pSrc,
currImage);
if (tmp != HANTRO_OK)
return (tmp);
}
else if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16)
{
tmp = ProcessIntra16x16Residual(pMb,
data,
constrainedIntraPredFlag,
pMbLayer->mbPred.intraChromaPredMode,
&pSrc,
currImage);
if (tmp != HANTRO_OK)
return (tmp);
}
tmp = ProcessChromaResidual(pMb, data, &pSrc);
#else
tmp = ProcessResidual(pMb, pMbLayer->residual.level,
pMbLayer->residual.coeffMap);
#endif
if (tmp != HANTRO_OK)
return (tmp);
}
else
{
H264SwDecMemset(pMb->totalCoeff, 0, 27*sizeof(*pMb->totalCoeff));
pMb->qpY = (u32)*qpY;
}
#ifdef H264DEC_OMXDL
/* if decoded flag > 1 -> mb has already been successfully decoded and
* written to output -> do not write again */
if (pMb->decoded > 1)
return HANTRO_OK;
h264bsdWriteMacroblock(currImage, data);
#else
if (h264bsdMbPartPredMode(mbType) != PRED_MODE_INTER)
{
tmp = h264bsdIntraPrediction(pMb, pMbLayer, currImage, mbNum,
constrainedIntraPredFlag, (u8*)data);
if (tmp != HANTRO_OK) return (tmp);
}
else
{
tmp = h264bsdInterPrediction(pMb, pMbLayer, dpb, mbNum,
currImage, (u8*)data);
if (tmp != HANTRO_OK) return (tmp);
}
#endif
}
return HANTRO_OK;
}
#ifdef H264DEC_OMXDL
/*------------------------------------------------------------------------------
Function: ProcessChromaResidual
Functional description:
Process the residual data of chroma with
inverse quantization and inverse transform.
------------------------------------------------------------------------------*/
u32 ProcessChromaResidual(mbStorage_t *pMb, u8 *data, const u8 **pSrc )
{
u32 i;
u32 chromaQp;
i16 *pDc;
i16 dc[4 + 4] = {0,0,0,0,0,0,0,0};
u8 *totalCoeff;
OMXResult result;
u8 *p;
/* chroma DC processing. First chroma dc block is block with index 25 */
chromaQp =
h264bsdQpC[CLIP3(0, 51, (i32)pMb->qpY + pMb->chromaQpIndexOffset)];
if (pMb->totalCoeff[25])
{
pDc = dc;
result = omxVCM4P10_TransformDequantChromaDCFromPair(
pSrc,
pDc,
(i32)chromaQp);
if (result != OMX_Sts_NoErr)
return (HANTRO_NOK);
}
if (pMb->totalCoeff[26])
{
pDc = dc+4;
result = omxVCM4P10_TransformDequantChromaDCFromPair(
pSrc,
pDc,
(i32)chromaQp);
if (result != OMX_Sts_NoErr)
return (HANTRO_NOK);
}
pDc = dc;
totalCoeff = pMb->totalCoeff + 16;
for (i = 0; i < 8; i++, pDc++, totalCoeff++)
{
/* chroma prediction */
if (*totalCoeff || *pDc)
{
p = data + chromaIndex[i];
result = omxVCM4P10_DequantTransformResidualFromPairAndAdd(
pSrc,
p,
pDc,
p,
8,
8,
(i32)chromaQp,
*totalCoeff);
if (result != OMX_Sts_NoErr)
return (HANTRO_NOK);
}
}
return(HANTRO_OK);
}
/*------------------------------------------------------------------------------
Function: ProcessIntra16x16Residual
Functional description:
Process the residual data of luma with
inverse quantization and inverse transform.
------------------------------------------------------------------------------*/
u32 ProcessIntra16x16Residual(mbStorage_t *pMb,
u8 *data,
u32 constrainedIntraPred,
u32 intraChromaPredMode,
const u8** pSrc,
image_t *image)
{
u32 i;
i16 *pDc;
i16 dc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
u8 *totalCoeff;
OMXResult result;
u8 *p;
totalCoeff = pMb->totalCoeff;
if (totalCoeff[24])
{
pDc = dc;
result = omxVCM4P10_TransformDequantLumaDCFromPair(
pSrc,
pDc,
(i32)pMb->qpY);
if (result != OMX_Sts_NoErr)
return (HANTRO_NOK);
}
/* Intra 16x16 pred */
if (h264bsdIntra16x16Prediction(pMb, data, image->luma,
image->width*16, constrainedIntraPred) != HANTRO_OK)
return(HANTRO_NOK);
for (i = 0; i < 16; i++, totalCoeff++)
{
p = data + lumaIndex[i];
pDc = &dc[dcCoeffIndex[i]];
if (*totalCoeff || *pDc)
{
result = omxVCM4P10_DequantTransformResidualFromPairAndAdd(
pSrc,
p,
pDc,
p,
16,
16,
(i32)pMb->qpY,
*totalCoeff);
if (result != OMX_Sts_NoErr)
return (HANTRO_NOK);
}
}
if (h264bsdIntraChromaPrediction(pMb, data + 256,
image,
intraChromaPredMode,
constrainedIntraPred) != HANTRO_OK)
return(HANTRO_NOK);
return HANTRO_OK;
}
/*------------------------------------------------------------------------------
Function: ProcessIntra4x4Residual
Functional description:
Process the residual data of luma with
inverse quantization and inverse transform.
------------------------------------------------------------------------------*/
u32 ProcessIntra4x4Residual(mbStorage_t *pMb,
u8 *data,
u32 constrainedIntraPred,
macroblockLayer_t *mbLayer,
const u8 **pSrc,
image_t *image)
{
u32 i;
u8 *totalCoeff;
OMXResult result;
u8 *p;
totalCoeff = pMb->totalCoeff;
for (i = 0; i < 16; i++, totalCoeff++)
{
p = data + lumaIndex[i];
if (h264bsdIntra4x4Prediction(pMb, p, mbLayer, image->luma,
image->width*16, constrainedIntraPred, i) != HANTRO_OK)
return(HANTRO_NOK);
if (*totalCoeff)
{
result = omxVCM4P10_DequantTransformResidualFromPairAndAdd(
pSrc,
p,
NULL,
p,
16,
16,
(i32)pMb->qpY,
*totalCoeff);
if (result != OMX_Sts_NoErr)
return (HANTRO_NOK);
}
}
if (h264bsdIntraChromaPrediction(pMb, data + 256,
image,
mbLayer->mbPred.intraChromaPredMode,
constrainedIntraPred) != HANTRO_OK)
return(HANTRO_NOK);
return HANTRO_OK;
}
#else /* H264DEC_OMXDL */
/*------------------------------------------------------------------------------
Function: ProcessResidual
Functional description:
Process the residual data of one macroblock with
inverse quantization and inverse transform.
------------------------------------------------------------------------------*/
u32 ProcessResidual(mbStorage_t *pMb, i32 residualLevel[][16], u32 *coeffMap)
{
/* Variables */
u32 i;
u32 chromaQp;
i32 (*blockData)[16];
i32 (*blockDc)[16];
i16 *totalCoeff;
i32 *chromaDc;
const u32 *dcCoeffIdx;
/* Code */
ASSERT(pMb);
ASSERT(residualLevel);
/* set pointers to DC coefficient blocks */
blockDc = residualLevel + 24;
blockData = residualLevel;
totalCoeff = pMb->totalCoeff;
if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA16x16)
{
if (totalCoeff[24])
{
h264bsdProcessLumaDc(*blockDc, pMb->qpY);
}
dcCoeffIdx = dcCoeffIndex;
for (i = 16; i--; blockData++, totalCoeff++, coeffMap++)
{
/* set dc coefficient of luma block */
(*blockData)[0] = (*blockDc)[*dcCoeffIdx++];
if ((*blockData)[0] || *totalCoeff)
{
if (h264bsdProcessBlock(*blockData, pMb->qpY, 1, *coeffMap) !=
HANTRO_OK)
return(HANTRO_NOK);
}
else
MARK_RESIDUAL_EMPTY(*blockData);
}
}
else
{
for (i = 16; i--; blockData++, totalCoeff++, coeffMap++)
{
if (*totalCoeff)
{
if (h264bsdProcessBlock(*blockData, pMb->qpY, 0, *coeffMap) !=
HANTRO_OK)
return(HANTRO_NOK);
}
else
MARK_RESIDUAL_EMPTY(*blockData);
}
}
/* chroma DC processing. First chroma dc block is block with index 25 */
chromaQp =
h264bsdQpC[CLIP3(0, 51, (i32)pMb->qpY + pMb->chromaQpIndexOffset)];
if (pMb->totalCoeff[25] || pMb->totalCoeff[26])
h264bsdProcessChromaDc(residualLevel[25], chromaQp);
chromaDc = residualLevel[25];
for (i = 8; i--; blockData++, totalCoeff++, coeffMap++)
{
/* set dc coefficient of chroma block */
(*blockData)[0] = *chromaDc++;
if ((*blockData)[0] || *totalCoeff)
{
if (h264bsdProcessBlock(*blockData, chromaQp, 1,*coeffMap) !=
HANTRO_OK)
return(HANTRO_NOK);
}
else
MARK_RESIDUAL_EMPTY(*blockData);
}
return(HANTRO_OK);
}
#endif /* H264DEC_OMXDL */
/*------------------------------------------------------------------------------
Function: h264bsdSubMbPartMode
Functional description:
Returns the macroblock's sub-partition mode.
------------------------------------------------------------------------------*/
subMbPartMode_e h264bsdSubMbPartMode(subMbType_e subMbType)
{
/* Variables */
/* Code */
ASSERT(subMbType < 4);
return((subMbPartMode_e)subMbType);
}