/*! * \copy * Copyright (c) 2009-2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * \file au_parser.c * * \brief Interfaces introduced in Access Unit level based parser * * \date 03/10/2009 Created * ************************************************************************************* */#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 "mem_align.h" namespace WelsDec {/*! ************************************************************************************* * \brief Start Code Prefix (0x 00 00 00 01) detection * * \param pBuf bitstream payload buffer * \param pOffset offset between NAL rbsp and original bitsteam that * start code prefix is seperated from. * \param iBufSize count size of buffer * * \return RBSP buffer of start code prefix exclusive * * \note N/A ************************************************************************************* */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;} /*! ************************************************************************************* * \brief to parse nal unit * * \param pCtx decoder context * \param pNalUnitHeader parsed result of NAL Unit Header to output * \param pSrcRbsp bitstream buffer to input * \param iSrcRbspLen length size of bitstream buffer payload * \param pSrcNal * \param iSrcNalLen * \param pConsumedBytes consumed bytes during parsing * * \return decoded bytes payload, might be (pSrcRbsp+1) if no escapes * * \note N/A ************************************************************************************* */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;//SHOULD init it. because pCtx->sCurNalHead is common variable. //remove the consecutive ZERO at the end of current NAL in the reverse order.--2011.6.1 { int32_t iIndex = iSrcRbspLen - 1; uint8_t uiBsZero = 0; while (iIndex >= 0) { uiBsZero = pSrcRbsp[iIndex]; if (0 == uiBsZero) { --iNalSize; --iIndex; } else { break; } } } pNalUnitHeader->uiForbiddenZeroBit = (uint8_t) (pNal[0] >> 7); // uiForbiddenZeroBit if (pNalUnitHeader->uiForbiddenZeroBit) { //2010.4.14 pCtx->iErrorCode |= dsBitstreamError; return NULL; //uiForbiddenZeroBit should always equal to 0 } pNalUnitHeader->uiNalRefIdc = (uint8_t) (pNal[0] >> 5); // uiNalRefIdc pNalUnitHeader->eNalUnitType = (EWelsNalUnitType) (pNal[0] & 0x1f); // eNalUnitType ++pNal; --iNalSize; ++ (*pConsumedBytes); if (! (IS_SEI_NAL (pNalUnitHeader->eNalUnitType) || IS_SPS_NAL (pNalUnitHeader->eNalUnitType) || pCtx->bSpsExistAheadFlag)) { if (pCtx->bPrintFrameErrorTraceFlag) { WelsLog (pLogCtx, WELS_LOG_WARNING, "parse_nal(), no exist Sequence Parameter Sets ahead of sequence when try to decode NAL(type:%d).", pNalUnitHeader->eNalUnitType); } pCtx->iErrorCode = dsNoParamSets; return NULL; } if (! (IS_SEI_NAL (pNalUnitHeader->eNalUnitType) || IS_PARAM_SETS_NALS (pNalUnitHeader->eNalUnitType) || pCtx->bPpsExistAheadFlag)) { if (pCtx->bPrintFrameErrorTraceFlag) { WelsLog (pLogCtx, WELS_LOG_WARNING, "parse_nal(), no exist Picture Parameter Sets ahead of sequence when try to decode NAL(type:%d).", pNalUnitHeader->eNalUnitType); } pCtx->iErrorCode = dsNoParamSets; return NULL; } if ((IS_VCL_NAL_AVC_BASE (pNalUnitHeader->eNalUnitType) && ! (pCtx->bSpsExistAheadFlag || pCtx->bPpsExistAheadFlag)) || (IS_NEW_INTRODUCED_SVC_NAL (pNalUnitHeader->eNalUnitType) && ! (pCtx->bSpsExistAheadFlag || pCtx->bSubspsExistAheadFlag || pCtx->bPpsExistAheadFlag))) { if (pCtx->bPrintFrameErrorTraceFlag) { WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseNalHeader(), no exist Parameter Sets ahead of sequence when try to decode slice(type:%d).", pNalUnitHeader->eNalUnitType); } pCtx->iErrorCode |= dsNoParamSets; return NULL; } 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->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->eErrorConMethod == 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->eErrorConMethod == 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); // convert into bit iErr = InitBits (pBs, pNal, iBitSize); if (iErr) { WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_PREFIX: InitBits() 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); 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->eErrorConMethod == 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->eErrorConMethod == 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->bParseOnly) { pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos; int32_t iTrailingZeroByte = 0; while (pSrcNal[iSrcNalLen - iTrailingZeroByte - 1] == 0x0) //remove final trailing 0 bytes iTrailingZeroByte++; int32_t iActualLen = iSrcNalLen - iTrailingZeroByte; pCurNal->sNalData.sVclNal.iNalLength = iActualLen - NAL_UNIT_HEADER_EXT_SIZE; //unify start code as 0x0001 int32_t iCurrStartByte = 4; //4 for 0x0001, 3 for 0x001 if (pSrcNal[0] == 0x0 && pSrcNal[1] == 0x0 && pSrcNal[2] == 0x1) { //if 0x001 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; int32_t iOffset = iCurrStartByte + 1 + NAL_UNIT_HEADER_EXT_SIZE; memcpy (pSavedData->pCurPos, pSrcNal + iOffset, iActualLen - iOffset); pSavedData->pCurPos += iActualLen - iOffset; } } else { if (pCtx->bParseOnly) { pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos; int32_t iTrailingZeroByte = 0; while (pSrcNal[iSrcNalLen - iTrailingZeroByte - 1] == 0x0) //remove final trailing 0 bytes iTrailingZeroByte++; int32_t iActualLen = iSrcNalLen - iTrailingZeroByte; pCurNal->sNalData.sVclNal.iNalLength = iActualLen; //unify start code as 0x0001 int32_t iStartDeltaByte = 0; //0 for 0x0001, 1 for 0x001 if (pSrcNal[0] == 0x0 && pSrcNal[1] == 0x0 && pSrcNal[2] == 0x1) { //if 0x001 pSavedData->pCurPos[0] = 0x0; iStartDeltaByte = 1; pCurNal->sNalData.sVclNal.iNalLength++; } memcpy (pSavedData->pCurPos + iStartDeltaByte, pSrcNal, iActualLen); pSavedData->pCurPos += iStartDeltaByte + iActualLen; } if (NAL_UNIT_PREFIX == pCtx->sPrefixNal.sNalHeaderExt.sNalUnitHeader.eNalUnitType) { if (pCtx->sPrefixNal.sNalData.sPrefixNal.bPrefixNalCorrectFlag) { PrefetchNalHeaderExtSyntax (pCtx, pCurNal, &pCtx->sPrefixNal); } } pCurNal->sNalHeaderExt.bIdrFlag = (NAL_UNIT_CODED_SLICE_IDR == pNalUnitHeader->eNalUnitType) ? true : false; //SHOULD update this flag for AVC if no prefix NAL pCurNal->sNalHeaderExt.iNoInterLayerPredFlag = 1; } pBs = &pCurAu->pNalUnitsList[uiAvailNalNum - 1]->sNalData.sVclNal.sSliceBitsRead; iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit iErr = InitBits (pBs, pNal, iBitSize); if (iErr) { ForceClearCurrentNal (pCurAu); if (uiAvailNalNum > 1) { pCurAu->uiEndPos = uiAvailNalNum - 2; if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) { pCtx->bAuReadyFlag = true; } } WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_CODED_SLICE: InitBits() fail due invalid access."); pCtx->iErrorCode |= dsBitstreamError; return NULL; } iErr = ParseSliceHeaderSyntaxs (pCtx, pBs, bExtensionFlag); if (iErr != ERR_NONE) { if ((uiAvailNalNum == 1) && (pCurNal->sNalHeaderExt.bIdrFlag)) { //IDR parse error ResetActiveSPSForEachLayer (pCtx); } //if current NAL occur error when parsing, should clean it from pNalUnitsList //otherwise, when Next good NAL decoding, this corrupt NAL is considered as normal NAL and lead to decoder crash ForceClearCurrentNal (pCurAu); if (uiAvailNalNum > 1) { pCurAu->uiEndPos = uiAvailNalNum - 2; if (pCtx->eErrorConMethod == 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; //Sub-clause 7.1.4.1.1 temporal_id if (pLastNalHdrExt->uiTemporalId != pCurNalHeaderExt->uiTemporalId) { return true; } // Subclause 7.4.1.2.5 if (pLastSliceHeader->iRedundantPicCnt < pCurSliceHeader->iRedundantPicCnt) return false; else if (pLastSliceHeader->iRedundantPicCnt > pCurSliceHeader->iRedundantPicCnt) return true; // Subclause G7.4.1.2.4 if (pLastNalHdrExt->uiDependencyId < pCurNalHeaderExt->uiDependencyId) return false; else if (pLastNalHdrExt->uiDependencyId > pCurNalHeaderExt->uiDependencyId) return true; if (pLastNalHdrExt->uiQualityId < pCurNalHeaderExt->uiQualityId) return false; else if (pLastNalHdrExt->uiQualityId > pCurNalHeaderExt->uiQualityId) return true; // Subclause 7.4.1.2.4 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->pActiveLayerSps[kpCurNalHeaderExt->uiDependencyId] != NULL && pCtx->pActiveLayerSps[kpCurNalHeaderExt->uiDependencyId] != kpSps) { return true; // the active sps changed, new sequence begins, so the current au is ready } //Sub-clause 7.1.4.1.1 temporal_id if (kpLastNalHeaderExt->uiTemporalId != kpCurNalHeaderExt->uiTemporalId) { return true; } if (kpLastSliceHeader->iFrameNum != kpCurSliceHeader->iFrameNum)Lines 1–500 of 1562. Load more
/*! * \copy * Copyright (c) 2009-2013, Cisco Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * \file au_parser.c * * \brief Interfaces introduced in Access Unit level based parser * * \date 03/10/2009 Created * ************************************************************************************* */ #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 "mem_align.h" namespace WelsDec { /*! ************************************************************************************* * \brief Start Code Prefix (0x 00 00 00 01) detection * * \param pBuf bitstream payload buffer * \param pOffset offset between NAL rbsp and original bitsteam that * start code prefix is seperated from. * \param iBufSize count size of buffer * * \return RBSP buffer of start code prefix exclusive * * \note N/A ************************************************************************************* */ 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; } /*! ************************************************************************************* * \brief to parse nal unit * * \param pCtx decoder context * \param pNalUnitHeader parsed result of NAL Unit Header to output * \param pSrcRbsp bitstream buffer to input * \param iSrcRbspLen length size of bitstream buffer payload * \param pSrcNal * \param iSrcNalLen * \param pConsumedBytes consumed bytes during parsing * * \return decoded bytes payload, might be (pSrcRbsp+1) if no escapes * * \note N/A ************************************************************************************* */ 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;//SHOULD init it. because pCtx->sCurNalHead is common variable. //remove the consecutive ZERO at the end of current NAL in the reverse order.--2011.6.1 { int32_t iIndex = iSrcRbspLen - 1; uint8_t uiBsZero = 0; while (iIndex >= 0) { uiBsZero = pSrcRbsp[iIndex]; if (0 == uiBsZero) { --iNalSize; --iIndex; } else { break; } } } pNalUnitHeader->uiForbiddenZeroBit = (uint8_t) (pNal[0] >> 7); // uiForbiddenZeroBit if (pNalUnitHeader->uiForbiddenZeroBit) { //2010.4.14 pCtx->iErrorCode |= dsBitstreamError; return NULL; //uiForbiddenZeroBit should always equal to 0 } pNalUnitHeader->uiNalRefIdc = (uint8_t) (pNal[0] >> 5); // uiNalRefIdc pNalUnitHeader->eNalUnitType = (EWelsNalUnitType) (pNal[0] & 0x1f); // eNalUnitType ++pNal; --iNalSize; ++ (*pConsumedBytes); if (! (IS_SEI_NAL (pNalUnitHeader->eNalUnitType) || IS_SPS_NAL (pNalUnitHeader->eNalUnitType) || pCtx->bSpsExistAheadFlag)) { if (pCtx->bPrintFrameErrorTraceFlag) { WelsLog (pLogCtx, WELS_LOG_WARNING, "parse_nal(), no exist Sequence Parameter Sets ahead of sequence when try to decode NAL(type:%d).", pNalUnitHeader->eNalUnitType); } pCtx->iErrorCode = dsNoParamSets; return NULL; } if (! (IS_SEI_NAL (pNalUnitHeader->eNalUnitType) || IS_PARAM_SETS_NALS (pNalUnitHeader->eNalUnitType) || pCtx->bPpsExistAheadFlag)) { if (pCtx->bPrintFrameErrorTraceFlag) { WelsLog (pLogCtx, WELS_LOG_WARNING, "parse_nal(), no exist Picture Parameter Sets ahead of sequence when try to decode NAL(type:%d).", pNalUnitHeader->eNalUnitType); } pCtx->iErrorCode = dsNoParamSets; return NULL; } if ((IS_VCL_NAL_AVC_BASE (pNalUnitHeader->eNalUnitType) && ! (pCtx->bSpsExistAheadFlag || pCtx->bPpsExistAheadFlag)) || (IS_NEW_INTRODUCED_SVC_NAL (pNalUnitHeader->eNalUnitType) && ! (pCtx->bSpsExistAheadFlag || pCtx->bSubspsExistAheadFlag || pCtx->bPpsExistAheadFlag))) { if (pCtx->bPrintFrameErrorTraceFlag) { WelsLog (pLogCtx, WELS_LOG_WARNING, "ParseNalHeader(), no exist Parameter Sets ahead of sequence when try to decode slice(type:%d).", pNalUnitHeader->eNalUnitType); } pCtx->iErrorCode |= dsNoParamSets; return NULL; } 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->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->eErrorConMethod == 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->eErrorConMethod == 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); // convert into bit iErr = InitBits (pBs, pNal, iBitSize); if (iErr) { WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_PREFIX: InitBits() 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); 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->eErrorConMethod == 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->eErrorConMethod == 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->bParseOnly) { pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos; int32_t iTrailingZeroByte = 0; while (pSrcNal[iSrcNalLen - iTrailingZeroByte - 1] == 0x0) //remove final trailing 0 bytes iTrailingZeroByte++; int32_t iActualLen = iSrcNalLen - iTrailingZeroByte; pCurNal->sNalData.sVclNal.iNalLength = iActualLen - NAL_UNIT_HEADER_EXT_SIZE; //unify start code as 0x0001 int32_t iCurrStartByte = 4; //4 for 0x0001, 3 for 0x001 if (pSrcNal[0] == 0x0 && pSrcNal[1] == 0x0 && pSrcNal[2] == 0x1) { //if 0x001 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; int32_t iOffset = iCurrStartByte + 1 + NAL_UNIT_HEADER_EXT_SIZE; memcpy (pSavedData->pCurPos, pSrcNal + iOffset, iActualLen - iOffset); pSavedData->pCurPos += iActualLen - iOffset; } } else { if (pCtx->bParseOnly) { pCurNal->sNalData.sVclNal.pNalPos = pSavedData->pCurPos; int32_t iTrailingZeroByte = 0; while (pSrcNal[iSrcNalLen - iTrailingZeroByte - 1] == 0x0) //remove final trailing 0 bytes iTrailingZeroByte++; int32_t iActualLen = iSrcNalLen - iTrailingZeroByte; pCurNal->sNalData.sVclNal.iNalLength = iActualLen; //unify start code as 0x0001 int32_t iStartDeltaByte = 0; //0 for 0x0001, 1 for 0x001 if (pSrcNal[0] == 0x0 && pSrcNal[1] == 0x0 && pSrcNal[2] == 0x1) { //if 0x001 pSavedData->pCurPos[0] = 0x0; iStartDeltaByte = 1; pCurNal->sNalData.sVclNal.iNalLength++; } memcpy (pSavedData->pCurPos + iStartDeltaByte, pSrcNal, iActualLen); pSavedData->pCurPos += iStartDeltaByte + iActualLen; } if (NAL_UNIT_PREFIX == pCtx->sPrefixNal.sNalHeaderExt.sNalUnitHeader.eNalUnitType) { if (pCtx->sPrefixNal.sNalData.sPrefixNal.bPrefixNalCorrectFlag) { PrefetchNalHeaderExtSyntax (pCtx, pCurNal, &pCtx->sPrefixNal); } } pCurNal->sNalHeaderExt.bIdrFlag = (NAL_UNIT_CODED_SLICE_IDR == pNalUnitHeader->eNalUnitType) ? true : false; //SHOULD update this flag for AVC if no prefix NAL pCurNal->sNalHeaderExt.iNoInterLayerPredFlag = 1; } pBs = &pCurAu->pNalUnitsList[uiAvailNalNum - 1]->sNalData.sVclNal.sSliceBitsRead; iBitSize = (iNalSize << 3) - BsGetTrailingBits (pNal + iNalSize - 1); // convert into bit iErr = InitBits (pBs, pNal, iBitSize); if (iErr) { ForceClearCurrentNal (pCurAu); if (uiAvailNalNum > 1) { pCurAu->uiEndPos = uiAvailNalNum - 2; if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) { pCtx->bAuReadyFlag = true; } } WelsLog (pLogCtx, WELS_LOG_ERROR, "NAL_UNIT_CODED_SLICE: InitBits() fail due invalid access."); pCtx->iErrorCode |= dsBitstreamError; return NULL; } iErr = ParseSliceHeaderSyntaxs (pCtx, pBs, bExtensionFlag); if (iErr != ERR_NONE) { if ((uiAvailNalNum == 1) && (pCurNal->sNalHeaderExt.bIdrFlag)) { //IDR parse error ResetActiveSPSForEachLayer (pCtx); } //if current NAL occur error when parsing, should clean it from pNalUnitsList //otherwise, when Next good NAL decoding, this corrupt NAL is considered as normal NAL and lead to decoder crash ForceClearCurrentNal (pCurAu); if (uiAvailNalNum > 1) { pCurAu->uiEndPos = uiAvailNalNum - 2; if (pCtx->eErrorConMethod == 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; //Sub-clause 7.1.4.1.1 temporal_id if (pLastNalHdrExt->uiTemporalId != pCurNalHeaderExt->uiTemporalId) { return true; } // Subclause 7.4.1.2.5 if (pLastSliceHeader->iRedundantPicCnt < pCurSliceHeader->iRedundantPicCnt) return false; else if (pLastSliceHeader->iRedundantPicCnt > pCurSliceHeader->iRedundantPicCnt) return true; // Subclause G7.4.1.2.4 if (pLastNalHdrExt->uiDependencyId < pCurNalHeaderExt->uiDependencyId) return false; else if (pLastNalHdrExt->uiDependencyId > pCurNalHeaderExt->uiDependencyId) return true; if (pLastNalHdrExt->uiQualityId < pCurNalHeaderExt->uiQualityId) return false; else if (pLastNalHdrExt->uiQualityId > pCurNalHeaderExt->uiQualityId) return true; // Subclause 7.4.1.2.4 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->pActiveLayerSps[kpCurNalHeaderExt->uiDependencyId] != NULL && pCtx->pActiveLayerSps[kpCurNalHeaderExt->uiDependencyId] != kpSps) { return true; // the active sps changed, new sequence begins, so the current au is ready } //Sub-clause 7.1.4.1.1 temporal_id if (kpLastNalHeaderExt->uiTemporalId != kpCurNalHeaderExt->uiTemporalId) { return true; } if (kpLastSliceHeader->iFrameNum != kpCurSliceHeader->iFrameNum)