! ************************************************************************************* * \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 iSrcNalLe
| 106 | ************************************************************************************* |
| 107 | */ |
| 108 | uint8_t* ParseNalHeader (PWelsDecoderContext pCtx, SNalUnitHeader* pNalUnitHeader, uint8_t* pSrcRbsp, |
| 109 | int32_t iSrcRbspLen, uint8_t* pSrcNal, int32_t iSrcNalLen, int32_t* pConsumedBytes) { |
| 110 | PNalUnit pCurNal = NULL; |
| 111 | uint8_t* pNal = pSrcRbsp; |
| 112 | int32_t iNalSize = iSrcRbspLen; |
| 113 | PBitStringAux pBs = NULL; |
| 114 | bool bExtensionFlag = false; |
| 115 | int32_t iErr = ERR_NONE; |
| 116 | int32_t iBitSize = 0; |
| 117 | SDataBuffer* pSavedData = &pCtx->sSavedData; |
| 118 | SLogContext* pLogCtx = & (pCtx->sLogCtx); |
| 119 | pNalUnitHeader->eNalUnitType = NAL_UNIT_UNSPEC_0;//SHOULD init it. because pCtx->sCurNalHead is common variable. |
| 120 | |
| 121 | //remove the consecutive ZERO at the end of current NAL in the reverse order.--2011.6.1 |
| 122 | { |
| 123 | int32_t iIndex = iSrcRbspLen - 1; |
| 124 | uint8_t uiBsZero = 0; |
| 125 | while (iIndex >= 0) { |
| 126 | uiBsZero = pSrcRbsp[iIndex]; |
| 127 | if (0 == uiBsZero) { |
| 128 | --iNalSize; |
| 129 | ++ (*pConsumedBytes); |
| 130 | --iIndex; |
| 131 | } else { |
| 132 | break; |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | pNalUnitHeader->uiForbiddenZeroBit = (uint8_t) (pNal[0] >> 7); // uiForbiddenZeroBit |
| 138 | if (pNalUnitHeader->uiForbiddenZeroBit) { //2010.4.14 |
| 139 | pCtx->iErrorCode |= dsBitstreamError; |
| 140 | return NULL; //uiForbiddenZeroBit should always equal to 0 |
| 141 | } |
| 142 | |
| 143 | pNalUnitHeader->uiNalRefIdc = (uint8_t) (pNal[0] >> 5); // uiNalRefIdc |
| 144 | pNalUnitHeader->eNalUnitType = (EWelsNalUnitType) (pNal[0] & 0x1f); // eNalUnitType |
| 145 | |
| 146 | ++pNal; |
| 147 | --iNalSize; |
| 148 | ++ (*pConsumedBytes); |
| 149 | |
| 150 | if (! (IS_SEI_NAL (pNalUnitHeader->eNalUnitType) || IS_SPS_NAL (pNalUnitHeader->eNalUnitType) |
| 151 | || IS_AU_DELIMITER_NAL (pNalUnitHeader->eNalUnitType) || pCtx->sSpsPpsCtx.bSpsExistAheadFlag)) { |
| 152 | if (pCtx->bPrintFrameErrorTraceFlag && pCtx->sSpsPpsCtx.iSpsErrorIgnored == 0) { |
| 153 | WelsLog (pLogCtx, WELS_LOG_WARNING, |
| 154 | "parse_nal(), no exist Sequence Parameter Sets ahead of sequence when try to decode NAL(type:%d).", |
| 155 | pNalUnitHeader->eNalUnitType); |
| 156 | } else { |
| 157 | pCtx->sSpsPpsCtx.iSpsErrorIgnored++; |
| 158 | } |
| 159 | pCtx->pDecoderStatistics->iSpsNoExistNalNum++; |
| 160 | pCtx->iErrorCode = dsNoParamSets; |
| 161 | return NULL; |
| 162 | } |
| 163 | pCtx->sSpsPpsCtx.iSpsErrorIgnored = 0; |
| 164 | if (! (IS_SEI_NAL (pNalUnitHeader->eNalUnitType) || IS_PARAM_SETS_NALS (pNalUnitHeader->eNalUnitType) |
| 165 | || IS_AU_DELIMITER_NAL (pNalUnitHeader->eNalUnitType) || pCtx->sSpsPpsCtx.bPpsExistAheadFlag)) { |
no test coverage detected