//if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) { //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo)); //ppDst[0] = ppTmpDst[0]; //ppDst[1] = ppTmpDst[1]; //ppDst[2] = ppTmpDst[2]; //} return (DECODING_STATE)iRet;} DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) { if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) { if (m_pWelsTrace != NULL) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n"); } return dsInitialOptExpected; } if (m_pDecContext->pParam->bParseOnly) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n"); m_pDecContext->iErrorCode |= dsInvalidArgument; return dsInvalidArgument; } if (CheckBsBuffer (m_pDecContext, kiSrcLen)) { if (ResetDecoder()) return dsOutOfMemory; return dsErrorFree; } 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 m_pDecContext->iFeedbackNalRefIdc = -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 & dsRefLost) && m_pDecContext->eSliceType == B_SLICE) { if (ResetDecoder()) return dsRefLost; return dsErrorFree; } if (m_pDecContext->iErrorCode & dsOutOfMemory) { if (ResetDecoder()) return dsOutOfMemory; return dsErrorFree; } //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->pParam->eEcActiveIdc == 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->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) { //TODO after dec status updated m_pDecContext->iErrorCode |= dsDataErrorConcealed; 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; OutputStatisticsLog (m_pDecContext->sDecoderStatistics); #ifdef _PICTURE_REORDERING_ ReorderPicturesInDisplay (ppDst, pDstInfo);#endif 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++; } OutputStatisticsLog (m_pDecContext->sDecoderStatistics); } iEnd = WelsTime(); m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; #ifdef _PICTURE_REORDERING_ ReorderPicturesInDisplay (ppDst, pDstInfo);#endif return dsErrorFree;} DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst, SBufferInfo* pDstInfo) { if (m_pDecContext->bEndOfStreamFlag && m_iNumOfPicts > 0) { m_iMinPOC = sIMinInt32; for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) { if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } } } if (m_iMinPOC > sIMinInt32) { m_LastWrittenPOC = m_iMinPOC;#if defined (_DEBUG)#ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);#endif#endif memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0]; ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1]; ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2]; m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32; if (m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false; m_iMinPOC = sIMinInt32; --m_iNumOfPicts; } return dsErrorFree;} void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) { if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0) && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \ uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \ uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \ uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \ iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \ uiProfile=%d, uiLevel=%d, \ iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,", sDecoderStatistics.uiWidth, sDecoderStatistics.uiHeight, sDecoderStatistics.fAverageFrameSpeedInMs, sDecoderStatistics.fActualAverageFrameSpeedInMs, sDecoderStatistics.uiDecodedFrameCount, sDecoderStatistics.uiResolutionChangeTimes, sDecoderStatistics.uiIDRCorrectNum, sDecoderStatistics.uiAvgEcRatio, sDecoderStatistics.uiAvgEcPropRatio, sDecoderStatistics.uiEcIDRNum, sDecoderStatistics.uiEcFrameNum, sDecoderStatistics.uiIDRLostNum, sDecoderStatistics.uiFreezingIDRNum, sDecoderStatistics.uiFreezingNonIDRNum, sDecoderStatistics.iAvgLumaQp, sDecoderStatistics.iSpsReportErrorNum, sDecoderStatistics.iSubSpsReportErrorNum, sDecoderStatistics.iPpsReportErrorNum, sDecoderStatistics.iSpsNoExistNalNum, sDecoderStatistics.iSubSpsNoExistNalNum, sDecoderStatistics.iPpsNoExistNalNum, sDecoderStatistics.uiProfile, sDecoderStatistics.uiLevel, sDecoderStatistics.iCurrentActiveSpsId, sDecoderStatistics.iCurrentActivePpsId); }} DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (unsigned char** ppDst, SBufferInfo* pDstInfo) { DECODING_STATE iRet = dsErrorFree; if (pDstInfo->iBufferStatus == 1 && m_pDecContext->pSps->uiProfileIdc != 66) { if (m_pDecContext->pSliceHeader->iPicOrderCntLsb == 0) { if (m_iNumOfPicts > 0) { m_iLastGOPRemainPicts = m_iNumOfPicts; for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC > sIMinInt32) { m_sPictInfoList[i].bLastGOP = true; } } } } for (int32_t i = 0; i < 16; ++i) { if (m_sPictInfoList[i].iPOC == sIMinInt32) { memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo)); m_sPictInfoList[i].pData[0] = ppDst[0]; m_sPictInfoList[i].pData[1] = ppDst[1]; m_sPictInfoList[i].pData[2] = ppDst[2]; m_sPictInfoList[i].iPOC = m_pDecContext->pSliceHeader->iPicOrderCntLsb; m_sPictInfoList[i].iPicBuffIdx = m_pDecContext->pPicBuff->iCurrentIdx; m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[i].iPicBuffIdx]->bAvailableFlag = false; m_sPictInfoList[i].bLastGOP = false; pDstInfo->iBufferStatus = 0; ++m_iNumOfPicts; if (i > m_iLargestBufferedPicIndex) { m_iLargestBufferedPicIndex = i; } break; } } if (m_iLastGOPRemainPicts > 0) { m_iMinPOC = sIMinInt32; for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) { if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].bLastGOP) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC && m_sPictInfoList[i].bLastGOP) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } } m_LastWrittenPOC = m_iMinPOC;#if defined (_DEBUG)#ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);#endif#endif memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0]; ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1]; ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2]; m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32; if (m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false; m_iMinPOC = sIMinInt32; --m_iNumOfPicts; --m_iLastGOPRemainPicts; if (m_iLastGOPRemainPicts == 0) { m_LastWrittenPOC = sIMinInt32; } return iRet; } if (m_iNumOfPicts > 0) { m_iMinPOC = sIMinInt32; for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) { if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } } } if (m_iMinPOC > sIMinInt32) { if ((m_LastWrittenPOC > sIMinInt32 && m_iMinPOC - m_LastWrittenPOC <= 1) || m_iMinPOC < m_pDecContext->pSliceHeader->iPicOrderCntLsb) { m_LastWrittenPOC = m_iMinPOC;#if defined (_DEBUG)#ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC);#endif#endif memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0]; ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1]; ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2]; m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32; if (m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false; m_iMinPOC = sIMinInt32; --m_iNumOfPicts; return iRet; } } } return iRet;} DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) { if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) { if (m_pWelsTrace != NULL) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n"); } return dsInitialOptExpected; } if (!m_pDecContext->pParam->bParseOnly) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n"); m_pDecContext->iErrorCode |= dsInvalidArgument; return dsInvalidArgument; } int64_t iEnd, iStart = WelsTime(); if (CheckBsBuffer (m_pDecContext, kiSrcLen)) { if (ResetDecoder()) return dsOutOfMemory; return dsErrorFree; } 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->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here. m_pDecContext->iFeedbackNalRefIdc = -1; //initialize if (!m_pDecContext->bFramePending) { //frame complete m_pDecContext->pParserBsInfo->iNalNum = 0; memset (m_pDecContext->pParserBsInfo->pNalLenInByte, 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->iErrorCode & dsOutOfMemory) { if (ResetDecoder()) return dsOutOfMemory; return dsErrorFree; } if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) { memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo)); if (m_pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++; if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t ResetDecStatNums (&m_pDecContext->sDecoderStatistics); m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++; } } } m_pDecContext->bInstantDecFlag = false; //reset no-delay flag if (m_pDecContext->iErrorCode && m_pDecContext->bPrintFrameErrorTraceFlag) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode); m_pDecContext->bPrintFrameErrorTraceFlag = false; } iEnd = WelsTime(); m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; return (DECODING_STATE) m_pDecContext->iErrorCode;} DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst, int* pStride, int& iWidth, int& iHeight) { DECODING_STATE eDecState = dsErrorFree; SBufferInfo DstInfo; memset (&DstInfo, 0, sizeof (SBufferInfo)); DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0]; DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1]; DstInfo.UsrData.sSystemBuffer.iWidth = iWidth; DstInfo.UsrData.sSystemBuffer.iHeight = iHeight; eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo); if (eDecState == dsErrorFree) { pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0]; pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1]; iWidth = DstInfo.UsrData.sSystemBuffer.iWidth; iHeight = DstInfo.UsrData.sSystemBuffer.iHeight; } return eDecState;} DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc, const int kiSrcLen, unsigned char* pDst, int iDstStride, int& iDstLen, int& iWidth, int& iHeight, int& iColorFormat) { DECODING_STATE state = dsErrorFree; return state;} void CWelsDecoder::ResetReorderingPictureBuffers() { m_iPictInfoIndex = 0; m_iMinPOC = sIMinInt32; m_iNumOfPicts = 0; m_iLastGOPRemainPicts = 0; m_LastWrittenPOC = sIMinInt32; m_iLargestBufferedPicIndex = 0; for (int32_t i = 0; i < 16; ++i) { m_sPictInfoList[i].bLastGOP = false; m_sPictInfoList[i].iPOC = sIMinInt32; }} } // namespace WelsDec using namespace WelsDec;/*Lines 501–1000 of 1046. Previous lines Load more
//if ((pDstInfo->iBufferStatus == 0) && (sTmpBufferInfo.iBufferStatus == 1)) { //memcpy (pDstInfo, &sTmpBufferInfo, sizeof (SBufferInfo)); //ppDst[0] = ppTmpDst[0]; //ppDst[1] = ppTmpDst[1]; //ppDst[2] = ppTmpDst[2]; //} return (DECODING_STATE)iRet; } DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) { if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) { if (m_pWelsTrace != NULL) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeFrame2 without Initialize.\n"); } return dsInitialOptExpected; } if (m_pDecContext->pParam->bParseOnly) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be false for this API calling! \n"); m_pDecContext->iErrorCode |= dsInvalidArgument; return dsInvalidArgument; } if (CheckBsBuffer (m_pDecContext, kiSrcLen)) { if (ResetDecoder()) return dsOutOfMemory; return dsErrorFree; } 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 m_pDecContext->iFeedbackNalRefIdc = -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 & dsRefLost) && m_pDecContext->eSliceType == B_SLICE) { if (ResetDecoder()) return dsRefLost; return dsErrorFree; } if (m_pDecContext->iErrorCode & dsOutOfMemory) { if (ResetDecoder()) return dsOutOfMemory; return dsErrorFree; } //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->pParam->eEcActiveIdc == 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->pParam->eEcActiveIdc != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) { //TODO after dec status updated m_pDecContext->iErrorCode |= dsDataErrorConcealed; 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; OutputStatisticsLog (m_pDecContext->sDecoderStatistics); #ifdef _PICTURE_REORDERING_ ReorderPicturesInDisplay (ppDst, pDstInfo); #endif 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++; } OutputStatisticsLog (m_pDecContext->sDecoderStatistics); } iEnd = WelsTime(); m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; #ifdef _PICTURE_REORDERING_ ReorderPicturesInDisplay (ppDst, pDstInfo); #endif return dsErrorFree; } DECODING_STATE CWelsDecoder::FlushFrame (unsigned char** ppDst, SBufferInfo* pDstInfo) { if (m_pDecContext->bEndOfStreamFlag && m_iNumOfPicts > 0) { m_iMinPOC = sIMinInt32; for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) { if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } } } if (m_iMinPOC > sIMinInt32) { m_LastWrittenPOC = m_iMinPOC; #if defined (_DEBUG) #ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC); #endif #endif memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0]; ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1]; ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2]; m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32; if (m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false; m_iMinPOC = sIMinInt32; --m_iNumOfPicts; } return dsErrorFree; } void CWelsDecoder::OutputStatisticsLog (SDecoderStatistics& sDecoderStatistics) { if ((sDecoderStatistics.uiDecodedFrameCount > 0) && (sDecoderStatistics.iStatisticsLogInterval > 0) && ((sDecoderStatistics.uiDecodedFrameCount % sDecoderStatistics.iStatisticsLogInterval) == 0)) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "DecoderStatistics: uiWidth=%d, uiHeight=%d, fAverageFrameSpeedInMs=%.1f, fActualAverageFrameSpeedInMs=%.1f, \ uiDecodedFrameCount=%d, uiResolutionChangeTimes=%d, uiIDRCorrectNum=%d, \ uiAvgEcRatio=%d, uiAvgEcPropRatio=%d, uiEcIDRNum=%d, uiEcFrameNum=%d, \ uiIDRLostNum=%d, uiFreezingIDRNum=%d, uiFreezingNonIDRNum=%d, iAvgLumaQp=%d, \ iSpsReportErrorNum=%d, iSubSpsReportErrorNum=%d, iPpsReportErrorNum=%d, iSpsNoExistNalNum=%d, iSubSpsNoExistNalNum=%d, iPpsNoExistNalNum=%d, \ uiProfile=%d, uiLevel=%d, \ iCurrentActiveSpsId=%d, iCurrentActivePpsId=%d,", sDecoderStatistics.uiWidth, sDecoderStatistics.uiHeight, sDecoderStatistics.fAverageFrameSpeedInMs, sDecoderStatistics.fActualAverageFrameSpeedInMs, sDecoderStatistics.uiDecodedFrameCount, sDecoderStatistics.uiResolutionChangeTimes, sDecoderStatistics.uiIDRCorrectNum, sDecoderStatistics.uiAvgEcRatio, sDecoderStatistics.uiAvgEcPropRatio, sDecoderStatistics.uiEcIDRNum, sDecoderStatistics.uiEcFrameNum, sDecoderStatistics.uiIDRLostNum, sDecoderStatistics.uiFreezingIDRNum, sDecoderStatistics.uiFreezingNonIDRNum, sDecoderStatistics.iAvgLumaQp, sDecoderStatistics.iSpsReportErrorNum, sDecoderStatistics.iSubSpsReportErrorNum, sDecoderStatistics.iPpsReportErrorNum, sDecoderStatistics.iSpsNoExistNalNum, sDecoderStatistics.iSubSpsNoExistNalNum, sDecoderStatistics.iPpsNoExistNalNum, sDecoderStatistics.uiProfile, sDecoderStatistics.uiLevel, sDecoderStatistics.iCurrentActiveSpsId, sDecoderStatistics.iCurrentActivePpsId); } } DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (unsigned char** ppDst, SBufferInfo* pDstInfo) { DECODING_STATE iRet = dsErrorFree; if (pDstInfo->iBufferStatus == 1 && m_pDecContext->pSps->uiProfileIdc != 66) { if (m_pDecContext->pSliceHeader->iPicOrderCntLsb == 0) { if (m_iNumOfPicts > 0) { m_iLastGOPRemainPicts = m_iNumOfPicts; for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC > sIMinInt32) { m_sPictInfoList[i].bLastGOP = true; } } } } for (int32_t i = 0; i < 16; ++i) { if (m_sPictInfoList[i].iPOC == sIMinInt32) { memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo)); m_sPictInfoList[i].pData[0] = ppDst[0]; m_sPictInfoList[i].pData[1] = ppDst[1]; m_sPictInfoList[i].pData[2] = ppDst[2]; m_sPictInfoList[i].iPOC = m_pDecContext->pSliceHeader->iPicOrderCntLsb; m_sPictInfoList[i].iPicBuffIdx = m_pDecContext->pPicBuff->iCurrentIdx; m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[i].iPicBuffIdx]->bAvailableFlag = false; m_sPictInfoList[i].bLastGOP = false; pDstInfo->iBufferStatus = 0; ++m_iNumOfPicts; if (i > m_iLargestBufferedPicIndex) { m_iLargestBufferedPicIndex = i; } break; } } if (m_iLastGOPRemainPicts > 0) { m_iMinPOC = sIMinInt32; for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) { if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].bLastGOP) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC && m_sPictInfoList[i].bLastGOP) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } } m_LastWrittenPOC = m_iMinPOC; #if defined (_DEBUG) #ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC); #endif #endif memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0]; ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1]; ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2]; m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32; if (m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false; m_iMinPOC = sIMinInt32; --m_iNumOfPicts; --m_iLastGOPRemainPicts; if (m_iLastGOPRemainPicts == 0) { m_LastWrittenPOC = sIMinInt32; } return iRet; } if (m_iNumOfPicts > 0) { m_iMinPOC = sIMinInt32; for (int32_t i = 0; i <= m_iLargestBufferedPicIndex; ++i) { if (m_iMinPOC == sIMinInt32 && m_sPictInfoList[i].iPOC > sIMinInt32) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } if (m_sPictInfoList[i].iPOC > sIMinInt32 && m_sPictInfoList[i].iPOC < m_iMinPOC) { m_iMinPOC = m_sPictInfoList[i].iPOC; m_iPictInfoIndex = i; } } } if (m_iMinPOC > sIMinInt32) { if ((m_LastWrittenPOC > sIMinInt32 && m_iMinPOC - m_LastWrittenPOC <= 1) || m_iMinPOC < m_pDecContext->pSliceHeader->iPicOrderCntLsb) { m_LastWrittenPOC = m_iMinPOC; #if defined (_DEBUG) #ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d\n", m_LastWrittenPOC); #endif #endif memcpy (pDstInfo, &m_sPictInfoList[m_iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = m_sPictInfoList[m_iPictInfoIndex].pData[0]; ppDst[1] = m_sPictInfoList[m_iPictInfoIndex].pData[1]; ppDst[2] = m_sPictInfoList[m_iPictInfoIndex].pData[2]; m_sPictInfoList[m_iPictInfoIndex].iPOC = sIMinInt32; if (m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx < m_pDecContext->pPicBuff->iCapacity) m_pDecContext->pPicBuff->ppPic[m_sPictInfoList[m_iPictInfoIndex].iPicBuffIdx]->bAvailableFlag = true; m_sPictInfoList[m_iPictInfoIndex].bLastGOP = false; m_iMinPOC = sIMinInt32; --m_iNumOfPicts; return iRet; } } } return iRet; } DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) { if (m_pDecContext == NULL || m_pDecContext->pParam == NULL) { if (m_pWelsTrace != NULL) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n"); } return dsInitialOptExpected; } if (!m_pDecContext->pParam->bParseOnly) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n"); m_pDecContext->iErrorCode |= dsInvalidArgument; return dsInvalidArgument; } int64_t iEnd, iStart = WelsTime(); if (CheckBsBuffer (m_pDecContext, kiSrcLen)) { if (ResetDecoder()) return dsOutOfMemory; return dsErrorFree; } 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->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here. m_pDecContext->iFeedbackNalRefIdc = -1; //initialize if (!m_pDecContext->bFramePending) { //frame complete m_pDecContext->pParserBsInfo->iNalNum = 0; memset (m_pDecContext->pParserBsInfo->pNalLenInByte, 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->iErrorCode & dsOutOfMemory) { if (ResetDecoder()) return dsOutOfMemory; return dsErrorFree; } if (!m_pDecContext->bFramePending && m_pDecContext->pParserBsInfo->iNalNum) { memcpy (pDstInfo, m_pDecContext->pParserBsInfo, sizeof (SParserBsInfo)); if (m_pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++; if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t ResetDecStatNums (&m_pDecContext->sDecoderStatistics); m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++; } } } m_pDecContext->bInstantDecFlag = false; //reset no-delay flag if (m_pDecContext->iErrorCode && m_pDecContext->bPrintFrameErrorTraceFlag) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", m_pDecContext->iErrorCode); m_pDecContext->bPrintFrameErrorTraceFlag = false; } iEnd = WelsTime(); m_pDecContext->dDecTime += (iEnd - iStart) / 1e3; return (DECODING_STATE) m_pDecContext->iErrorCode; } DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst, int* pStride, int& iWidth, int& iHeight) { DECODING_STATE eDecState = dsErrorFree; SBufferInfo DstInfo; memset (&DstInfo, 0, sizeof (SBufferInfo)); DstInfo.UsrData.sSystemBuffer.iStride[0] = pStride[0]; DstInfo.UsrData.sSystemBuffer.iStride[1] = pStride[1]; DstInfo.UsrData.sSystemBuffer.iWidth = iWidth; DstInfo.UsrData.sSystemBuffer.iHeight = iHeight; eDecState = DecodeFrame2 (kpSrc, kiSrcLen, ppDst, &DstInfo); if (eDecState == dsErrorFree) { pStride[0] = DstInfo.UsrData.sSystemBuffer.iStride[0]; pStride[1] = DstInfo.UsrData.sSystemBuffer.iStride[1]; iWidth = DstInfo.UsrData.sSystemBuffer.iWidth; iHeight = DstInfo.UsrData.sSystemBuffer.iHeight; } return eDecState; } DECODING_STATE CWelsDecoder::DecodeFrameEx (const unsigned char* kpSrc, const int kiSrcLen, unsigned char* pDst, int iDstStride, int& iDstLen, int& iWidth, int& iHeight, int& iColorFormat) { DECODING_STATE state = dsErrorFree; return state; } void CWelsDecoder::ResetReorderingPictureBuffers() { m_iPictInfoIndex = 0; m_iMinPOC = sIMinInt32; m_iNumOfPicts = 0; m_iLastGOPRemainPicts = 0; m_LastWrittenPOC = sIMinInt32; m_iLargestBufferedPicIndex = 0; for (int32_t i = 0; i < 16; ++i) { m_sPictInfoList[i].bLastGOP = false; m_sPictInfoList[i].iPOC = sIMinInt32; } } } // namespace WelsDec using namespace WelsDec; /*