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); }} void CWelsDecoder::BufferingReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo) { if (pDstInfo->iBufferStatus == 0) { return; } m_bIsBaseline = pCtx->pSps->uiProfileIdc == 66 || pCtx->pSps->uiProfileIdc == 83; if (!m_bIsBaseline) { if (m_sReoderingStatus.iNumOfPicts && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin) { m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC > IMinInt32) { m_sPictInfoList[i].bLastGOP = true; } } } else { if (m_sReoderingStatus.iNumOfPicts > 0) { //This can happen when decoder moves to next GOP without being able to decoder first picture PicOrderCntLsb = 0 bool hasGOPChanged = false; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC == pCtx->pSliceHeader->iPicOrderCntLsb) { hasGOPChanged = true; break; } } if (hasGOPChanged) { m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC > IMinInt32) { m_sPictInfoList[i].bLastGOP = true; } } } } } } for (int32_t i = 0; i < 16; ++i) { if (m_sPictInfoList[i].iPOC == IMinInt32) { memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo)); m_sPictInfoList[i].iPOC = pCtx->pSliceHeader->iPicOrderCntLsb; m_sPictInfoList[i].uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp; m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx; if (GetThreadCount (pCtx) <= 1) ++pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount; m_sPictInfoList[i].bLastGOP = false; m_iLastBufferedIdx = i; pDstInfo->iBufferStatus = 0; ++m_sReoderingStatus.iNumOfPicts; if (i > m_sReoderingStatus.iLargestBufferedPicIndex) { m_sReoderingStatus.iLargestBufferedPicIndex = i; } break; } }} void CWelsDecoder::ReleaseBufferedReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo) { PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff; if (pCtx == NULL && m_iThreadCount <= 1) { pCtx = m_pDecThrCtx[0].pCtx; } if (!m_bIsBaseline && m_sReoderingStatus.iLastGOPRemainPicts > 0) { m_sReoderingStatus.iMinPOC = IMinInt32; int32_t firstValidIdx = -1; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) { m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; m_sReoderingStatus.iPictInfoIndex = i; firstValidIdx = i; break; } } for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (i == firstValidIdx) continue; if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC && m_sPictInfoList[i].bLastGOP) { m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; m_sReoderingStatus.iPictInfoIndex = i; } } m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;#if defined (_DEBUG)#ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC, m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);#endif#endif memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = pDstInfo->pDst[0]; ppDst[1] = pDstInfo->pDst[1]; ppDst[2] = pDstInfo->pDst[2]; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]; --pPic->iRefCount; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; m_sReoderingStatus.iMinPOC = IMinInt32; --m_sReoderingStatus.iNumOfPicts; --m_sReoderingStatus.iLastGOPRemainPicts; if (m_sReoderingStatus.iLastGOPRemainPicts == 0) { m_sReoderingStatus.iLastWrittenPOC = IMinInt32; } return; } if (m_sReoderingStatus.iNumOfPicts && m_bIsBaseline) { uint32_t uiDecodingTimeStamp = 0; int32_t firstValidIdx = -1; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC > IMinInt32) { uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp; m_sReoderingStatus.iPictInfoIndex = i; firstValidIdx = i; break; } } for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (i == firstValidIdx) continue; if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) { uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp; m_sReoderingStatus.iPictInfoIndex = i; } } if (uiDecodingTimeStamp > 0) {#if defined (_DEBUG)#ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC, uiDecodingTimeStamp);#endif#endif memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = pDstInfo->pDst[0]; ppDst[1] = pDstInfo->pDst[1]; ppDst[2] = pDstInfo->pDst[2]; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]; --pPic->iRefCount; --m_sReoderingStatus.iNumOfPicts; } return; } if (m_sReoderingStatus.iNumOfPicts > 0) { m_sReoderingStatus.iMinPOC = IMinInt32; int32_t firstValidIdx = -1; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) { m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; m_sReoderingStatus.iPictInfoIndex = i; firstValidIdx = i; break; } } for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (i == firstValidIdx) continue; if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) { m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; m_sReoderingStatus.iPictInfoIndex = i; } } } if (m_sReoderingStatus.iMinPOC > IMinInt32) { int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC; bool isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32 && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1) || m_sReoderingStatus.iMinPOC < iLastPOC; if (isReady) { m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC;#if defined (_DEBUG)#ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC, m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp);#endif#endif memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = pDstInfo->pDst[0]; ppDst[1] = pDstInfo->pDst[1]; ppDst[2] = pDstInfo->pDst[2]; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]; --pPic->iRefCount; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; m_sReoderingStatus.iMinPOC = IMinInt32; --m_sReoderingStatus.iNumOfPicts; } }} DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (PWelsDecoderContext pDecContext, unsigned char** ppDst, SBufferInfo* pDstInfo) { DECODING_STATE iRet = dsErrorFree; if (pDstInfo->iBufferStatus == 1) { m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83; if (!m_bIsBaseline) { BufferingReadyPicture (pDecContext, ppDst, pDstInfo); ReleaseBufferedReadyPicture (pDecContext, ppDst, pDstInfo); } } return iRet;} DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) { PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx; if (pDecContext == NULL || pDecContext->pParam == NULL) { if (m_pWelsTrace != NULL) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n"); } return dsInitialOptExpected; } if (!pDecContext->pParam->bParseOnly) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n"); pDecContext->iErrorCode |= dsInvalidArgument; return dsInvalidArgument; } int64_t iEnd, iStart = WelsTime(); if (CheckBsBuffer (pDecContext, kiSrcLen)) { if (ResetDecoder (pDecContext)) 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 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. pDecContext->bEndOfStreamFlag = true; pDecContext->bInstantDecFlag = true; } pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here. pDecContext->iFeedbackNalRefIdc = -1; //initialize if (!pDecContext->bFramePending) { //frame complete pDecContext->pParserBsInfo->iNalNum = 0; memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER); } pDstInfo->iNalNum = 0; pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0; if (pDstInfo) { pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp; pDstInfo->uiOutBsTimeStamp = 0; } else { pDecContext->uiTimeStamp = 0; } WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo); if (pDecContext->iErrorCode & dsOutOfMemory) { if (ResetDecoder (pDecContext)) return dsOutOfMemory; return dsErrorFree; } if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) { memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo)); if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count pDecContext->pDecoderStatistics->uiDecodedFrameCount++; if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t ResetDecStatNums (pDecContext->pDecoderStatistics); pDecContext->pDecoderStatistics->uiDecodedFrameCount++; } } } pDecContext->bInstantDecFlag = false; //reset no-delay flag if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode); pDecContext->bPrintFrameErrorTraceFlag = false; } iEnd = WelsTime(); pDecContext->dDecTime += (iEnd - iStart) / 1e3; return (DECODING_STATE)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;} DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) { sThreadCtx.pCtx->bHasNewSps = false; sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag; sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput; sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp; bool bPicBuffChanged = false; if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) { CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx); sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber; if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) { bPicBuffChanged = true; sThreadCtx.pCtx->pPicBuff = m_pPicBuff; sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL; sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel; sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel; } } //if threadCount > 1, then each thread must contain exact one complete frame. if (GetThreadCount (sThreadCtx.pCtx) > 1) { sThreadCtx.pCtx->pAccessUnitList->uiAvailUnitsNum = 0; sThreadCtx.pCtx->pAccessUnitList->uiActualUnitsNum = 0; } int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst, &sThreadCtx.sDstInfo); int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo); if (ERR_NONE != iErr) { return (DECODING_STATE) (iRet | iErr); } if (sThreadCtx.pCtx->bNewSeqBegin) { m_pPicBuff = sThreadCtx.pCtx->pPicBuff; } else if (bPicBuffChanged) { InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4); } m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag; m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput; return (DECODING_STATE)iErr;}/** Run decoding picture in separate thread.*/ int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) { int state = dsErrorFree; int32_t i, j; int32_t signal = 0; //serial using of threads if (m_DecCtxActiveCount < m_iThreadCount) { signal = m_DecCtxActiveCount; } else { signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum; } WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); for (i = 0; i < m_DecCtxActiveCount; ++i) { if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) { m_pDecThrCtxActive[i] = NULL; for (j = i; j < m_DecCtxActiveCount - 1; j++) { m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1]; m_pDecThrCtxActive[j + 1] = NULL; } --m_DecCtxActiveCount; break; } } m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal]; if (m_pLastDecThrCtx != NULL) { m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx; } m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc); m_pDecThrCtx[signal].kiSrcLen = kiSrcLen; m_pDecThrCtx[signal].ppDst = ppDst; memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo)); ParseAccessUnit (m_pDecThrCtx[signal]); if (m_iThreadCount > 1) { m_pLastDecThrCtx = &m_pDecThrCtx[signal]; } m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN; RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated); // wait early picture if (m_DecCtxActiveCount >= m_iThreadCount) { WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle); } return state;} } // namespace WelsDec using namespace WelsDec;/** WelsGetDecoderCapability* @return: DecCapability information*/int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) { memset (pDecCapability, 0, sizeof (SDecoderCapability)); pDecCapability->iProfileIdc = 66; //Baseline pDecCapability->iProfileIop = 0xE0; //11100000b pDecCapability->iLevelIdc = 32; //level_idc = 3.2 pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2 pDecCapability->iMaxFs = 5120; //from level_idc = 3.2 pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2 pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2 pDecCapability->iMaxBr = 20000; //from level_idc = 3.2 pDecCapability->bRedPicCap = 0; //not support redundant pic return ERR_NONE;}/* WINAPI is indeed in prefix due to sync to application layer callings!! */ /** WelsCreateDecoder* @return: success in return 0, otherwise failed.*/long WelsCreateDecoder (ISVCDecoder** ppDecoder) { if (NULL == ppDecoder) { return ERR_INVALID_PARAMETERS; } *ppDecoder = new CWelsDecoder(); if (NULL == *ppDecoder) { return ERR_MALLOC_FAILED; } return ERR_NONE;} /** WelsDestroyDecoder*/void WelsDestroyDecoder (ISVCDecoder* pDecoder) { if (NULL != pDecoder) { delete (CWelsDecoder*)pDecoder; }}Lines 1001–1498 of 1498. Previous lines
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); } } void CWelsDecoder::BufferingReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo) { if (pDstInfo->iBufferStatus == 0) { return; } m_bIsBaseline = pCtx->pSps->uiProfileIdc == 66 || pCtx->pSps->uiProfileIdc == 83; if (!m_bIsBaseline) { if (m_sReoderingStatus.iNumOfPicts && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb && pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->bNewSeqBegin) { m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC > IMinInt32) { m_sPictInfoList[i].bLastGOP = true; } } } else { if (m_sReoderingStatus.iNumOfPicts > 0) { //This can happen when decoder moves to next GOP without being able to decoder first picture PicOrderCntLsb = 0 bool hasGOPChanged = false; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC == pCtx->pSliceHeader->iPicOrderCntLsb) { hasGOPChanged = true; break; } } if (hasGOPChanged) { m_sReoderingStatus.iLastGOPRemainPicts = m_sReoderingStatus.iNumOfPicts; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC > IMinInt32) { m_sPictInfoList[i].bLastGOP = true; } } } } } } for (int32_t i = 0; i < 16; ++i) { if (m_sPictInfoList[i].iPOC == IMinInt32) { memcpy (&m_sPictInfoList[i].sBufferInfo, pDstInfo, sizeof (SBufferInfo)); m_sPictInfoList[i].iPOC = pCtx->pSliceHeader->iPicOrderCntLsb; m_sPictInfoList[i].uiDecodingTimeStamp = pCtx->uiDecodingTimeStamp; m_sPictInfoList[i].iPicBuffIdx = pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iPicBuffIdx; if (GetThreadCount (pCtx) <= 1) ++pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iRefCount; m_sPictInfoList[i].bLastGOP = false; m_iLastBufferedIdx = i; pDstInfo->iBufferStatus = 0; ++m_sReoderingStatus.iNumOfPicts; if (i > m_sReoderingStatus.iLargestBufferedPicIndex) { m_sReoderingStatus.iLargestBufferedPicIndex = i; } break; } } } void CWelsDecoder::ReleaseBufferedReadyPicture (PWelsDecoderContext pCtx, unsigned char** ppDst, SBufferInfo* pDstInfo) { PPicBuff pPicBuff = pCtx ? pCtx->pPicBuff : m_pPicBuff; if (pCtx == NULL && m_iThreadCount <= 1) { pCtx = m_pDecThrCtx[0].pCtx; } if (!m_bIsBaseline && m_sReoderingStatus.iLastGOPRemainPicts > 0) { m_sReoderingStatus.iMinPOC = IMinInt32; int32_t firstValidIdx = -1; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].bLastGOP) { m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; m_sReoderingStatus.iPictInfoIndex = i; firstValidIdx = i; break; } } for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (i == firstValidIdx) continue; if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC && m_sPictInfoList[i].bLastGOP) { m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; m_sReoderingStatus.iPictInfoIndex = i; } } m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC; #if defined (_DEBUG) #ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC, m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp); #endif #endif memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = pDstInfo->pDst[0]; ppDst[1] = pDstInfo->pDst[1]; ppDst[2] = pDstInfo->pDst[2]; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]; --pPic->iRefCount; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; m_sReoderingStatus.iMinPOC = IMinInt32; --m_sReoderingStatus.iNumOfPicts; --m_sReoderingStatus.iLastGOPRemainPicts; if (m_sReoderingStatus.iLastGOPRemainPicts == 0) { m_sReoderingStatus.iLastWrittenPOC = IMinInt32; } return; } if (m_sReoderingStatus.iNumOfPicts && m_bIsBaseline) { uint32_t uiDecodingTimeStamp = 0; int32_t firstValidIdx = -1; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sPictInfoList[i].iPOC > IMinInt32) { uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp; m_sReoderingStatus.iPictInfoIndex = i; firstValidIdx = i; break; } } for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (i == firstValidIdx) continue; if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].uiDecodingTimeStamp < uiDecodingTimeStamp) { uiDecodingTimeStamp = m_sPictInfoList[i].uiDecodingTimeStamp; m_sReoderingStatus.iPictInfoIndex = i; } } if (uiDecodingTimeStamp > 0) { #if defined (_DEBUG) #ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC, uiDecodingTimeStamp); #endif #endif memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = pDstInfo->pDst[0]; ppDst[1] = pDstInfo->pDst[1]; ppDst[2] = pDstInfo->pDst[2]; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]; --pPic->iRefCount; --m_sReoderingStatus.iNumOfPicts; } return; } if (m_sReoderingStatus.iNumOfPicts > 0) { m_sReoderingStatus.iMinPOC = IMinInt32; int32_t firstValidIdx = -1; for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (m_sReoderingStatus.iMinPOC == IMinInt32 && m_sPictInfoList[i].iPOC > IMinInt32) { m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; m_sReoderingStatus.iPictInfoIndex = i; firstValidIdx = i; break; } } for (int32_t i = 0; i <= m_sReoderingStatus.iLargestBufferedPicIndex; ++i) { if (i == firstValidIdx) continue; if (m_sPictInfoList[i].iPOC > IMinInt32 && m_sPictInfoList[i].iPOC < m_sReoderingStatus.iMinPOC) { m_sReoderingStatus.iMinPOC = m_sPictInfoList[i].iPOC; m_sReoderingStatus.iPictInfoIndex = i; } } } if (m_sReoderingStatus.iMinPOC > IMinInt32) { int32_t iLastPOC = pCtx != NULL ? pCtx->pSliceHeader->iPicOrderCntLsb : m_sPictInfoList[m_iLastBufferedIdx].iPOC; bool isReady = (m_sReoderingStatus.iLastWrittenPOC > IMinInt32 && m_sReoderingStatus.iMinPOC - m_sReoderingStatus.iLastWrittenPOC <= 1) || m_sReoderingStatus.iMinPOC < iLastPOC; if (isReady) { m_sReoderingStatus.iLastWrittenPOC = m_sReoderingStatus.iMinPOC; #if defined (_DEBUG) #ifdef _MOTION_VECTOR_DUMP_ fprintf (stderr, "Output POC: #%d uiDecodingTimeStamp=%d\n", m_sReoderingStatus.iLastWrittenPOC, m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].uiDecodingTimeStamp); #endif #endif memcpy (pDstInfo, &m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].sBufferInfo, sizeof (SBufferInfo)); ppDst[0] = pDstInfo->pDst[0]; ppDst[1] = pDstInfo->pDst[1]; ppDst[2] = pDstInfo->pDst[2]; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPOC = IMinInt32; PPicture pPic = pPicBuff->ppPic[m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].iPicBuffIdx]; --pPic->iRefCount; m_sPictInfoList[m_sReoderingStatus.iPictInfoIndex].bLastGOP = false; m_sReoderingStatus.iMinPOC = IMinInt32; --m_sReoderingStatus.iNumOfPicts; } } } DECODING_STATE CWelsDecoder::ReorderPicturesInDisplay (PWelsDecoderContext pDecContext, unsigned char** ppDst, SBufferInfo* pDstInfo) { DECODING_STATE iRet = dsErrorFree; if (pDstInfo->iBufferStatus == 1) { m_bIsBaseline = pDecContext->pSps->uiProfileIdc == 66 || pDecContext->pSps->uiProfileIdc == 83; if (!m_bIsBaseline) { BufferingReadyPicture (pDecContext, ppDst, pDstInfo); ReleaseBufferedReadyPicture (pDecContext, ppDst, pDstInfo); } } return iRet; } DECODING_STATE CWelsDecoder::DecodeParser (const unsigned char* kpSrc, const int kiSrcLen, SParserBsInfo* pDstInfo) { PWelsDecoderContext pDecContext = m_pDecThrCtx[0].pCtx; if (pDecContext == NULL || pDecContext->pParam == NULL) { if (m_pWelsTrace != NULL) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "Call DecodeParser without Initialize.\n"); } return dsInitialOptExpected; } if (!pDecContext->pParam->bParseOnly) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "bParseOnly should be true for this API calling! \n"); pDecContext->iErrorCode |= dsInvalidArgument; return dsInvalidArgument; } int64_t iEnd, iStart = WelsTime(); if (CheckBsBuffer (pDecContext, kiSrcLen)) { if (ResetDecoder (pDecContext)) 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 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. pDecContext->bEndOfStreamFlag = true; pDecContext->bInstantDecFlag = true; } pDecContext->iErrorCode = dsErrorFree; //initialize at the starting of AU decoding. pDecContext->pParam->eEcActiveIdc = ERROR_CON_DISABLE; //add protection to disable EC here. pDecContext->iFeedbackNalRefIdc = -1; //initialize if (!pDecContext->bFramePending) { //frame complete pDecContext->pParserBsInfo->iNalNum = 0; memset (pDecContext->pParserBsInfo->pNalLenInByte, 0, MAX_NAL_UNITS_IN_LAYER); } pDstInfo->iNalNum = 0; pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0; if (pDstInfo) { pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp; pDstInfo->uiOutBsTimeStamp = 0; } else { pDecContext->uiTimeStamp = 0; } WelsDecodeBs (pDecContext, kpSrc, kiSrcLen, NULL, NULL, pDstInfo); if (pDecContext->iErrorCode & dsOutOfMemory) { if (ResetDecoder (pDecContext)) return dsOutOfMemory; return dsErrorFree; } if (!pDecContext->bFramePending && pDecContext->pParserBsInfo->iNalNum) { memcpy (pDstInfo, pDecContext->pParserBsInfo, sizeof (SParserBsInfo)); if (pDecContext->iErrorCode == ERR_NONE) { //update statistics: decoding frame count pDecContext->pDecoderStatistics->uiDecodedFrameCount++; if (pDecContext->pDecoderStatistics->uiDecodedFrameCount == 0) { //exceed max value of uint32_t ResetDecStatNums (pDecContext->pDecoderStatistics); pDecContext->pDecoderStatistics->uiDecodedFrameCount++; } } } pDecContext->bInstantDecFlag = false; //reset no-delay flag if (pDecContext->iErrorCode && pDecContext->bPrintFrameErrorTraceFlag) { WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "decode failed, failure type:%d \n", pDecContext->iErrorCode); pDecContext->bPrintFrameErrorTraceFlag = false; } iEnd = WelsTime(); pDecContext->dDecTime += (iEnd - iStart) / 1e3; return (DECODING_STATE)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; } DECODING_STATE CWelsDecoder::ParseAccessUnit (SWelsDecoderThreadCTX& sThreadCtx) { sThreadCtx.pCtx->bHasNewSps = false; sThreadCtx.pCtx->bParamSetsLostFlag = m_bParamSetsLostFlag; sThreadCtx.pCtx->bFreezeOutput = m_bFreezeOutput; sThreadCtx.pCtx->uiDecodingTimeStamp = ++m_uiDecodeTimeStamp; bool bPicBuffChanged = false; if (m_pLastDecThrCtx != NULL && sThreadCtx.pCtx->sSpsPpsCtx.iSeqId < m_pLastDecThrCtx->pCtx->sSpsPpsCtx.iSeqId) { CopySpsPps (m_pLastDecThrCtx->pCtx, sThreadCtx.pCtx); sThreadCtx.pCtx->iPicQueueNumber = m_pLastDecThrCtx->pCtx->iPicQueueNumber; if (sThreadCtx.pCtx->pPicBuff != m_pPicBuff) { bPicBuffChanged = true; sThreadCtx.pCtx->pPicBuff = m_pPicBuff; sThreadCtx.pCtx->bHaveGotMemory = m_pPicBuff != NULL; sThreadCtx.pCtx->iImgWidthInPixel = m_pLastDecThrCtx->pCtx->iImgWidthInPixel; sThreadCtx.pCtx->iImgHeightInPixel = m_pLastDecThrCtx->pCtx->iImgHeightInPixel; } } //if threadCount > 1, then each thread must contain exact one complete frame. if (GetThreadCount (sThreadCtx.pCtx) > 1) { sThreadCtx.pCtx->pAccessUnitList->uiAvailUnitsNum = 0; sThreadCtx.pCtx->pAccessUnitList->uiActualUnitsNum = 0; } int32_t iRet = DecodeFrame2WithCtx (sThreadCtx.pCtx, sThreadCtx.kpSrc, sThreadCtx.kiSrcLen, sThreadCtx.ppDst, &sThreadCtx.sDstInfo); int32_t iErr = InitConstructAccessUnit (sThreadCtx.pCtx, &sThreadCtx.sDstInfo); if (ERR_NONE != iErr) { return (DECODING_STATE) (iRet | iErr); } if (sThreadCtx.pCtx->bNewSeqBegin) { m_pPicBuff = sThreadCtx.pCtx->pPicBuff; } else if (bPicBuffChanged) { InitialDqLayersContext (sThreadCtx.pCtx, sThreadCtx.pCtx->pSps->iMbWidth << 4, sThreadCtx.pCtx->pSps->iMbHeight << 4); } m_bParamSetsLostFlag = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bParamSetsLostFlag; m_bFreezeOutput = sThreadCtx.pCtx->bNewSeqBegin ? false : sThreadCtx.pCtx->bFreezeOutput; return (DECODING_STATE)iErr; } /* * Run decoding picture in separate thread. */ int CWelsDecoder::ThreadDecodeFrameInternal (const unsigned char* kpSrc, const int kiSrcLen, unsigned char** ppDst, SBufferInfo* pDstInfo) { int state = dsErrorFree; int32_t i, j; int32_t signal = 0; //serial using of threads if (m_DecCtxActiveCount < m_iThreadCount) { signal = m_DecCtxActiveCount; } else { signal = m_pDecThrCtxActive[0]->sThreadInfo.uiThrNum; } WAIT_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); for (i = 0; i < m_DecCtxActiveCount; ++i) { if (m_pDecThrCtxActive[i] == &m_pDecThrCtx[signal]) { m_pDecThrCtxActive[i] = NULL; for (j = i; j < m_DecCtxActiveCount - 1; j++) { m_pDecThrCtxActive[j] = m_pDecThrCtxActive[j + 1]; m_pDecThrCtxActive[j + 1] = NULL; } --m_DecCtxActiveCount; break; } } m_pDecThrCtxActive[m_DecCtxActiveCount++] = &m_pDecThrCtx[signal]; if (m_pLastDecThrCtx != NULL) { m_pDecThrCtx[signal].pCtx->pLastThreadCtx = m_pLastDecThrCtx; } m_pDecThrCtx[signal].kpSrc = const_cast<uint8_t*> (kpSrc); m_pDecThrCtx[signal].kiSrcLen = kiSrcLen; m_pDecThrCtx[signal].ppDst = ppDst; memcpy (&m_pDecThrCtx[signal].sDstInfo, pDstInfo, sizeof (SBufferInfo)); ParseAccessUnit (m_pDecThrCtx[signal]); if (m_iThreadCount > 1) { m_pLastDecThrCtx = &m_pDecThrCtx[signal]; } m_pDecThrCtx[signal].sThreadInfo.uiCommand = WELS_DEC_THREAD_COMMAND_RUN; RELEASE_SEMAPHORE (&m_pDecThrCtx[signal].sThreadInfo.sIsActivated); // wait early picture if (m_DecCtxActiveCount >= m_iThreadCount) { WAIT_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle, WELS_DEC_THREAD_WAIT_INFINITE); RELEASE_SEMAPHORE (&m_pDecThrCtxActive[0]->sThreadInfo.sIsIdle); } return state; } } // namespace WelsDec using namespace WelsDec; /* * WelsGetDecoderCapability * @return: DecCapability information */ int WelsGetDecoderCapability (SDecoderCapability* pDecCapability) { memset (pDecCapability, 0, sizeof (SDecoderCapability)); pDecCapability->iProfileIdc = 66; //Baseline pDecCapability->iProfileIop = 0xE0; //11100000b pDecCapability->iLevelIdc = 32; //level_idc = 3.2 pDecCapability->iMaxMbps = 216000; //from level_idc = 3.2 pDecCapability->iMaxFs = 5120; //from level_idc = 3.2 pDecCapability->iMaxCpb = 20000; //from level_idc = 3.2 pDecCapability->iMaxDpb = 20480; //from level_idc = 3.2 pDecCapability->iMaxBr = 20000; //from level_idc = 3.2 pDecCapability->bRedPicCap = 0; //not support redundant pic return ERR_NONE; } /* WINAPI is indeed in prefix due to sync to application layer callings!! */ /* * WelsCreateDecoder * @return: success in return 0, otherwise failed. */ long WelsCreateDecoder (ISVCDecoder** ppDecoder) { if (NULL == ppDecoder) { return ERR_INVALID_PARAMETERS; } *ppDecoder = new CWelsDecoder(); if (NULL == *ppDecoder) { return ERR_MALLOC_FAILED; } return ERR_NONE; } /* * WelsDestroyDecoder */ void WelsDestroyDecoder (ISVCDecoder* pDecoder) { if (NULL != pDecoder) { delete (CWelsDecoder*)pDecoder; } }