/*! ************************************************************************************* * \brief First entrance to decoding core interface. * * \param pCtx decoder context * \param pBufBs bit streaming buffer * \param kBsLen size in bytes length of bit streaming buffer input * \param ppDst picture payload data to be output * \param pDstBufInfo buf information of ouput data * * \return 0 - successed * \return 1 - failed * * \note N/A ************************************************************************************* */ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen, uint8_t** ppDst, SBufferInfo* pDstBufInfo, SParserBsInfo* pDstBsInfo) { if (!pCtx->bEndOfStreamFlag) { SDataBuffer* pRawData = &pCtx->sRawData; SDataBuffer* pSavedData = NULL; int32_t iSrcIdx = 0; //the index of source bit-stream till now after parsing one or more NALs int32_t iSrcConsumed = 0; // consumed bit count of source bs int32_t iDstIdx = 0; //the size of current NAL after 0x03 removal and 00 00 01 removal int32_t iSrcLength = 0; //the total size of current AU or NAL int32_t iRet = 0; int32_t iConsumedBytes = 0; int32_t iOffset = 0; uint8_t* pSrcNal = NULL; uint8_t* pDstNal = NULL; uint8_t* pNalPayload = NULL; if (NULL == DetectStartCodePrefix (kpBsBuf, &iOffset, kiBsLen)) { //CAN'T find the 00 00 01 start prefix from the source buffer pCtx->iErrorCode |= dsBitstreamError; return dsBitstreamError; } pSrcNal = const_cast<uint8_t*> (kpBsBuf) + iOffset; iSrcLength = kiBsLen - iOffset; if ((kiBsLen + 4) > (pRawData->pEnd - pRawData->pCurPos)) { pRawData->pCurPos = pRawData->pHead; } if (pCtx->bParseOnly) { pSavedData = &pCtx->sSavedData; if ((kiBsLen + 4) > (pSavedData->pEnd - pSavedData->pCurPos)) { pSavedData->pCurPos = pSavedData->pHead; } } //copy raw data from source buffer (application) to raw data buffer (codec inside) //0x03 removal and extract all of NAL Unit from current raw data pDstNal = pRawData->pCurPos; while (iSrcConsumed < iSrcLength) { if ((2 + iSrcConsumed < iSrcLength) && (0 == LD16 (pSrcNal + iSrcIdx)) && ((pSrcNal[2 + iSrcIdx] == 0x03) || (pSrcNal[2 + iSrcIdx] == 0x01))) { if (pSrcNal[2 + iSrcIdx] == 0x03) { ST16 (pDstNal + iDstIdx, 0); iDstIdx += 2; iSrcIdx += 3; iSrcConsumed += 3; } else { iConsumedBytes = 0; pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] = 0; // set 4 reserved bytes to zero pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes); if (pNalPayload) { //parse correct if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) { CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo); } if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType)) { iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3); } if (pCtx->bAuReadyFlag) { ConstructAccessUnit (pCtx, ppDst, pDstBufInfo); if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif if (dsOutOfMemory & pCtx->iErrorCode) { return pCtx->iErrorCode; } } } } if (iRet) { iRet = 0; if (dsNoParamSets & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif } return pCtx->iErrorCode; } pDstNal += (iDstIdx + 4); //init, increase 4 reserved zero bytes, used to store the next NAL if ((iSrcLength - iSrcConsumed + 4) > (pRawData->pEnd - pDstNal)) { pDstNal = pRawData->pCurPos = pRawData->pHead; } else { pRawData->pCurPos = pDstNal; } pSrcNal += iSrcIdx + 3; iSrcConsumed += 3; iSrcIdx = 0; iDstIdx = 0; //reset 0, used to statistic the length of next NAL } continue; } pDstNal[iDstIdx++] = pSrcNal[iSrcIdx++]; iSrcConsumed++; } //last NAL decoding iConsumedBytes = 0; pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] = 0; // set 4 reserved bytes to zero pRawData->pCurPos = pDstNal + iDstIdx + 4; //init, increase 4 reserved zero bytes, used to store the next NAL pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes); if (pNalPayload) { //parse correct if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) { CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo); } if (IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType)) { iRet = ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes, pSrcNal - 3, iSrcIdx + 3); } if (pCtx->bAuReadyFlag) { ConstructAccessUnit (pCtx, ppDst, pDstBufInfo); if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif return pCtx->iErrorCode; } } } if (iRet) { iRet = 0; if (dsNoParamSets & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif } return pCtx->iErrorCode; } } else { /* no supplementary picture payload input, but stored a picture */ PAccessUnit pCurAu = pCtx->pAccessUnitList; // current access unit, it will never point to NULL after decode's successful initialization if (pCurAu->uiAvailUnitsNum == 0) { return pCtx->iErrorCode; } else { pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1; ConstructAccessUnit (pCtx, ppDst, pDstBufInfo); if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif return pCtx->iErrorCode; } } } return pCtx->iErrorCode; }
/*! ************************************************************************************* * \brief First entrance to decoding core interface. * * \param pCtx decoder context * \param pBufBs bit streaming buffer * \param kBsLen size in bytes length of bit streaming buffer input * \param ppDst picture payload data to be output * \param pDstBufInfo buf information of ouput data * * \return 0 - successed * \return 1 - failed * * \note N/A ************************************************************************************* */ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen, uint8_t** ppDst, SBufferInfo* pDstBufInfo) { if (!pCtx->bEndOfStreamFlag) { SDataBuffer* pRawData = &pCtx->sRawData; int32_t iSrcIdx = 0; //the index of source bit-stream till now after parsing one or more NALs int32_t iSrcConsumed = 0; // consumed bit count of source bs int32_t iDstIdx = 0; //the size of current NAL after 0x03 removal and 00 00 01 removal int32_t iSrcLength = 0; //the total size of current AU or NAL int32_t iConsumedBytes = 0; int32_t iOffset = 0; uint8_t* pSrcNal = NULL; uint8_t* pDstNal = NULL; uint8_t* pNalPayload = NULL; if (NULL == DetectStartCodePrefix (kpBsBuf, &iOffset, kiBsLen)) { //CAN'T find the 00 00 01 start prefix from the source buffer return dsBitstreamError; } pSrcNal = const_cast<uint8_t*> (kpBsBuf) + iOffset; iSrcLength = kiBsLen - iOffset; if ((kiBsLen + 4) > (pRawData->pEnd - pRawData->pCurPos)) { pRawData->pCurPos = pRawData->pHead; } //copy raw data from source buffer (application) to raw data buffer (codec inside) //0x03 removal and extract all of NAL Unit from current raw data pDstNal = pRawData->pCurPos + 4; //4-bytes used to write the length of current NAL rbsp while (iSrcConsumed < iSrcLength) { if ((2 + iSrcConsumed < iSrcLength) && (0 == LD16 (pSrcNal + iSrcIdx)) && ((pSrcNal[2 + iSrcIdx] == 0x03) || (pSrcNal[2 + iSrcIdx] == 0x01))) { if (pSrcNal[2 + iSrcIdx] == 0x03) { ST16 (pDstNal + iDstIdx, 0); iDstIdx += 2; iSrcIdx += 3; iSrcConsumed += 3; } else { GetValueOf4Bytes (pDstNal - 4, iDstIdx); //pDstNal-4 (non-aligned by 4) in Solaris10(SPARC). Given value by byte. iConsumedBytes = 0; pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes); if (pCtx->bAuReadyFlag) { ConstructAccessUnit (pCtx, ppDst, pDstBufInfo); if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif ResetParameterSetsState (pCtx); if (dsOutOfMemory & pCtx->iErrorCode) { return pCtx->iErrorCode; } } } if ((IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) || IS_SEI_NAL (pCtx->sCurNalHead.eNalUnitType)) && pNalPayload) { if (ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes)) { if (dsNoParamSets & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif ResetParameterSetsState (pCtx); } return pCtx->iErrorCode; } } pDstNal += iDstIdx; //update current position if ((iSrcLength - iSrcConsumed + 4) > (pRawData->pEnd - pDstNal)) { pRawData->pCurPos = pRawData->pHead; } else { pRawData->pCurPos = pDstNal; } pDstNal = pRawData->pCurPos + 4; //init, 4 bytes used to store the next NAL pSrcNal += iSrcIdx + 3; iSrcConsumed += 3; iSrcIdx = 0; iDstIdx = 0; //reset 0, used to statistic the length of next NAL } continue; } pDstNal[iDstIdx++] = pSrcNal[iSrcIdx++]; iSrcConsumed++; } //last NAL decoding GetValueOf4Bytes (pDstNal - 4, iDstIdx); //pDstNal-4 (non-aligned by 4) in Solaris10(SPARC). Given value by byte. iConsumedBytes = 0; pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes); if (pCtx->bAuReadyFlag) { ConstructAccessUnit (pCtx, ppDst, pDstBufInfo); if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif ResetParameterSetsState (pCtx); return pCtx->iErrorCode; } } if ((IS_PARAM_SETS_NALS (pCtx->sCurNalHead.eNalUnitType) || IS_SEI_NAL (pCtx->sCurNalHead.eNalUnitType)) && pNalPayload) { if (ParseNonVclNal (pCtx, pNalPayload, iDstIdx - iConsumedBytes)) { if (dsNoParamSets & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif ResetParameterSetsState (pCtx); } return pCtx->iErrorCode; } } pDstNal += iDstIdx; pRawData->pCurPos = pDstNal; //init the pCurPos for next NAL(s) storage } else { /* no supplementary picture payload input, but stored a picture */ PAccessUnit pCurAu = pCtx->pAccessUnitList; // current access unit, it will never point to NULL after decode's successful initialization if (pCurAu->uiAvailUnitsNum == 0) { return pCtx->iErrorCode; } else { pCtx->pAccessUnitList->uiEndPos = pCtx->pAccessUnitList->uiAvailUnitsNum - 1; ConstructAccessUnit (pCtx, ppDst, pDstBufInfo); if ((dsOutOfMemory | dsNoParamSets) & pCtx->iErrorCode) { #ifdef LONG_TERM_REF pCtx->bParamSetsLostFlag = true; #else pCtx->bReferenceLostAtT0Flag = true; #endif ResetParameterSetsState (pCtx); return pCtx->iErrorCode; } } } return pCtx->iErrorCode; }
DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc, const int kiSrcLen, void** ppDst, SBufferInfo* pDstInfo) { if (kiSrcLen > MAX_ACCESS_UNIT_CAPACITY - MAX_MACROBLOCK_CAPACITY) {//prevent from residual reading overflow m_pDecContext->iErrorCode |= dsOutOfMemory; IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "max AU size exceeded. Allowed size = %d, current size = %d", MAX_ACCESS_UNIT_CAPACITY, kiSrcLen); return dsOutOfMemory; } if (kiSrcLen > 0 && kpSrc != NULL) { #ifdef OUTPUT_BIT_STREAM if (m_pFBS) { WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS); WelsFflush (m_pFBS); } if (m_pFBSSize) { WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize); WelsFflush (m_pFBSSize); } #endif//OUTPUT_BIT_STREAM m_pDecContext->bEndOfStreamFlag = false; } else { //For application MODE, the error detection should be added for safe. //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL. m_pDecContext->bEndOfStreamFlag = true; } ppDst[0] = ppDst[1] = ppDst[2] = NULL; m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize memset (pDstInfo, 0, sizeof (SBufferInfo)); #ifdef LONG_TERM_REF m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR m_pDecContext->bCurAuContainLtrMarkSeFlag = false; m_pDecContext->iFrameNumOfAuMarkedLtr = 0; m_pDecContext->iFrameNum = -1; //initialize #endif m_pDecContext->iFeedbackTidInAu = -1; //initialize WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, (unsigned char**)ppDst, pDstInfo); //iErrorCode has been modified in this function if (m_pDecContext->iErrorCode) { ENalUnitType eNalType = NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently eNalType = m_pDecContext->sCurNalHead.eNalUnitType; //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss. if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) || (VIDEO_BITSTREAM_AVC == m_pDecContext->eVideoType)) { #ifdef LONG_TERM_REF m_pDecContext->bParamSetsLostFlag = true; #else m_pDecContext->bReferenceLostAtT0Flag = true; #endif ResetParameterSetsState (m_pDecContext); //initial SPS&PPS ready flag } IWelsTrace::WelsVTrace (m_pTrace, IWelsTrace::WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode); return (DECODING_STATE)m_pDecContext->iErrorCode; } return dsErrorFree; }
DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) { if (CheckBsBuffer (m_pDecContext, kiSrcLen)) { return dsOutOfMemory; } if (kiSrcLen > 0 && kpSrc != NULL) { #ifdef OUTPUT_BIT_STREAM if (m_pFBS) { WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS); WelsFflush (m_pFBS); } if (m_pFBSSize) { WelsFwrite (&kiSrcLen, sizeof (int), 1, m_pFBSSize); WelsFflush (m_pFBSSize); } #endif//OUTPUT_BIT_STREAM m_pDecContext->bEndOfStreamFlag = false; } else { //For application MODE, the error detection should be added for safe. //But for CONSOLE MODE, when decoding LAST AU, kiSrcLen==0 && kpSrc==NULL. m_pDecContext->bEndOfStreamFlag = true; m_pDecContext->bInstantDecFlag = true; } int64_t iStart, iEnd; iStart = WelsTime(); ppDst[0] = ppDst[1] = ppDst[2] = NULL; m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize unsigned long long uiInBsTimeStamp = pDstInfo->uiInBsTimeStamp; memset (pDstInfo, 0, sizeof (SBufferInfo)); pDstInfo->uiInBsTimeStamp = uiInBsTimeStamp; #ifdef LONG_TERM_REF m_pDecContext->bReferenceLostAtT0Flag = false; //initialize for LTR m_pDecContext->bCurAuContainLtrMarkSeFlag = false; m_pDecContext->iFrameNumOfAuMarkedLtr = 0; m_pDecContext->iFrameNum = -1; //initialize #endif m_pDecContext->iFeedbackTidInAu = -1; //initialize if (pDstInfo) { pDstInfo->uiOutYuvTimeStamp = 0; m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp; } else { m_pDecContext->uiTimeStamp = 0; } WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, ppDst, pDstInfo, NULL); //iErrorCode has been modified in this function m_pDecContext->bInstantDecFlag = false; //reset no-delay flag if (m_pDecContext->iErrorCode) { EWelsNalUnitType eNalType = NAL_UNIT_UNSPEC_0; //for NBR, IDR frames are expected to decode as followed if error decoding an IDR currently eNalType = m_pDecContext->sCurNalHead.eNalUnitType; if (m_pDecContext->iErrorCode & dsOutOfMemory) { ResetDecoder(); } //for AVC bitstream (excluding AVC with temporal scalability, including TP), as long as error occur, SHOULD notify upper layer key frame loss. if ((IS_PARAM_SETS_NALS (eNalType) || NAL_UNIT_CODED_SLICE_IDR == eNalType) || (VIDEO_BITSTREAM_AVC == m_pDecContext->eVideoType)) { if (m_pDecContext->eErrorConMethod == ERROR_CON_DISABLE) { #ifdef LONG_TERM_REF m_pDecContext->bParamSetsLostFlag = true; #else m_pDecContext->bReferenceLostAtT0Flag = true; #endif } } if (m_pDecContext->bPrintFrameErrorTraceFlag) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode); m_pDecContext->bPrintFrameErrorTraceFlag = false; } else { m_pDecContext->iIgnoredErrorInfoPacketCount ++; if (m_pDecContext->iIgnoredErrorInfoPacketCount == INT_MAX) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, "continuous error reached INT_MAX! Restart as 0."); m_pDecContext->iIgnoredErrorInfoPacketCount = 0; } } if ((m_pDecContext->eErrorConMethod != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) { //TODO after dec status updated m_pDecContext->iErrorCode |= dsDataErrorConcealed; // if ((m_pDecContext->sDecoderStatistics.uiWidth != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iWidth) || (m_pDecContext->sDecoderStatistics.uiHeight != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iHeight)) { m_pDecContext->sDecoderStatistics.uiResolutionChangeTimes++; m_pDecContext->sDecoderStatistics.uiWidth = pDstInfo->UsrData.sSystemBuffer.iWidth; m_pDecContext->sDecoderStatistics.uiHeight = pDstInfo->UsrData.sSystemBuffer.iHeight; } m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++; if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t ResetDecStatNums (&m_pDecContext->sDecoderStatistics); m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++; } int32_t iMbConcealedNum = m_pDecContext->iMbEcedNum + m_pDecContext->iMbEcedPropNum; m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->iMbNum == 0 ? (m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : (( m_pDecContext->sDecoderStatistics.uiAvgEcRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + (( iMbConcealedNum * 100) / m_pDecContext->iMbNum)); m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->iMbNum == 0 ? (m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) : (( m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio * m_pDecContext->sDecoderStatistics.uiEcFrameNum) + (( m_pDecContext->iMbEcedPropNum * 100) / m_pDecContext->iMbNum)); m_pDecContext->sDecoderStatistics.uiEcFrameNum += (iMbConcealedNum == 0 ? 0 : 1); m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 : m_pDecContext->sDecoderStatistics.uiAvgEcRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum; m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio = m_pDecContext->sDecoderStatistics.uiEcFrameNum == 0 ? 0 : m_pDecContext->sDecoderStatistics.uiAvgEcPropRatio / m_pDecContext->sDecoderStatistics.uiEcFrameNum; } iEnd = WelsTime(); m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; return (DECODING_STATE) m_pDecContext->iErrorCode; } // else Error free, the current codec works well if (pDstInfo->iBufferStatus == 1) { m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++; if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t ResetDecStatNums (&m_pDecContext->sDecoderStatistics); m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++; } if ((m_pDecContext->sDecoderStatistics.uiWidth != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iWidth) || (m_pDecContext->sDecoderStatistics.uiHeight != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iHeight)) { m_pDecContext->sDecoderStatistics.uiResolutionChangeTimes++; m_pDecContext->sDecoderStatistics.uiWidth = pDstInfo->UsrData.sSystemBuffer.iWidth; m_pDecContext->sDecoderStatistics.uiHeight = pDstInfo->UsrData.sSystemBuffer.iHeight; } } iEnd = WelsTime(); m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; return dsErrorFree; }