#include "codec_def.h"
#include "au_parser.h"
#include "decoder.h"
#include "error_code.h"
#include "memmgr_nal_unit.h"
#include "decoder_core.h"
#include "bit_stream.h"
#include "memory_align.h"
#define _PARSE_NALHRD_VCLHRD_PARAMS_ 1
namespace WelsDec {
uint8_t* DetectStartCodePrefix (const uint8_t* kpBuf, int32_t* pOffset, int32_t iBufSize) {
uint8_t* pBits = (uint8_t*)kpBuf;
do {
int32_t iIdx = 0;
while ((iIdx < iBufSize) && (! (*pBits))) {
++ pBits;
++ iIdx;
}
if (iIdx >= iBufSize) break;
++ iIdx;
++ pBits;
if ((iIdx >= 3) && ((* (pBits - 1)) == 0x1)) {
*pOffset = (int32_t) (((uintptr_t)pBits) - ((uintptr_t)kpBuf));
return pBits;
}
iBufSize -= iIdx;
} while (1);
return NULL;
}
uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeader, uint8_t* pSrcRbsp,
int32_t iSrcRbspLen, uint8_t* pSrcNal, int32_t iSrcNalLen, int32_t* pConsumedBytes) {
PNalUnit pCurNal = NULL;
uint8_t* pNal = pSrcRbsp;
int32_t iNalSize = iSrcRbspLen;
PBitStringAux pBs = NULL;
bool bExtensionFlag = false;
int32_t iErr = ERR_NONE;
int32_t iBitSize = 0;
SDataBuffer* pSavedData = &pCtx->sSavedData;
SLogContext* pLogCtx = & (pCtx->sLogCtx);
pNalUnitHeader->eNalUnitType = NAL_UNIT_UNSPEC_0;
{
int32_t iIndex = iSrcRbspLen - 1;
uint8_t uiBsZero = 0;
while (iIndex >= 0) {
uiBsZero = pSrcRbsp[iIndex];
if (0 == uiBsZero) {
--iNalSize;
++ (*pConsumedBytes);
--iIndex;
} else {
break;
}
}
}
pNalUnitHeader->uiForbiddenZeroBit = (uint8_t) (pNal[0] >> 7); if (pNalUnitHeader->uiForbiddenZeroBit) { pCtx->iErrorCode |= dsBitstreamError;
return NULL; }
pNalUnitHeader->uiNalRefIdc = (uint8_t) (pNal[0] >> 5); pNalUnitHeader->eNalUnitType = (EWelsNalUnitType) (pNal[0] & 0x1f);
++pNal;
--iNalSize;
++ (*pConsumedBytes);
if (! (IS_SEI_NAL (pNalUnitHeader->eNalUnitType) || IS_SPS_NAL (pNalUnitHeader->eNalUnitType)
|| IS_AU_DELIMITER_NAL (pNalUnitHeader->eNalUnitType) || pCtx->sSpsPpsCtx.bSpsExistAheadFlag)) {
if (pCtx->bPrintFrameErrorTraceFlag && pCtx->sSpsPpsCtx.iSpsErrorIgnored == 0) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"parse_nal(), no exist Sequence Parameter Sets ahead of sequence when try to decode NAL(type:%d).",
pNalUnitHeader->eNalUnitType);
} else {
pCtx->sSpsPpsCtx.iSpsErrorIgnored++;
}
pCtx->pDecoderStatistics->iSpsNoExistNalNum++;
pCtx->iErrorCode = dsNoParamSets;
return NULL;
}
pCtx->sSpsPpsCtx.iSpsErrorIgnored = 0;
if (! (IS_SEI_NAL (pNalUnitHeader->eNalUnitType) || IS_PARAM_SETS_NALS (pNalUnitHeader->eNalUnitType)
|| IS_AU_DELIMITER_NAL (pNalUnitHeader->eNalUnitType) || pCtx->sSpsPpsCtx.bPpsExistAheadFlag)) {
if (pCtx->bPrintFrameErrorTraceFlag && pCtx->sSpsPpsCtx.iPpsErrorIgnored == 0) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"parse_nal(), no exist Picture Parameter Sets ahead of sequence when try to decode NAL(type:%d).",
pNalUnitHeader->eNalUnitType);
} else {
pCtx->sSpsPpsCtx.iPpsErrorIgnored++;
}
pCtx->pDecoderStatistics->iPpsNoExistNalNum++;
pCtx->iErrorCode = dsNoParamSets;
return NULL;
}
pCtx->sSpsPpsCtx.iPpsErrorIgnored = 0;
if ((IS_VCL_NAL_AVC_BASE (pNalUnitHeader->eNalUnitType) && ! (pCtx->sSpsPpsCtx.bSpsExistAheadFlag
|| pCtx->sSpsPpsCtx.bPpsExistAheadFlag)) ||
(IS_NEW_INTRODUCED_SVC_NAL (pNalUnitHeader->eNalUnitType) && ! (pCtx->sSpsPpsCtx.bSpsExistAheadFlag
|| pCtx->sSpsPpsCtx.bSubspsExistAheadFlag
|| pCtx->sSpsPpsCtx.bPpsExistAheadFlag))) {
if (pCtx->bPrintFrameErrorTraceFlag && pCtx->sSpsPpsCtx.iSubSpsErrorIgnored == 0) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"ParseNalHeader(), no exist Parameter Sets ahead of sequence when try to decode slice(type:%d).",
pNalUnitHeader->eNalUnitType);
} else {
pCtx->sSpsPpsCtx.iSubSpsErrorIgnored++;
}
pCtx->pDecoderStatistics->iSubSpsNoExistNalNum++;
pCtx->iErrorCode |= dsNoParamSets;
return NULL;
}
pCtx->sSpsPpsCtx.iSubSpsErrorIgnored = 0;
switch (pNalUnitHeader->eNalUnitType) {
case NAL_UNIT_AU_DELIMITER:
case NAL_UNIT_SEI:
if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
pCtx->bAuReadyFlag = true;
}
break;
case NAL_UNIT_PREFIX:
pCurNal = &pCtx->sSpsPpsCtx.sPrefixNal;
pCurNal->uiTimeStamp = pCtx->uiTimeStamp;
if (iNalSize < NAL_UNIT_HEADER_EXT_SIZE) {
PAccessUnit pCurAu = pCtx->pAccessUnitList;
uint32_t uiAvailNalNum = pCurAu->uiAvailUnitsNum;
if (uiAvailNalNum > 0) {
pCurAu->uiEndPos = uiAvailNalNum - 1;
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
pCtx->bAuReadyFlag = true;
}
}
pCurNal->sNalData.sPrefixNal.bPrefixNalCorrectFlag = false;
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
DecodeNalHeaderExt (pCurNal, pNal);
if ((pCurNal->sNalHeaderExt.uiQualityId != 0) || (pCurNal->sNalHeaderExt.bUseRefBasePicFlag != 0)) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"ParseNalHeader() in Prefix Nal Unit:uiQualityId (%d) != 0, bUseRefBasePicFlag (%d) != 0, not supported!",
pCurNal->sNalHeaderExt.uiQualityId, pCurNal->sNalHeaderExt.bUseRefBasePicFlag);
PAccessUnit pCurAu = pCtx->pAccessUnitList;
uint32_t uiAvailNalNum = pCurAu->uiAvailUnitsNum;
if (uiAvailNalNum > 0) {
pCurAu->uiEndPos = uiAvailNalNum - 1;
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
pCtx->bAuReadyFlag = true;
}
}
pCurNal->sNalData.sPrefixNal.bPrefixNalCorrectFlag = false;
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
pNal += NAL_UNIT_HEADER_EXT_SIZE;
iNalSize -= NAL_UNIT_HEADER_EXT_SIZE;
*pConsumedBytes += NAL_UNIT_HEADER_EXT_SIZE;
pCurNal->sNalHeaderExt.sNalUnitHeader.uiForbiddenZeroBit = pNalUnitHeader->uiForbiddenZeroBit;
pCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc = pNalUnitHeader->uiNalRefIdc;
pCurNal->sNalHeaderExt.sNalUnitHeader.eNalUnitType = pNalUnitHeader->eNalUnitType;
if (pNalUnitHeader->uiNalRefIdc != 0) {
pBs = &pCtx->sBs;
iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1);
iErr = DecInitBits (pBs, pNal, iBitSize);
if (iErr) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_PREFIX: DecInitBits() fail due invalid access.");
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
ParsePrefixNalUnit (pCtx, pBs);
}
pCurNal->sNalData.sPrefixNal.bPrefixNalCorrectFlag = true;
break;
case NAL_UNIT_CODED_SLICE_EXT:
bExtensionFlag = true;
case NAL_UNIT_CODED_SLICE:
case NAL_UNIT_CODED_SLICE_IDR: {
PAccessUnit pCurAu = NULL;
uint32_t uiAvailNalNum;
pCurNal = MemGetNextNal (&pCtx->pAccessUnitList, pCtx->pMemAlign);
if (NULL == pCurNal) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "MemGetNextNal() fail due out of memory.");
pCtx->iErrorCode |= dsOutOfMemory;
return NULL;
}
pCurNal->uiTimeStamp = pCtx->uiTimeStamp;
pCurNal->sNalHeaderExt.sNalUnitHeader.uiForbiddenZeroBit = pNalUnitHeader->uiForbiddenZeroBit;
pCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc = pNalUnitHeader->uiNalRefIdc;
pCurNal->sNalHeaderExt.sNalUnitHeader.eNalUnitType = pNalUnitHeader->eNalUnitType;
pCurAu = pCtx->pAccessUnitList;
uiAvailNalNum = pCurAu->uiAvailUnitsNum;
if (pNalUnitHeader->eNalUnitType == NAL_UNIT_CODED_SLICE_EXT) {
if (iNalSize < NAL_UNIT_HEADER_EXT_SIZE) {
ForceClearCurrentNal (pCurAu);
if (uiAvailNalNum > 1) {
pCurAu->uiEndPos = uiAvailNalNum - 2;
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
pCtx->bAuReadyFlag = true;
}
}
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
DecodeNalHeaderExt (pCurNal, pNal);
if (pCurNal->sNalHeaderExt.uiQualityId != 0 ||
pCurNal->sNalHeaderExt.bUseRefBasePicFlag) {
if (pCurNal->sNalHeaderExt.uiQualityId != 0)
WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseNalHeader():uiQualityId (%d) != 0, MGS not supported!",
pCurNal->sNalHeaderExt.uiQualityId);
if (pCurNal->sNalHeaderExt.bUseRefBasePicFlag != 0)
WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseNalHeader():bUseRefBasePicFlag (%d) != 0, MGS not supported!",
pCurNal->sNalHeaderExt.bUseRefBasePicFlag);
ForceClearCurrentNal (pCurAu);
if (uiAvailNalNum > 1) {
pCurAu->uiEndPos = uiAvailNalNum - 2;
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
pCtx->bAuReadyFlag = true;
}
}
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
pNal += NAL_UNIT_HEADER_EXT_SIZE;
iNalSize -= NAL_UNIT_HEADER_EXT_SIZE;
*pConsumedBytes += NAL_UNIT_HEADER_EXT_SIZE;
if (pCtx->pParam->bParseOnly) {
int32_t iTrailingZeroByte = 0;
while (pSrcNal[iSrcNalLen - iTrailingZeroByte - 1] == 0x0) iTrailingZeroByte++;
int32_t iActualLen = iSrcNalLen - iTrailingZeroByte;
int32_t iCurrStartByte = 4; if (pSrcNal[0] == 0x0 && pSrcNal[1] == 0x0 && pSrcNal[2] == 0x1) { iCurrStartByte = 3;
}
int32_t iOffset = iCurrStartByte + 1 + NAL_UNIT_HEADER_EXT_SIZE;
int32_t iWriteLen = 5 + (iActualLen - iOffset); if (pSavedData->pCurPos + iWriteLen > pSavedData->pEnd) {
pSavedData->pCurPos = pSavedData->pHead;
}
pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos;
pCurNal->sNalData.sVclNal.iNalLength = iActualLen - NAL_UNIT_HEADER_EXT_SIZE;
if (iCurrStartByte == 3) {
pCurNal->sNalData.sVclNal.iNalLength++;
}
if (pCurNal->sNalHeaderExt.bIdrFlag) {
* (pSrcNal + iCurrStartByte) &= 0xE0;
* (pSrcNal + iCurrStartByte) |= 0x05;
} else {
* (pSrcNal + iCurrStartByte) &= 0xE0;
* (pSrcNal + iCurrStartByte) |= 0x01;
}
pSavedData->pCurPos[0] = pSavedData->pCurPos[1] = pSavedData->pCurPos[2] = 0x0;
pSavedData->pCurPos[3] = 0x1;
pSavedData->pCurPos[4] = * (pSrcNal + iCurrStartByte);
pSavedData->pCurPos += 5;
memcpy (pSavedData->pCurPos, pSrcNal + iOffset, iActualLen - iOffset);
pSavedData->pCurPos += iActualLen - iOffset;
}
} else {
if (pCtx->pParam->bParseOnly) {
int32_t iTrailingZeroByte = 0;
while (pSrcNal[iSrcNalLen - iTrailingZeroByte - 1] == 0x0) iTrailingZeroByte++;
int32_t iActualLen = iSrcNalLen - iTrailingZeroByte;
int32_t iStartDeltaByte = 0; if (pSrcNal[0] == 0x0 && pSrcNal[1] == 0x0 && pSrcNal[2] == 0x1) { iStartDeltaByte = 1;
}
int32_t iWriteLen = iStartDeltaByte + iActualLen;
if (pSavedData->pCurPos + iWriteLen > pSavedData->pEnd) {
pSavedData->pCurPos = pSavedData->pHead;
}
pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos;
pCurNal->sNalData.sVclNal.iNalLength = iActualLen;
if (iStartDeltaByte) {
pSavedData->pCurPos[0] = 0x0;
pCurNal->sNalData.sVclNal.iNalLength++;
}
memcpy (pSavedData->pCurPos + iStartDeltaByte, pSrcNal, iActualLen);
pSavedData->pCurPos += iStartDeltaByte + iActualLen;
}
if (NAL_UNIT_PREFIX == pCtx->sSpsPpsCtx.sPrefixNal.sNalHeaderExt.sNalUnitHeader.eNalUnitType) {
if (pCtx->sSpsPpsCtx.sPrefixNal.sNalData.sPrefixNal.bPrefixNalCorrectFlag) {
PrefetchNalHeaderExtSyntax (pCtx, pCurNal, &pCtx->sSpsPpsCtx.sPrefixNal);
}
}
pCurNal->sNalHeaderExt.bIdrFlag = (NAL_UNIT_CODED_SLICE_IDR == pNalUnitHeader->eNalUnitType) ? true :
false; pCurNal->sNalHeaderExt.iNoInterLayerPredFlag = 1;
}
pBs = &pCurAu->pNalUnitsList[uiAvailNalNum - 1]->sNalData.sVclNal.sSliceBitsRead;
iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); iErr = DecInitBits (pBs, pNal, iBitSize);
if (iErr) {
ForceClearCurrentNal (pCurAu);
if (uiAvailNalNum > 1) {
pCurAu->uiEndPos = uiAvailNalNum - 2;
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
pCtx->bAuReadyFlag = true;
}
}
WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_CODED_SLICE: DecInitBits() fail due invalid access.");
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
iErr = ParseSliceHeaderSyntaxs (pCtx, pBs, bExtensionFlag);
if (iErr != ERR_NONE) {
if ((uiAvailNalNum == 1) && (pCurNal->sNalHeaderExt.bIdrFlag)) { ResetActiveSPSForEachLayer (pCtx);
}
ForceClearCurrentNal (pCurAu);
if (uiAvailNalNum > 1) {
pCurAu->uiEndPos = uiAvailNalNum - 2;
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE) {
pCtx->bAuReadyFlag = true;
}
}
pCtx->iErrorCode |= dsBitstreamError;
return NULL;
}
if ((uiAvailNalNum == 1)
&& CheckNextAuNewSeq (pCtx, pCurNal, pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps)) {
ResetActiveSPSForEachLayer (pCtx);
}
if ((uiAvailNalNum > 1) &&
CheckAccessUnitBoundary (pCtx, pCurAu->pNalUnitsList[uiAvailNalNum - 1], pCurAu->pNalUnitsList[uiAvailNalNum - 2],
pCurAu->pNalUnitsList[uiAvailNalNum - 1]->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps)) {
pCurAu->uiEndPos = uiAvailNalNum - 2;
pCtx->bAuReadyFlag = true;
pCtx->bNextNewSeqBegin = CheckNextAuNewSeq (pCtx, pCurNal, pCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps);
}
}
break;
default:
break;
}
return pNal;
}
bool CheckAccessUnitBoundaryExt (PNalUnitHeaderExt pLastNalHdrExt, PNalUnitHeaderExt pCurNalHeaderExt,
PSliceHeader pLastSliceHeader, PSliceHeader pCurSliceHeader) {
const PSps kpSps = pCurSliceHeader->pSps;
if (pLastNalHdrExt->uiTemporalId != pCurNalHeaderExt->uiTemporalId) {
return true;
}
if (pLastSliceHeader->iRedundantPicCnt > pCurSliceHeader->iRedundantPicCnt)
return true;
if (pLastNalHdrExt->uiDependencyId > pCurNalHeaderExt->uiDependencyId)
return true;
if (pLastNalHdrExt->uiQualityId > pCurNalHeaderExt->uiQualityId)
return true;
if (pLastSliceHeader->iFrameNum != pCurSliceHeader->iFrameNum)
return true;
if (pLastSliceHeader->iPpsId != pCurSliceHeader->iPpsId)
return true;
if (pLastSliceHeader->pSps->iSpsId != pCurSliceHeader->pSps->iSpsId)
return true;
if (pLastSliceHeader->bFieldPicFlag != pCurSliceHeader->bFieldPicFlag)
return true;
if (pLastSliceHeader->bBottomFiledFlag != pCurSliceHeader->bBottomFiledFlag)
return true;
if ((pLastNalHdrExt->sNalUnitHeader.uiNalRefIdc != NRI_PRI_LOWEST) != (pCurNalHeaderExt->sNalUnitHeader.uiNalRefIdc !=
NRI_PRI_LOWEST))
return true;
if (pLastNalHdrExt->bIdrFlag != pCurNalHeaderExt->bIdrFlag)
return true;
if (pCurNalHeaderExt->bIdrFlag) {
if (pLastSliceHeader->uiIdrPicId != pCurSliceHeader->uiIdrPicId)
return true;
}
if (kpSps->uiPocType == 0) {
if (pLastSliceHeader->iPicOrderCntLsb != pCurSliceHeader->iPicOrderCntLsb)
return true;
if (pLastSliceHeader->iDeltaPicOrderCntBottom != pCurSliceHeader->iDeltaPicOrderCntBottom)
return true;
} else if (kpSps->uiPocType == 1) {
if (pLastSliceHeader->iDeltaPicOrderCnt[0] != pCurSliceHeader->iDeltaPicOrderCnt[0])
return true;
if (pLastSliceHeader->iDeltaPicOrderCnt[1] != pCurSliceHeader->iDeltaPicOrderCnt[1])
return true;
}
if (memcmp (pLastSliceHeader->pPps, pCurSliceHeader->pPps, sizeof (SPps)) != 0
|| memcmp (pLastSliceHeader->pSps, pCurSliceHeader->pSps, sizeof (SSps)) != 0) {
return true;
}
return false;
}
bool CheckAccessUnitBoundary (PWelsDecoderContext pCtx, const PNalUnit kpCurNal, const PNalUnit kpLastNal,
const PSps kpSps) {
const PNalUnitHeaderExt kpLastNalHeaderExt = &kpLastNal->sNalHeaderExt;
const PNalUnitHeaderExt kpCurNalHeaderExt = &kpCurNal->sNalHeaderExt;
const SSliceHeader* kpLastSliceHeader = &kpLastNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader;
const SSliceHeader* kpCurSliceHeader = &kpCurNal->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader;
if (pCtx->sSpsPpsCtx.pActiveLayerSps[kpCurNalHeaderExt->uiDependencyId] != NULL
&& pCtx->sSpsPpsCtx.pActiveLayerSps[kpCurNalHeaderExt->uiDependencyId] != kpSps) {
return true; }
if (kpLastNalHeaderExt->uiTemporalId != kpCurNalHeaderExt->uiTemporalId) {
return true;
}
if (kpLastSliceHeader->iFrameNum != kpCurSliceHeader->iFrameNum)
return true;
if (kpLastSliceHeader->iRedundantPicCnt > kpCurSliceHeader->iRedundantPicCnt)
return true;
if (kpLastNalHeaderExt->uiDependencyId > kpCurNalHeaderExt->uiDependencyId)
return true;
if (kpLastNalHeaderExt->uiDependencyId == kpCurNalHeaderExt->uiDependencyId
&& kpLastSliceHeader->iPpsId != kpCurSliceHeader->iPpsId)
return true;
if (kpLastSliceHeader->bFieldPicFlag != kpCurSliceHeader->bFieldPicFlag)
return true;
if (kpLastSliceHeader->bBottomFiledFlag != kpCurSliceHeader->bBottomFiledFlag)
return true;
if ((kpLastNalHeaderExt->sNalUnitHeader.uiNalRefIdc != NRI_PRI_LOWEST) != (kpCurNalHeaderExt->sNalUnitHeader.uiNalRefIdc
!= NRI_PRI_LOWEST))
return true;
if (kpLastNalHeaderExt->bIdrFlag != kpCurNalHeaderExt->bIdrFlag)
return true;
if (kpCurNalHeaderExt->bIdrFlag) {
if (kpLastSliceHeader->uiIdrPicId != kpCurSliceHeader->uiIdrPicId)
return true;
}
if (kpSps->uiPocType == 0) {
if (kpLastSliceHeader->iPicOrderCntLsb != kpCurSliceHeader->iPicOrderCntLsb)
return true;
if (kpLastSliceHeader->iDeltaPicOrderCntBottom != kpCurSliceHeader->iDeltaPicOrderCntBottom)
return true;
} else if (kpSps->uiPocType == 1) {
if (kpLastSliceHeader->iDeltaPicOrderCnt[0] != kpCurSliceHeader->iDeltaPicOrderCnt[0])
return true;
if (kpLastSliceHeader->iDeltaPicOrderCnt[1] != kpCurSliceHeader->iDeltaPicOrderCnt[1])
return true;
}
return false;
}
bool CheckNextAuNewSeq (PWelsDecoderContext pCtx, const PNalUnit kpCurNal, const PSps kpSps) {
const PNalUnitHeaderExt kpCurNalHeaderExt = &kpCurNal->sNalHeaderExt;
if (pCtx->sSpsPpsCtx.pActiveLayerSps[kpCurNalHeaderExt->uiDependencyId] != NULL
&& pCtx->sSpsPpsCtx.pActiveLayerSps[kpCurNalHeaderExt->uiDependencyId] != kpSps)
return true;
if (kpCurNalHeaderExt->bIdrFlag)
return true;
return false;
}
int32_t ParseNonVclNal (PWelsDecoderContext pCtx, uint8_t* pRbsp, const int32_t kiSrcLen, uint8_t* pSrcNal,
const int32_t kSrcNalLen) {
PBitStringAux pBs = NULL;
EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0; int32_t iPicWidth = 0;
int32_t iPicHeight = 0;
int32_t iBitSize = 0;
int32_t iErr = ERR_NONE;
if (kiSrcLen <= 0)
return iErr;
pBs = &pCtx->sBs; iBitSize = (kiSrcLen << 3) - BsGetTrailingBits (pRbsp + kiSrcLen - 1); eNalType = pCtx->sCurNalHead.eNalUnitType;
switch (eNalType) {
case NAL_UNIT_SPS:
case NAL_UNIT_SUBSET_SPS:
if (iBitSize > 0) {
iErr = DecInitBits (pBs, pRbsp, iBitSize);
if (ERR_NONE != iErr) {
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
else
pCtx->iErrorCode |= dsBitstreamError;
return iErr;
}
}
iErr = ParseSps (pCtx, pBs, &iPicWidth, &iPicHeight, pSrcNal, kSrcNalLen);
if (ERR_NONE != iErr) { if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
else
pCtx->iErrorCode |= dsBitstreamError;
return iErr;
}
pCtx->bHasNewSps = true;
break;
case NAL_UNIT_PPS:
if (iBitSize > 0) {
iErr = DecInitBits (pBs, pRbsp, iBitSize);
if (ERR_NONE != iErr) {
if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
else
pCtx->iErrorCode |= dsBitstreamError;
return iErr;
}
}
iErr = ParsePps (pCtx, &pCtx->sSpsPpsCtx.sPpsBuffer[0], pBs, pSrcNal, kSrcNalLen);
if (ERR_NONE != iErr) { if (pCtx->pParam->eEcActiveIdc == ERROR_CON_DISABLE)
pCtx->iErrorCode |= dsNoParamSets;
else
pCtx->iErrorCode |= dsBitstreamError;
pCtx->bHasNewSps = false;
return iErr;
}
pCtx->sSpsPpsCtx.bPpsExistAheadFlag = true;
++ (pCtx->sSpsPpsCtx.iSeqId);
break;
case NAL_UNIT_SEI:
break;
case NAL_UNIT_PREFIX:
break;
case NAL_UNIT_CODED_SLICE_DPA:
case NAL_UNIT_CODED_SLICE_DPB:
case NAL_UNIT_CODED_SLICE_DPC:
break;
default:
break;
}
return iErr;
}
int32_t ParseRefBasePicMarking (PBitStringAux pBs, PRefBasePicMarking pRefBasePicMarking) {
uint32_t uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); const bool kbAdaptiveMarkingModeFlag = !!uiCode;
pRefBasePicMarking->bAdaptiveRefBasePicMarkingModeFlag = kbAdaptiveMarkingModeFlag;
if (kbAdaptiveMarkingModeFlag) {
int32_t iIdx = 0;
do {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); const uint32_t kuiMmco = uiCode;
pRefBasePicMarking->mmco_base[iIdx].uiMmcoType = kuiMmco;
if (kuiMmco == MMCO_END)
break;
if (kuiMmco == MMCO_SHORT2UNUSED) {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pRefBasePicMarking->mmco_base[iIdx].uiDiffOfPicNums = 1 + uiCode;
pRefBasePicMarking->mmco_base[iIdx].iShortFrameNum = 0;
} else if (kuiMmco == MMCO_LONG2UNUSED) {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pRefBasePicMarking->mmco_base[iIdx].uiLongTermPicNum = uiCode;
}
++ iIdx;
} while (iIdx < MAX_MMCO_COUNT);
}
return ERR_NONE;
}
int32_t ParsePrefixNalUnit (PWelsDecoderContext pCtx, PBitStringAux pBs) {
PNalUnit pCurNal = &pCtx->sSpsPpsCtx.sPrefixNal;
uint32_t uiCode;
if (pCurNal->sNalHeaderExt.sNalUnitHeader.uiNalRefIdc != 0) {
PNalUnitHeaderExt head_ext = &pCurNal->sNalHeaderExt;
PPrefixNalUnit sPrefixNal = &pCurNal->sNalData.sPrefixNal;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); sPrefixNal->bStoreRefBasePicFlag = !!uiCode;
if ((head_ext->bUseRefBasePicFlag || sPrefixNal->bStoreRefBasePicFlag) && !head_ext->bIdrFlag) {
WELS_READ_VERIFY (ParseRefBasePicMarking (pBs, &sPrefixNal->sRefPicBaseMarking));
}
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); sPrefixNal->bPrefixNalUnitAdditionalExtFlag = !!uiCode;
if (sPrefixNal->bPrefixNalUnitAdditionalExtFlag) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); sPrefixNal->bPrefixNalUnitExtFlag = !!uiCode;
}
}
return ERR_NONE;
}
#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_LEFT_OFFSET_MIN -32768
#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_LEFT_OFFSET_MAX 32767
#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_TOP_OFFSET_MIN -32768
#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_TOP_OFFSET_MAX 32767
#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_RIGHT_OFFSET_MIN -32768
#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_RIGHT_OFFSET_MAX 32767
#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_BOTTOM_OFFSET_MIN -32768
#define SUBSET_SPS_SEQ_SCALED_REF_LAYER_BOTTOM_OFFSET_MAX 32767
int32_t DecodeSpsSvcExt (PWelsDecoderContext pCtx, PSubsetSps pSpsExt, PBitStringAux pBs) {
PSpsSvcExt pExt = NULL;
uint32_t uiCode;
int32_t iCode;
pExt = &pSpsExt->sSpsSvcExt;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pExt->bInterLayerDeblockingFilterCtrlPresentFlag = !!uiCode;
WELS_READ_VERIFY (BsGetBits (pBs, 2, &uiCode)); pExt->uiExtendedSpatialScalability = uiCode;
if (pExt->uiExtendedSpatialScalability > 2) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"DecodeSpsSvcExt():extended_spatial_scalability (%d) != 0, ESS not supported!",
pExt->uiExtendedSpatialScalability);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_ESS);
}
pExt->uiChromaPhaseXPlus1Flag =
0; pExt->uiChromaPhaseYPlus1 = 1;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pExt->uiChromaPhaseXPlus1Flag = uiCode;
WELS_READ_VERIFY (BsGetBits (pBs, 2, &uiCode)); pExt->uiChromaPhaseYPlus1 = uiCode;
pExt->uiSeqRefLayerChromaPhaseXPlus1Flag = pExt->uiChromaPhaseXPlus1Flag;
pExt->uiSeqRefLayerChromaPhaseYPlus1 = pExt->uiChromaPhaseYPlus1;
memset (&pExt->sSeqScaledRefLayer, 0, sizeof (SPosOffset));
if (pExt->uiExtendedSpatialScalability == 1) {
SPosOffset* const kpPos = &pExt->sSeqScaledRefLayer;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pExt->uiSeqRefLayerChromaPhaseXPlus1Flag = uiCode;
WELS_READ_VERIFY (BsGetBits (pBs, 2, &uiCode)); pExt->uiSeqRefLayerChromaPhaseYPlus1 = uiCode;
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); kpPos->iLeftOffset = iCode;
WELS_CHECK_SE_BOTH_WARNING (kpPos->iLeftOffset, SUBSET_SPS_SEQ_SCALED_REF_LAYER_LEFT_OFFSET_MIN,
SUBSET_SPS_SEQ_SCALED_REF_LAYER_LEFT_OFFSET_MAX, "seq_scaled_ref_layer_left_offset");
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); kpPos->iTopOffset = iCode;
WELS_CHECK_SE_BOTH_WARNING (kpPos->iTopOffset, SUBSET_SPS_SEQ_SCALED_REF_LAYER_TOP_OFFSET_MIN,
SUBSET_SPS_SEQ_SCALED_REF_LAYER_TOP_OFFSET_MAX, "seq_scaled_ref_layer_top_offset");
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); kpPos->iRightOffset = iCode;
WELS_CHECK_SE_BOTH_WARNING (kpPos->iRightOffset, SUBSET_SPS_SEQ_SCALED_REF_LAYER_RIGHT_OFFSET_MIN,
SUBSET_SPS_SEQ_SCALED_REF_LAYER_RIGHT_OFFSET_MAX, "seq_scaled_ref_layer_right_offset");
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); kpPos->iBottomOffset = iCode;
WELS_CHECK_SE_BOTH_WARNING (kpPos->iBottomOffset, SUBSET_SPS_SEQ_SCALED_REF_LAYER_BOTTOM_OFFSET_MIN,
SUBSET_SPS_SEQ_SCALED_REF_LAYER_BOTTOM_OFFSET_MAX, "seq_scaled_ref_layer_bottom_offset");
}
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pExt->bSeqTCoeffLevelPredFlag = !!uiCode;
pExt->bAdaptiveTCoeffLevelPredFlag = false;
if (pExt->bSeqTCoeffLevelPredFlag) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pExt->bAdaptiveTCoeffLevelPredFlag = !!uiCode;
}
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pExt->bSliceHeaderRestrictionFlag = !!uiCode;
return ERR_NONE;
}
const SLevelLimits* GetLevelLimits (int32_t iLevelIdx, bool bConstraint3) {
switch (iLevelIdx) {
case 9:
return &g_ksLevelLimits[1];
case 10:
return &g_ksLevelLimits[0];
case 11:
if (bConstraint3)
return &g_ksLevelLimits[1];
else
return &g_ksLevelLimits[2];
case 12:
return &g_ksLevelLimits[3];
case 13:
return &g_ksLevelLimits[4];
case 20:
return &g_ksLevelLimits[5];
case 21:
return &g_ksLevelLimits[6];
case 22:
return &g_ksLevelLimits[7];
case 30:
return &g_ksLevelLimits[8];
case 31:
return &g_ksLevelLimits[9];
case 32:
return &g_ksLevelLimits[10];
case 40:
return &g_ksLevelLimits[11];
case 41:
return &g_ksLevelLimits[12];
case 42:
return &g_ksLevelLimits[13];
case 50:
return &g_ksLevelLimits[14];
case 51:
return &g_ksLevelLimits[15];
case 52:
return &g_ksLevelLimits[16];
default:
return NULL;
}
return NULL;
}
bool CheckSpsActive (PWelsDecoderContext pCtx, PSps pSps, bool bUseSubsetFlag) {
for (int i = 0; i < MAX_LAYER_NUM; i++) {
if (pCtx->sSpsPpsCtx.pActiveLayerSps[i] == pSps)
return true;
}
if (bUseSubsetFlag) {
if (pSps->iMbWidth > 0 && pSps->iMbHeight > 0 && pCtx->sSpsPpsCtx.bSubspsAvailFlags[pSps->iSpsId]) {
if (pCtx->iTotalNumMbRec > 0) {
return true;
}
if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
int i = 0, iNum = (int32_t) pCtx->pAccessUnitList->uiAvailUnitsNum;
while (i < iNum) {
PNalUnit pNalUnit = pCtx->pAccessUnitList->pNalUnitsList[i];
if (pNalUnit->sNalData.sVclNal.bSliceHeaderExtFlag) { PSps pNextUsedSps = pNalUnit->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
if (pNextUsedSps->iSpsId == pSps->iSpsId)
return true;
}
++i;
}
}
}
} else {
if (pSps->iMbWidth > 0 && pSps->iMbHeight > 0 && pCtx->sSpsPpsCtx.bSpsAvailFlags[pSps->iSpsId]) {
if (pCtx->iTotalNumMbRec > 0) {
return true;
}
if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
int i = 0, iNum = (int32_t) pCtx->pAccessUnitList->uiAvailUnitsNum;
while (i < iNum) {
PNalUnit pNalUnit = pCtx->pAccessUnitList->pNalUnitsList[i];
if (!pNalUnit->sNalData.sVclNal.bSliceHeaderExtFlag) { PSps pNextUsedSps = pNalUnit->sNalData.sVclNal.sSliceHeaderExt.sSliceHeader.pSps;
if (pNextUsedSps->iSpsId == pSps->iSpsId)
return true;
}
++i;
}
}
}
}
return false;
}
#define SPS_LOG2_MAX_FRAME_NUM_MINUS4_MAX 12
#define SPS_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4_MAX 12
#define SPS_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE_MAX 255
#define SPS_MAX_NUM_REF_FRAMES_MAX 16
#define PPS_PIC_INIT_QP_QS_MIN 0
#define PPS_PIC_INIT_QP_QS_MAX 51
#define PPS_CHROMA_QP_INDEX_OFFSET_MIN -12
#define PPS_CHROMA_QP_INDEX_OFFSET_MAX 12
#define SCALING_LIST_DELTA_SCALE_MAX 127
#define SCALING_LIST_DELTA_SCALE_MIN -128
int32_t ParseSps (PWelsDecoderContext pCtx, PBitStringAux pBsAux, int32_t* pPicWidth, int32_t* pPicHeight,
uint8_t* pSrcNal, const int32_t kSrcNalLen) {
PBitStringAux pBs = pBsAux;
SSubsetSps sTempSubsetSps;
PSps pSps = NULL;
PSubsetSps pSubsetSps = NULL;
SNalUnitHeader* pNalHead = &pCtx->sCurNalHead;
ProfileIdc uiProfileIdc;
uint8_t uiLevelIdc;
int32_t iSpsId;
uint32_t uiCode;
int32_t iCode;
int32_t iRet = ERR_NONE;
bool bConstraintSetFlags[6] = { false };
const bool kbUseSubsetFlag = IS_SUBSET_SPS_NAL (pNalHead->eNalUnitType);
WELS_READ_VERIFY (BsGetBits (pBs, 8, &uiCode)); uiProfileIdc = uiCode;
if (uiProfileIdc != PRO_BASELINE && uiProfileIdc != PRO_MAIN && uiProfileIdc != PRO_SCALABLE_BASELINE
&& uiProfileIdc != PRO_SCALABLE_HIGH
&& uiProfileIdc != PRO_EXTENDED && uiProfileIdc != PRO_HIGH) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "SPS ID can not be supported!\n");
return false;
}
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); bConstraintSetFlags[0] = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); bConstraintSetFlags[1] = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); bConstraintSetFlags[2] = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); bConstraintSetFlags[3] = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); bConstraintSetFlags[4] = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); bConstraintSetFlags[5] = !!uiCode;
WELS_READ_VERIFY (BsGetBits (pBs, 2, &uiCode)); WELS_READ_VERIFY (BsGetBits (pBs, 8, &uiCode)); uiLevelIdc = uiCode;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); if (uiCode >= MAX_SPS_COUNT) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, " iSpsId is out of range! \n");
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_SPS_ID_OVERFLOW);
}
iSpsId = uiCode;
pSubsetSps = &sTempSubsetSps;
pSps = &sTempSubsetSps.sSps;
memset (pSubsetSps, 0, sizeof (SSubsetSps));
const SLevelLimits* pSMaxLevelLimits = GetLevelLimits (52, false);
const SLevelLimits* pSLevelLimits = GetLevelLimits (uiLevelIdc, bConstraintSetFlags[3]);
if (NULL == pSLevelLimits) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "ParseSps(): level_idx (%d).\n", uiLevelIdc);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_NON_BASELINE);
} else pSps->pSLevelLimits = pSLevelLimits;
pSps->uiChromaFormatIdc = 1;
pSps->uiChromaArrayType = 1;
pSps->uiProfileIdc = uiProfileIdc;
pSps->uiLevelIdc = uiLevelIdc;
pSps->iSpsId = iSpsId;
if (PRO_SCALABLE_BASELINE == uiProfileIdc || PRO_SCALABLE_HIGH == uiProfileIdc ||
PRO_HIGH == uiProfileIdc || PRO_HIGH10 == uiProfileIdc ||
PRO_HIGH422 == uiProfileIdc || PRO_HIGH444 == uiProfileIdc ||
PRO_CAVLC444 == uiProfileIdc || 44 == uiProfileIdc) {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->uiChromaFormatIdc = uiCode;
if (pSps->uiChromaFormatIdc > 1) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "ParseSps(): chroma_format_idc (%d) <=1 supported.",
pSps->uiChromaFormatIdc);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_NON_BASELINE);
} pSps->uiChromaArrayType = pSps->uiChromaFormatIdc;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); if (uiCode != 0) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "ParseSps(): bit_depth_luma (%d) Only 8 bit supported.", 8 + uiCode);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_NON_BASELINE);
}
pSps->uiBitDepthLuma = 8;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); if (uiCode != 0) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "ParseSps(): bit_depth_chroma (%d). Only 8 bit supported.", 8 + uiCode);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_NON_BASELINE);
}
pSps->uiBitDepthChroma = 8;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSps->bQpPrimeYZeroTransfBypassFlag = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSps->bSeqScalingMatrixPresentFlag = !!uiCode;
if (pSps->bSeqScalingMatrixPresentFlag) {
WELS_READ_VERIFY (ParseScalingList (pSps, pBs, 0, 0, pSps->bSeqScalingListPresentFlag, pSps->iScalingList4x4,
pSps->iScalingList8x8));
}
}
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); WELS_CHECK_SE_UPPER_ERROR (uiCode, SPS_LOG2_MAX_FRAME_NUM_MINUS4_MAX, "log2_max_frame_num_minus4",
GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_LOG2_MAX_FRAME_NUM_MINUS4));
pSps->uiLog2MaxFrameNum = LOG2_MAX_FRAME_NUM_OFFSET + uiCode;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->uiPocType = uiCode;
if (0 == pSps->uiPocType) {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); WELS_CHECK_SE_UPPER_ERROR (uiCode, SPS_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4_MAX, "log2_max_pic_order_cnt_lsb_minus4",
GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4));
pSps->iLog2MaxPocLsb = LOG2_MAX_PIC_ORDER_CNT_LSB_OFFSET + uiCode;
} else if (1 == pSps->uiPocType) {
int32_t i;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSps->bDeltaPicOrderAlwaysZeroFlag = !!uiCode;
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); pSps->iOffsetForNonRefPic = iCode;
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); pSps->iOffsetForTopToBottomField = iCode;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); WELS_CHECK_SE_UPPER_ERROR (uiCode, SPS_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE_MAX,
"num_ref_frames_in_pic_order_cnt_cycle", GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS,
ERR_INFO_INVALID_NUM_REF_FRAME_IN_PIC_ORDER_CNT_CYCLE));
pSps->iNumRefFramesInPocCycle = uiCode;
for (i = 0; i < pSps->iNumRefFramesInPocCycle; i++) {
WELS_READ_VERIFY (BsGetSe (pBs, &iCode)); pSps->iOffsetForRefFrame[ i ] = iCode;
}
}
if (pSps->uiPocType > 2) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, " illegal pic_order_cnt_type: %d ! ", pSps->uiPocType);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_POC_TYPE);
}
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->iNumRefFrames = uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSps->bGapsInFrameNumValueAllowedFlag = !!uiCode;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->iMbWidth = PIC_WIDTH_IN_MBS_OFFSET + uiCode;
if (pSps->iMbWidth > MAX_MB_SIZE || pSps->iMbWidth == 0) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "pic_width_in_mbs(%d) invalid!", pSps->iMbWidth);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_MB_SIZE);
}
if (((uint64_t)pSps->iMbWidth * (uint64_t)pSps->iMbWidth) > (uint64_t) (8 * pSLevelLimits->uiMaxFS)) {
if (((uint64_t)pSps->iMbWidth * (uint64_t)pSps->iMbWidth) > (uint64_t) (8 * pSMaxLevelLimits->uiMaxFS)) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "the pic_width_in_mbs exceeds the level limits!");
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_MB_SIZE);
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "the pic_width_in_mbs exceeds the level limits!");
}
}
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->iMbHeight = PIC_HEIGHT_IN_MAP_UNITS_OFFSET + uiCode;
if (pSps->iMbHeight > MAX_MB_SIZE || pSps->iMbHeight == 0) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "pic_height_in_mbs(%d) invalid!", pSps->iMbHeight);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_MB_SIZE);
}
if (((uint64_t)pSps->iMbHeight * (uint64_t)pSps->iMbHeight) > (uint64_t) (8 * pSLevelLimits->uiMaxFS)) {
if (((uint64_t)pSps->iMbHeight * (uint64_t)pSps->iMbHeight) > (uint64_t) (8 * pSMaxLevelLimits->uiMaxFS)) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "the pic_height_in_mbs exceeds the level limits!");
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_MB_SIZE);
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "the pic_height_in_mbs exceeds the level limits!");
}
}
uint64_t uiTmp64 = (uint64_t)pSps->iMbWidth * (uint64_t)pSps->iMbHeight;
if (uiTmp64 > (uint64_t)pSLevelLimits->uiMaxFS) {
if (uiTmp64 > (uint64_t)pSMaxLevelLimits->uiMaxFS) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "the total count of mb exceeds the level limits!");
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_MB_SIZE);
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "the total count of mb exceeds the level limits!");
}
}
pSps->uiTotalMbCount = (uint32_t)uiTmp64;
WELS_CHECK_SE_UPPER_ERROR (pSps->iNumRefFrames, SPS_MAX_NUM_REF_FRAMES_MAX, "max_num_ref_frames",
GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_MAX_NUM_REF_FRAMES));
uint32_t uiMaxDpbMbs = pSLevelLimits->uiMaxDPBMbs;
uint32_t uiMaxDpbFrames = uiMaxDpbMbs / pSps->uiTotalMbCount;
if (uiMaxDpbFrames > SPS_MAX_NUM_REF_FRAMES_MAX)
uiMaxDpbFrames = SPS_MAX_NUM_REF_FRAMES_MAX;
if ((uint32_t)pSps->iNumRefFrames > uiMaxDpbFrames) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, " max_num_ref_frames exceeds level limits!");
}
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSps->bFrameMbsOnlyFlag = !!uiCode;
if (!pSps->bFrameMbsOnlyFlag) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "ParseSps(): frame_mbs_only_flag (%d) not supported.",
pSps->bFrameMbsOnlyFlag);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_MBAFF);
}
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSps->bDirect8x8InferenceFlag = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSps->bFrameCroppingFlag = !!uiCode;
if (pSps->bFrameCroppingFlag) {
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->sFrameCrop.iLeftOffset = uiCode;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->sFrameCrop.iRightOffset = uiCode;
if ((pSps->sFrameCrop.iLeftOffset + pSps->sFrameCrop.iRightOffset) > ((int32_t)pSps->iMbWidth * 16 / 2)) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "frame_crop_left_offset + frame_crop_right_offset exceeds limits!");
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_CROPPING_DATA);
}
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->sFrameCrop.iTopOffset = uiCode;
WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); pSps->sFrameCrop.iBottomOffset = uiCode;
if ((pSps->sFrameCrop.iTopOffset + pSps->sFrameCrop.iBottomOffset) > ((int32_t)pSps->iMbHeight * 16 / 2)) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "frame_crop_top_offset + frame_crop_right_offset exceeds limits!");
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_CROPPING_DATA);
}
} else {
pSps->sFrameCrop.iLeftOffset = 0; pSps->sFrameCrop.iRightOffset = 0; pSps->sFrameCrop.iTopOffset = 0; pSps->sFrameCrop.iBottomOffset = 0; }
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSps->bVuiParamPresentFlag = !!uiCode;
if (pSps->bVuiParamPresentFlag) {
int iRetVui = ParseVui (pCtx, pSps, pBsAux);
if (iRetVui == GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_VUI_HRD)) {
if (kbUseSubsetFlag) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "hrd parse in vui of subsetSPS is not supported!");
return iRetVui;
}
} else {
WELS_READ_VERIFY (iRetVui);
}
}
if (pCtx->pParam->bParseOnly) {
if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "sps payload size (%d) too large for parse only (%d), not supported!",
kSrcNalLen, SPS_PPS_BS_SIZE - 4);
pCtx->iErrorCode |= dsBitstreamError;
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_OUT_OF_MEMORY);
}
if (!kbUseSubsetFlag) { SSpsBsInfo* pSpsBs = &pCtx->sSpsBsInfo [iSpsId];
pSpsBs->iSpsId = iSpsId;
int32_t iTrailingZeroByte = 0;
while (pSrcNal[kSrcNalLen - iTrailingZeroByte - 1] == 0x0) iTrailingZeroByte++;
int32_t iActualLen = kSrcNalLen - iTrailingZeroByte;
pSpsBs->uiSpsBsLen = (uint16_t) iActualLen;
int32_t iStartDeltaByte = 0; if (pSrcNal[0] == 0x0 && pSrcNal[1] == 0x0 && pSrcNal[2] == 0x1) { pSpsBs->pSpsBsBuf[0] = 0x0; iStartDeltaByte++;
pSpsBs->uiSpsBsLen++;
}
memcpy (pSpsBs->pSpsBsBuf + iStartDeltaByte, pSrcNal, iActualLen);
} else { SSpsBsInfo* pSpsBs = &pCtx->sSubsetSpsBsInfo [iSpsId];
pSpsBs->iSpsId = iSpsId;
pSpsBs->pSpsBsBuf [0] = pSpsBs->pSpsBsBuf [1] = pSpsBs->pSpsBsBuf [2] = 0x00;
pSpsBs->pSpsBsBuf [3] = 0x01;
pSpsBs->pSpsBsBuf [4] = 0x67;
SBitStringAux sSubsetSpsBs;
CMemoryAlign* pMa = pCtx->pMemAlign;
uint8_t* pBsBuf = static_cast<uint8_t*> (pMa->WelsMallocz (SPS_PPS_BS_SIZE + 4,
"Temp buffer for parse only usage.")); if (NULL == pBsBuf) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "sps buffer alloc failed for parse only!");
pCtx->iErrorCode |= dsOutOfMemory;
return pCtx->iErrorCode;
}
InitBits (&sSubsetSpsBs, pBsBuf, (int32_t) (pBs->pEndBuf - pBs->pStartBuf));
BsWriteBits (&sSubsetSpsBs, 8, 77); BsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet0Flag); BsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet1Flag); BsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet2Flag); BsWriteOneBit (&sSubsetSpsBs, pSps->bConstraintSet3Flag); BsWriteBits (&sSubsetSpsBs, 4, 0); BsWriteBits (&sSubsetSpsBs, 8, pSps->uiLevelIdc); BsWriteUE (&sSubsetSpsBs, pSps->iSpsId); BsWriteUE (&sSubsetSpsBs, pSps->uiLog2MaxFrameNum - 4); BsWriteUE (&sSubsetSpsBs, pSps->uiPocType); if (pSps->uiPocType == 0) {
BsWriteUE (&sSubsetSpsBs, pSps->iLog2MaxPocLsb - 4); } else if (pSps->uiPocType == 1) {
BsWriteOneBit (&sSubsetSpsBs, pSps->bDeltaPicOrderAlwaysZeroFlag); BsWriteSE (&sSubsetSpsBs, pSps->iOffsetForNonRefPic); BsWriteSE (&sSubsetSpsBs, pSps->iOffsetForTopToBottomField); BsWriteUE (&sSubsetSpsBs, pSps->iNumRefFramesInPocCycle); for (int32_t i = 0; i < pSps->iNumRefFramesInPocCycle; ++i) {
BsWriteSE (&sSubsetSpsBs, pSps->iOffsetForRefFrame[i]); }
}
BsWriteUE (&sSubsetSpsBs, pSps->iNumRefFrames); BsWriteOneBit (&sSubsetSpsBs, pSps->bGapsInFrameNumValueAllowedFlag); BsWriteUE (&sSubsetSpsBs, pSps->iMbWidth - 1); BsWriteUE (&sSubsetSpsBs, pSps->iMbHeight - 1); BsWriteOneBit (&sSubsetSpsBs, pSps->bFrameMbsOnlyFlag); if (!pSps->bFrameMbsOnlyFlag) {
BsWriteOneBit (&sSubsetSpsBs, pSps->bMbaffFlag); }
BsWriteOneBit (&sSubsetSpsBs, pSps->bDirect8x8InferenceFlag); BsWriteOneBit (&sSubsetSpsBs, pSps->bFrameCroppingFlag); if (pSps->bFrameCroppingFlag) {
BsWriteUE (&sSubsetSpsBs, pSps->sFrameCrop.iLeftOffset); BsWriteUE (&sSubsetSpsBs, pSps->sFrameCrop.iRightOffset); BsWriteUE (&sSubsetSpsBs, pSps->sFrameCrop.iTopOffset); BsWriteUE (&sSubsetSpsBs, pSps->sFrameCrop.iBottomOffset); }
BsWriteOneBit (&sSubsetSpsBs, 0); BsRbspTrailingBits (&sSubsetSpsBs); int32_t iRbspSize = (int32_t) (sSubsetSpsBs.pCurBuf - sSubsetSpsBs.pStartBuf);
RBSP2EBSP (pSpsBs->pSpsBsBuf + 5, sSubsetSpsBs.pStartBuf, iRbspSize);
pSpsBs->uiSpsBsLen = (uint16_t) (sSubsetSpsBs.pCurBuf - sSubsetSpsBs.pStartBuf + 5);
if (pBsBuf) {
pMa->WelsFree (pBsBuf, "pBsBuf for parse only usage");
}
}
}
if (kbUseSubsetFlag && (PRO_SCALABLE_BASELINE == uiProfileIdc || PRO_SCALABLE_HIGH == uiProfileIdc)) {
if ((iRet = DecodeSpsSvcExt (pCtx, pSubsetSps, pBs)) != ERR_NONE) {
return iRet;
}
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode)); pSubsetSps->bSvcVuiParamPresentFlag = !!uiCode;
if (pSubsetSps->bSvcVuiParamPresentFlag) {
}
}
if (PRO_SCALABLE_BASELINE == uiProfileIdc || PRO_SCALABLE_HIGH == uiProfileIdc)
pCtx->sSpsPpsCtx.bAvcBasedFlag = false;
*pPicWidth = pSps->iMbWidth << 4;
*pPicHeight = pSps->iMbHeight << 4;
PSps pTmpSps = NULL;
if (kbUseSubsetFlag) {
pTmpSps = &pCtx->sSpsPpsCtx.sSubsetSpsBuffer[iSpsId].sSps;
} else {
pTmpSps = &pCtx->sSpsPpsCtx.sSpsBuffer[iSpsId];
}
if (CheckSpsActive (pCtx, pTmpSps, kbUseSubsetFlag)) {
if (kbUseSubsetFlag) {
if (memcmp (&pCtx->sSpsPpsCtx.sSubsetSpsBuffer[iSpsId], pSubsetSps, sizeof (SSubsetSps)) != 0) {
if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
memcpy (&pCtx->sSpsPpsCtx.sSubsetSpsBuffer[MAX_SPS_COUNT], pSubsetSps, sizeof (SSubsetSps));
pCtx->bAuReadyFlag = true;
pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
pCtx->sSpsPpsCtx.iOverwriteFlags |= OVERWRITE_SUBSETSPS;
} else if ((pCtx->pSps != NULL) && (pCtx->pSps->iSpsId == pSubsetSps->sSps.iSpsId)) {
memcpy (&pCtx->sSpsPpsCtx.sSubsetSpsBuffer[MAX_SPS_COUNT], pSubsetSps, sizeof (SSubsetSps));
pCtx->sSpsPpsCtx.iOverwriteFlags |= OVERWRITE_SUBSETSPS;
} else {
memcpy (&pCtx->sSpsPpsCtx.sSubsetSpsBuffer[iSpsId], pSubsetSps, sizeof (SSubsetSps));
}
}
} else {
if (memcmp (&pCtx->sSpsPpsCtx.sSpsBuffer[iSpsId], pSps, sizeof (SSps)) != 0) {
if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
memcpy (&pCtx->sSpsPpsCtx.sSpsBuffer[MAX_SPS_COUNT], pSps, sizeof (SSps));
pCtx->sSpsPpsCtx.iOverwriteFlags |= OVERWRITE_SPS;
pCtx->bAuReadyFlag = true;
pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
} else if ((pCtx->pSps != NULL) && (pCtx->pSps->iSpsId == pSps->iSpsId)) {
memcpy (&pCtx->sSpsPpsCtx.sSpsBuffer[MAX_SPS_COUNT], pSps, sizeof (SSps));
pCtx->sSpsPpsCtx.iOverwriteFlags |= OVERWRITE_SPS;
} else {
memcpy (&pCtx->sSpsPpsCtx.sSpsBuffer[iSpsId], pSps, sizeof (SSps));
}
}
}
}
else if (kbUseSubsetFlag) {
memcpy (&pCtx->sSpsPpsCtx.sSubsetSpsBuffer[iSpsId], pSubsetSps, sizeof (SSubsetSps));
pCtx->sSpsPpsCtx.bSubspsAvailFlags[iSpsId] = true;
pCtx->sSpsPpsCtx.bSubspsExistAheadFlag = true;
} else {
memcpy (&pCtx->sSpsPpsCtx.sSpsBuffer[iSpsId], pSps, sizeof (SSps));
pCtx->sSpsPpsCtx.bSpsAvailFlags[iSpsId] = true;
pCtx->sSpsPpsCtx.bSpsExistAheadFlag = true;
}
return ERR_NONE;
}
int32_t ParsePps (PWelsDecoderContext pCtx, PPps pPpsList, PBitStringAux pBsAux, uint8_t* pSrcNal,
const int32_t kSrcNalLen) {
PPps pPps = NULL;
SPps sTempPps;
uint32_t uiPpsId = 0;
uint32_t iTmp;
uint32_t uiCode;
int32_t iCode;
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); uiPpsId = uiCode;
if (uiPpsId >= MAX_PPS_COUNT) {
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_PPS_ID_OVERFLOW);
}
pPps = &sTempPps;
memset (pPps, 0, sizeof (SPps));
pPps->iPpsId = uiPpsId;
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pPps->iSpsId = uiCode;
if (pPps->iSpsId >= MAX_SPS_COUNT) {
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_SPS_ID_OVERFLOW);
}
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pPps->bEntropyCodingModeFlag = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pPps->bPicOrderPresentFlag = !!uiCode;
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pPps->uiNumSliceGroups = NUM_SLICE_GROUPS_OFFSET + uiCode;
if (pPps->uiNumSliceGroups > MAX_SLICEGROUP_IDS) {
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_SLICEGROUP);
}
if (pPps->uiNumSliceGroups > 1) {
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pPps->uiSliceGroupMapType = uiCode;
if (pPps->uiSliceGroupMapType > 1) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "ParsePps(): slice_group_map_type (%d): support only 0,1.",
pPps->uiSliceGroupMapType);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_FMOTYPE);
}
switch (pPps->uiSliceGroupMapType) {
case 0:
for (iTmp = 0; iTmp < pPps->uiNumSliceGroups; iTmp++) {
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pPps->uiRunLength[iTmp] = RUN_LENGTH_OFFSET + uiCode;
}
break;
default:
break;
}
}
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pPps->uiNumRefIdxL0Active = NUM_REF_IDX_L0_DEFAULT_ACTIVE_OFFSET + uiCode;
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pPps->uiNumRefIdxL1Active = NUM_REF_IDX_L1_DEFAULT_ACTIVE_OFFSET + uiCode;
if (pPps->uiNumRefIdxL0Active > MAX_REF_PIC_COUNT ||
pPps->uiNumRefIdxL1Active > MAX_REF_PIC_COUNT) {
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_REF_COUNT_OVERFLOW);
}
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pPps->bWeightedPredFlag = !!uiCode;
WELS_READ_VERIFY (BsGetBits (pBsAux, 2, &uiCode)); pPps->uiWeightedBipredIdc = uiCode;
WELS_READ_VERIFY (BsGetSe (pBsAux, &iCode)); pPps->iPicInitQp = PIC_INIT_QP_OFFSET + iCode;
WELS_CHECK_SE_BOTH_ERROR (pPps->iPicInitQp, PPS_PIC_INIT_QP_QS_MIN, PPS_PIC_INIT_QP_QS_MAX, "pic_init_qp_minus26 + 26",
GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_PIC_INIT_QP));
WELS_READ_VERIFY (BsGetSe (pBsAux, &iCode)); pPps->iPicInitQs = PIC_INIT_QS_OFFSET + iCode;
WELS_CHECK_SE_BOTH_ERROR (pPps->iPicInitQs, PPS_PIC_INIT_QP_QS_MIN, PPS_PIC_INIT_QP_QS_MAX, "pic_init_qs_minus26 + 26",
GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_PIC_INIT_QS));
WELS_READ_VERIFY (BsGetSe (pBsAux, &iCode)); pPps->iChromaQpIndexOffset[0] = iCode;
WELS_CHECK_SE_BOTH_ERROR (pPps->iChromaQpIndexOffset[0], PPS_CHROMA_QP_INDEX_OFFSET_MIN, PPS_CHROMA_QP_INDEX_OFFSET_MAX,
"chroma_qp_index_offset", GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_CHROMA_QP_INDEX_OFFSET));
pPps->iChromaQpIndexOffset[1] = pPps->iChromaQpIndexOffset[0]; WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pPps->bDeblockingFilterControlPresentFlag = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pPps->bConstainedIntraPredFlag = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pPps->bRedundantPicCntPresentFlag = !!uiCode;
if (CheckMoreRBSPData (pBsAux)) {
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pPps->bTransform8x8ModeFlag = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pPps->bPicScalingMatrixPresentFlag = !!uiCode;
if (pPps->bPicScalingMatrixPresentFlag) {
if (pCtx->sSpsPpsCtx.bSpsAvailFlags[pPps->iSpsId]) {
WELS_READ_VERIFY (ParseScalingList (&pCtx->sSpsPpsCtx.sSpsBuffer[pPps->iSpsId], pBsAux, 1, pPps->bTransform8x8ModeFlag,
pPps->bPicScalingListPresentFlag, pPps->iScalingList4x4, pPps->iScalingList8x8));
} else {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"ParsePps(): sps_id (%d) does not exist for scaling_list. This PPS (%d) is marked as invalid.", pPps->iSpsId,
pPps->iPpsId);
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_INVALID_SPS_ID);
}
}
WELS_READ_VERIFY (BsGetSe (pBsAux, &iCode)); pPps->iChromaQpIndexOffset[1] = iCode;
WELS_CHECK_SE_BOTH_ERROR (pPps->iChromaQpIndexOffset[1], PPS_CHROMA_QP_INDEX_OFFSET_MIN,
PPS_CHROMA_QP_INDEX_OFFSET_MAX, "chroma_qp_index_offset", GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS,
ERR_INFO_INVALID_CHROMA_QP_INDEX_OFFSET));
}
if (pCtx->pPps != NULL && pCtx->pPps->iPpsId == pPps->iPpsId) {
if (memcmp (pCtx->pPps, pPps, sizeof (*pPps)) != 0) {
memcpy (&pCtx->sSpsPpsCtx.sPpsBuffer[MAX_PPS_COUNT], pPps, sizeof (SPps));
pCtx->sSpsPpsCtx.iOverwriteFlags |= OVERWRITE_PPS;
if (pCtx->pAccessUnitList->uiAvailUnitsNum > 0) {
pCtx->bAuReadyFlag = true;
pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1;
}
}
} else {
memcpy (&pCtx->sSpsPpsCtx.sPpsBuffer[uiPpsId], pPps, sizeof (SPps));
pCtx->sSpsPpsCtx.bPpsAvailFlags[uiPpsId] = true;
}
if (pCtx->pParam->bParseOnly) {
if (kSrcNalLen >= SPS_PPS_BS_SIZE - 4) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "pps payload size (%d) too large for parse only (%d), not supported!",
kSrcNalLen, SPS_PPS_BS_SIZE - 4);
pCtx->iErrorCode |= dsBitstreamError;
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_OUT_OF_MEMORY);
}
SPpsBsInfo* pPpsBs = &pCtx->sPpsBsInfo [uiPpsId];
pPpsBs->iPpsId = (int32_t) uiPpsId;
int32_t iTrailingZeroByte = 0;
while (pSrcNal[kSrcNalLen - iTrailingZeroByte - 1] == 0x0) iTrailingZeroByte++;
int32_t iActualLen = kSrcNalLen - iTrailingZeroByte;
pPpsBs->uiPpsBsLen = (uint16_t) iActualLen;
int32_t iStartDeltaByte = 0; if (pSrcNal[0] == 0x0 && pSrcNal[1] == 0x0 && pSrcNal[2] == 0x1) { pPpsBs->pPpsBsBuf[0] = 0x0; iStartDeltaByte++;
pPpsBs->uiPpsBsLen++;
}
memcpy (pPpsBs->pPpsBsBuf + iStartDeltaByte, pSrcNal, iActualLen);
}
return ERR_NONE;
}
#define VUI_MAX_CHROMA_LOG_TYPE_TOP_BOTTOM_FIELD_MAX 5
#define VUI_NUM_UNITS_IN_TICK_MIN 1
#define VUI_TIME_SCALE_MIN 1
#define VUI_MAX_BYTES_PER_PIC_DENOM_MAX 16
#define VUI_MAX_BITS_PER_MB_DENOM_MAX 16
#define VUI_LOG2_MAX_MV_LENGTH_HOR_MAX 16
#define VUI_LOG2_MAX_MV_LENGTH_VER_MAX 16
#define VUI_MAX_DEC_FRAME_BUFFERING_MAX 16
int32_t ParseVui (PWelsDecoderContext pCtx, PSps pSps, PBitStringAux pBsAux) {
uint32_t uiCode;
PVui pVui = &pSps->sVui;
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bAspectRatioInfoPresentFlag = !!uiCode;
if (pSps->sVui.bAspectRatioInfoPresentFlag) {
WELS_READ_VERIFY (BsGetBits (pBsAux, 8, &uiCode)); pVui->uiAspectRatioIdc = uiCode;
if (pVui->uiAspectRatioIdc < 17) {
pVui->uiSarWidth = g_ksVuiSampleAspectRatio[pVui->uiAspectRatioIdc].uiWidth;
pVui->uiSarHeight = g_ksVuiSampleAspectRatio[pVui->uiAspectRatioIdc].uiHeight;
} else if (pVui->uiAspectRatioIdc == EXTENDED_SAR) {
WELS_READ_VERIFY (BsGetBits (pBsAux, 16, &uiCode)); pVui->uiSarWidth = uiCode;
WELS_READ_VERIFY (BsGetBits (pBsAux, 16, &uiCode)); pVui->uiSarHeight = uiCode;
}
}
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bOverscanInfoPresentFlag = !!uiCode;
if (pVui->bOverscanInfoPresentFlag) {
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bOverscanAppropriateFlag = !!uiCode;
}
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bVideoSignalTypePresentFlag = !!uiCode;
if (pVui->bVideoSignalTypePresentFlag) {
WELS_READ_VERIFY (BsGetBits (pBsAux, 3, &uiCode)); pVui->uiVideoFormat = uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bVideoFullRangeFlag = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bColourDescripPresentFlag = !!uiCode;
if (pVui->bColourDescripPresentFlag) {
WELS_READ_VERIFY (BsGetBits (pBsAux, 8, &uiCode)); pVui->uiColourPrimaries = uiCode;
WELS_READ_VERIFY (BsGetBits (pBsAux, 8, &uiCode)); pVui->uiTransferCharacteristics = uiCode;
WELS_READ_VERIFY (BsGetBits (pBsAux, 8, &uiCode)); pVui->uiMatrixCoeffs = uiCode;
}
}
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bChromaLocInfoPresentFlag = !!uiCode;
if (pVui->bChromaLocInfoPresentFlag) {
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pVui->uiChromaSampleLocTypeTopField = uiCode;
WELS_CHECK_SE_UPPER_WARNING (pVui->uiChromaSampleLocTypeTopField, VUI_MAX_CHROMA_LOG_TYPE_TOP_BOTTOM_FIELD_MAX,
"chroma_sample_loc_type_top_field");
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pVui->uiChromaSampleLocTypeBottomField = uiCode;
WELS_CHECK_SE_UPPER_WARNING (pVui->uiChromaSampleLocTypeBottomField, VUI_MAX_CHROMA_LOG_TYPE_TOP_BOTTOM_FIELD_MAX,
"chroma_sample_loc_type_bottom_field");
}
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bTimingInfoPresentFlag = !!uiCode;
if (pVui->bTimingInfoPresentFlag) {
uint32_t uiTmp = 0;
WELS_READ_VERIFY (BsGetBits (pBsAux, 16, &uiCode)); uiTmp = (uiCode << 16);
WELS_READ_VERIFY (BsGetBits (pBsAux, 16, &uiCode)); uiTmp |= uiCode;
pVui->uiNumUnitsInTick = uiTmp;
WELS_CHECK_SE_LOWER_WARNING (pVui->uiNumUnitsInTick, VUI_NUM_UNITS_IN_TICK_MIN, "num_units_in_tick");
WELS_READ_VERIFY (BsGetBits (pBsAux, 16, &uiCode)); uiTmp = (uiCode << 16);
WELS_READ_VERIFY (BsGetBits (pBsAux, 16, &uiCode)); uiTmp |= uiCode;
pVui->uiTimeScale = uiTmp;
WELS_CHECK_SE_LOWER_WARNING (pVui->uiNumUnitsInTick, VUI_TIME_SCALE_MIN, "time_scale");
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bFixedFrameRateFlag = !!uiCode;
}
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bNalHrdParamPresentFlag = !!uiCode;
if (pVui->bNalHrdParamPresentFlag) { #ifdef _PARSE_NALHRD_VCLHRD_PARAMS_
int32_t cpb_cnt_minus1 = BsGetUe (pBsAux, &uiCode);
BsGetBits (pBsAux, 4, &uiCode);
BsGetBits (pBsAux, 4, &uiCode);
for (int32_t i = 0; i <= cpb_cnt_minus1; i++) {
BsGetUe (pBsAux, &uiCode);
BsGetUe (pBsAux, &uiCode);
BsGetOneBit (pBsAux, &uiCode);
}
BsGetBits (pBsAux, 5, &uiCode);
BsGetBits (pBsAux, 5, &uiCode);
BsGetBits (pBsAux, 5, &uiCode);
BsGetBits (pBsAux, 5, &uiCode);
#else
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "nal_hrd_parameters_present_flag = 1 not supported.");
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_VUI_HRD);
#endif
}
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bVclHrdParamPresentFlag = !!uiCode;
if (pVui->bVclHrdParamPresentFlag) {#ifdef _PARSE_NALHRD_VCLHRD_PARAMS_
int32_t cpb_cnt_minus1 = BsGetUe (pBsAux, &uiCode);
BsGetBits (pBsAux, 4, &uiCode);
BsGetBits (pBsAux, 4, &uiCode);
for (int32_t i = 0; i <= cpb_cnt_minus1; i++) {
BsGetUe (pBsAux, &uiCode);
BsGetUe (pBsAux, &uiCode);
BsGetOneBit (pBsAux, &uiCode);
}
BsGetBits (pBsAux, 5, &uiCode);
BsGetBits (pBsAux, 5, &uiCode);
BsGetBits (pBsAux, 5, &uiCode);
BsGetBits (pBsAux, 5, &uiCode);
#else
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "vcl_hrd_parameters_present_flag = 1 not supported.");
return GENERATE_ERROR_NO (ERR_LEVEL_PARAM_SETS, ERR_INFO_UNSUPPORTED_VUI_HRD);
#endif
}
#ifdef _PARSE_NALHRD_VCLHRD_PARAMS_
if (pVui->bNalHrdParamPresentFlag | pVui->bVclHrdParamPresentFlag) {
BsGetOneBit (pBsAux, &uiCode);
}
#endif
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bPicStructPresentFlag = !!uiCode;
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bBitstreamRestrictionFlag = !!uiCode;
if (pVui->bBitstreamRestrictionFlag) {
WELS_READ_VERIFY (BsGetOneBit (pBsAux, &uiCode)); pVui->bMotionVectorsOverPicBoundariesFlag = !!uiCode;
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pVui->uiMaxBytesPerPicDenom = uiCode;
WELS_CHECK_SE_UPPER_WARNING (pVui->uiMaxBytesPerPicDenom, VUI_MAX_BYTES_PER_PIC_DENOM_MAX,
"max_bytes_per_pic_denom");
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pVui->uiMaxBitsPerMbDenom = uiCode;
WELS_CHECK_SE_UPPER_WARNING (pVui->uiMaxBitsPerMbDenom, VUI_MAX_BITS_PER_MB_DENOM_MAX,
"max_bits_per_mb_denom");
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pVui->uiLog2MaxMvLengthHorizontal = uiCode;
WELS_CHECK_SE_UPPER_WARNING (pVui->uiLog2MaxMvLengthHorizontal, VUI_LOG2_MAX_MV_LENGTH_HOR_MAX,
"log2_max_mv_length_horizontal");
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pVui->uiLog2MaxMvLengthVertical = uiCode;
WELS_CHECK_SE_UPPER_WARNING (pVui->uiLog2MaxMvLengthVertical, VUI_LOG2_MAX_MV_LENGTH_VER_MAX,
"log2_max_mv_length_vertical");
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pVui->uiMaxNumReorderFrames = uiCode;
WELS_CHECK_SE_UPPER_WARNING (pVui->uiMaxNumReorderFrames, VUI_MAX_DEC_FRAME_BUFFERING_MAX,
"max_num_reorder_frames");
WELS_READ_VERIFY (BsGetUe (pBsAux, &uiCode)); pVui->uiMaxDecFrameBuffering = uiCode;
WELS_CHECK_SE_UPPER_WARNING (pVui->uiMaxDecFrameBuffering, VUI_MAX_DEC_FRAME_BUFFERING_MAX,
"max_num_reorder_frames");
}
return ERR_NONE;
}
int32_t ParseSei (void* pSei, PBitStringAux pBsAux) {
return ERR_NONE;
}
int32_t SetScalingListValue (uint8_t* pScalingList, int iScalingListNum, bool* bUseDefaultScalingMatrixFlag,
PBitStringAux pBsAux) { int iLastScale = 8;
int iNextScale = 8;
int iDeltaScale;
int32_t iCode;
int32_t iIdx;
for (int j = 0; j < iScalingListNum; j++) {
if (iNextScale != 0) {
WELS_READ_VERIFY (BsGetSe (pBsAux, &iCode));
WELS_CHECK_SE_BOTH_ERROR_NOLOG (iCode, SCALING_LIST_DELTA_SCALE_MIN, SCALING_LIST_DELTA_SCALE_MAX, "DeltaScale",
ERR_SCALING_LIST_DELTA_SCALE);
iDeltaScale = iCode;
iNextScale = (iLastScale + iDeltaScale + 256) % 256;
*bUseDefaultScalingMatrixFlag = (j == 0 && iNextScale == 0);
if (*bUseDefaultScalingMatrixFlag)
break;
}
iIdx = iScalingListNum == 16 ? g_kuiZigzagScan[j] : g_kuiZigzagScan8x8[j];
pScalingList[iIdx] = (iNextScale == 0) ? iLastScale : iNextScale;
iLastScale = pScalingList[iIdx];
}
return ERR_NONE;
}
int32_t ParseScalingList (PSps pSps, PBitStringAux pBs, bool bPPS, const bool kbTrans8x8ModeFlag,
bool* pScalingListPresentFlag, uint8_t (*iScalingList4x4)[16], uint8_t (*iScalingList8x8)[64]) {
uint32_t uiScalingListNum;
uint32_t uiCode;
bool bUseDefaultScalingMatrixFlag4x4 = false;
bool bUseDefaultScalingMatrixFlag8x8 = false;
bool bInit = false;
const uint8_t* defaultScaling[4];
if (!bPPS) { uiScalingListNum = (pSps->uiChromaFormatIdc != 3) ? 8 : 12;
} else { uiScalingListNum = 6 + (int32_t) kbTrans8x8ModeFlag * ((pSps->uiChromaFormatIdc != 3) ? 2 : 6);
bInit = pSps->bSeqScalingMatrixPresentFlag;
}
defaultScaling[0] = bInit ? pSps->iScalingList4x4[0] : g_kuiDequantScaling4x4Default[0];
defaultScaling[1] = bInit ? pSps->iScalingList4x4[3] : g_kuiDequantScaling4x4Default[1];
defaultScaling[2] = bInit ? pSps->iScalingList8x8[0] : g_kuiDequantScaling8x8Default[0];
defaultScaling[3] = bInit ? pSps->iScalingList8x8[1] : g_kuiDequantScaling8x8Default[1];
for (unsigned int i = 0; i < uiScalingListNum; i++) {
WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));
pScalingListPresentFlag[i] = !!uiCode;
if (!!uiCode) {
if (i < 6) { WELS_READ_VERIFY (SetScalingListValue (iScalingList4x4[i], 16, &bUseDefaultScalingMatrixFlag4x4, pBs));
if (bUseDefaultScalingMatrixFlag4x4) {
bUseDefaultScalingMatrixFlag4x4 = false;
memcpy (iScalingList4x4[i], g_kuiDequantScaling4x4Default[i / 3], sizeof (uint8_t) * 16);
}
} else {
WELS_READ_VERIFY (SetScalingListValue (iScalingList8x8[i - 6], 64, &bUseDefaultScalingMatrixFlag8x8, pBs));
if (bUseDefaultScalingMatrixFlag8x8) {
bUseDefaultScalingMatrixFlag8x8 = false;
memcpy (iScalingList8x8[i - 6], g_kuiDequantScaling8x8Default[ (i - 6) & 1], sizeof (uint8_t) * 64);
}
}
} else {
if (i < 6) {
if ((i != 0) && (i != 3))
memcpy (iScalingList4x4[i], iScalingList4x4[i - 1], sizeof (uint8_t) * 16);
else
memcpy (iScalingList4x4[i], defaultScaling[i / 3], sizeof (uint8_t) * 16);
} else {
if ((i == 6) || (i == 7))
memcpy (iScalingList8x8[i - 6], defaultScaling[ (i & 1) + 2], sizeof (uint8_t) * 64);
else
memcpy (iScalingList8x8[i - 6], iScalingList8x8[i - 8], sizeof (uint8_t) * 64);
}
}
}
return ERR_NONE;
}
int32_t ResetFmoList (PWelsDecoderContext pCtx) {
int32_t iCountNum = 0;
if (NULL != pCtx) {
UninitFmoList (&pCtx->sFmoList[0], MAX_PPS_COUNT, pCtx->iActiveFmoNum, pCtx->pMemAlign);
iCountNum = pCtx->iActiveFmoNum;
pCtx->iActiveFmoNum = 0;
}
return iCountNum;
}
}