extern "C" void DumpDependencyRec (SPicture* pCurPicture, const char* kpFileName, const int8_t kiDid, bool bAppend) { WelsFileHandle* pDumpRecFile = NULL; int32_t iWrittenSize = 0; const char* openMode = bAppend ? "ab" : "wb"; if (NULL == pCurPicture || NULL == kpFileName || kiDid >= MAX_DEPENDENCY_LAYER) return; if (strlen (kpFileName) > 0) // confirmed_safe_unsafe_usage pDumpRecFile = WelsFopen (kpFileName, openMode); else { char sDependencyRecFileName[16] = {0}; WelsSnprintf (sDependencyRecFileName, 16, "rec%d.yuv", kiDid); // confirmed_safe_unsafe_usage pDumpRecFile = WelsFopen (sDependencyRecFileName, openMode); } if (NULL != pDumpRecFile && bAppend) WelsFseek (pDumpRecFile, 0, SEEK_END); if (NULL != pDumpRecFile) { int32_t i = 0; int32_t j = 0; const int32_t kiStrideY = pCurPicture->iLineSize[0]; const int32_t kiLumaWidth = pCurPicture->iWidthInPixel; const int32_t kiLumaHeight = pCurPicture->iHeightInPixel; const int32_t kiChromaWidth = kiLumaWidth >> 1; const int32_t kiChromaHeight = kiLumaHeight >> 1; for (j = 0; j < kiLumaHeight; ++ j) { iWrittenSize = WelsFwrite (&pCurPicture->pData[0][j * kiStrideY], 1, kiLumaWidth, pDumpRecFile); assert (iWrittenSize == kiLumaWidth); if (iWrittenSize < kiLumaWidth) { assert (0); // make no sense for us if writing failed WelsFclose (pDumpRecFile); return; } } for (i = 1; i < I420_PLANES; ++ i) { const int32_t kiStrideUV = pCurPicture->iLineSize[i]; for (j = 0; j < kiChromaHeight; ++ j) { iWrittenSize = WelsFwrite (&pCurPicture->pData[i][j * kiStrideUV], 1, kiChromaWidth, pDumpRecFile); assert (iWrittenSize == kiChromaWidth); if (iWrittenSize < kiChromaWidth) { assert (0); // make no sense for us if writing failed WelsFclose (pDumpRecFile); return; } } } WelsFclose (pDumpRecFile); pDumpRecFile = NULL; }
DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) { if (CheckBsBuffer (m_pDecContext, kiSrcLen)) { return dsOutOfMemory; } if (kiSrcLen > 0 && kpSrc != NULL) { #ifdef OUTPUT_BITSTREAM if (m_pFBS) { WelsFwrite (kpSrc, sizeof (unsigned char), kiSrcLen, m_pFBS); WelsFflush (m_pFBS); } #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; } m_pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. m_pDecContext->eErrorConMethod = ERROR_CON_DISABLE; //add protection to disable EC here. if (!m_pDecContext->bFramePending) { //frame complete m_pDecContext->pParserBsInfo->iNalNum = 0; memset (m_pDecContext->pParserBsInfo->iNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER); } pDstInfo->iNalNum = 0; pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0; if (pDstInfo) { m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp; pDstInfo->uiOutBsTimeStamp = 0; } else { m_pDecContext->uiTimeStamp = 0; } WelsDecodeBs (m_pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo); if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) { memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo)); } m_pDecContext->bInstantDecFlag = false; //reset no-delay flag return (DECODING_STATE) m_pDecContext->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; }
extern "C" void DumpDependencyRec (SPicture* pCurPicture, const char* kpFileName, const int8_t kiDid, bool bAppend, SDqLayer* pDqLayer) { WelsFileHandle* pDumpRecFile = NULL; int32_t iWrittenSize = 0; const char* openMode = bAppend ? "ab" : "wb"; SWelsSPS* pSpsTmp = (kiDid > BASE_DEPENDENCY_ID) ? & (pDqLayer->sLayerInfo.pSubsetSpsP->pSps) : pDqLayer->sLayerInfo.pSpsP; bool bFrameCroppingFlag = pSpsTmp->bFrameCroppingFlag; SCropOffset* pFrameCrop = &pSpsTmp->sFrameCrop; if (NULL == pCurPicture || NULL == kpFileName || kiDid >= MAX_DEPENDENCY_LAYER) return; if (strlen (kpFileName) > 0) // confirmed_safe_unsafe_usage pDumpRecFile = WelsFopen (kpFileName, openMode); else { char sDependencyRecFileName[16] = {0}; WelsSnprintf (sDependencyRecFileName, 16, "rec%d.yuv", kiDid); // confirmed_safe_unsafe_usage pDumpRecFile = WelsFopen (sDependencyRecFileName, openMode); } if (NULL != pDumpRecFile && bAppend) WelsFseek (pDumpRecFile, 0, SEEK_END); if (NULL != pDumpRecFile) { int32_t i = 0; int32_t j = 0; const int32_t kiStrideY = pCurPicture->iLineSize[0]; const int32_t kiLumaWidth = bFrameCroppingFlag ? (pCurPicture->iWidthInPixel - ((pFrameCrop->iCropLeft + pFrameCrop->iCropRight) << 1)) : pCurPicture->iWidthInPixel; const int32_t kiLumaHeight = bFrameCroppingFlag ? (pCurPicture->iHeightInPixel - ((pFrameCrop->iCropTop + pFrameCrop->iCropBottom) << 1)) : pCurPicture->iHeightInPixel; const int32_t kiChromaWidth = kiLumaWidth >> 1; const int32_t kiChromaHeight = kiLumaHeight >> 1; uint8_t* pSrc = NULL; pSrc = bFrameCroppingFlag ? (pCurPicture->pData[0] + kiStrideY * (pFrameCrop->iCropTop << 1) + (pFrameCrop->iCropLeft << 1)) : pCurPicture->pData[0]; for (j = 0; j < kiLumaHeight; ++ j) { iWrittenSize = WelsFwrite (pSrc + j * kiStrideY, 1, kiLumaWidth, pDumpRecFile); assert (iWrittenSize == kiLumaWidth); if (iWrittenSize < kiLumaWidth) { assert (0); // make no sense for us if writing failed WelsFclose (pDumpRecFile); return; } } for (i = 1; i < I420_PLANES; ++ i) { const int32_t kiStrideUV = pCurPicture->iLineSize[i]; pSrc = bFrameCroppingFlag ? (pCurPicture->pData[i] + kiStrideUV * pFrameCrop->iCropTop + pFrameCrop->iCropLeft) : pCurPicture->pData[i]; for (j = 0; j < kiChromaHeight; ++ j) { iWrittenSize = WelsFwrite (pSrc + j * kiStrideUV, 1, kiChromaWidth, pDumpRecFile); assert (iWrittenSize == kiChromaWidth); if (iWrittenSize < kiChromaWidth) { assert (0); // make no sense for us if writing failed WelsFclose (pDumpRecFile); return; } } } WelsFclose (pDumpRecFile); pDumpRecFile = NULL; }