diff --git a/codec/encoder/core/inc/encoder_context.h b/codec/encoder/core/inc/encoder_context.h index 43528e8e..c90d6ca8 100644 --- a/codec/encoder/core/inc/encoder_context.h +++ b/codec/encoder/core/inc/encoder_context.h @@ -225,12 +225,12 @@ typedef struct TagWelsEncCtx { //related to Statistics int64_t uiStartTimestamp; - SEncoderStatistics sEncoderStatistics; + SEncoderStatistics sEncoderStatistics[MAX_DEPENDENCY_LAYER]; int32_t iStatisticsLogInterval; int64_t iLastStatisticsLogTs; - int64_t iTotalEncodedBytes; - int64_t iLastStatisticsBytes; - int64_t iLastStatisticsFrameCount; + int64_t iTotalEncodedBytes[MAX_DEPENDENCY_LAYER]; + int64_t iLastStatisticsBytes[MAX_DEPENDENCY_LAYER]; + int64_t iLastStatisticsFrameCount[MAX_DEPENDENCY_LAYER]; int32_t iEncoderError; WELS_MUTEX mutexEncoderError; diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index e7dd2c8f..4c12111b 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -3412,7 +3412,7 @@ int32_t ForceCodingIDR (sWelsEncCtx* pCtx) { pCtx->bCheckWindowStatusRefreshFlag = false; WelsLog (&pCtx->sLogCtx, WELS_LOG_INFO, "ForceCodingIDR at InputFrameCount=%d\n", - pCtx->sEncoderStatistics.uiInputFrameCount); + pCtx->sEncoderStatistics[0].uiInputFrameCount); return 0; } @@ -3435,7 +3435,7 @@ int32_t WelsEncoderEncodeParameterSets (sWelsEncCtx* pCtx, void* pDst) { pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->iNalCount = iCountNal; - + pLayerBsInfo->eFrameType = videoFrameTypeIDR; //pCtx->eLastNalPriority = NRI_PRI_HIGHEST; pFbi->iLayerNum = 1; pFbi->eFrameType = videoFrameTypeInvalid; @@ -3473,7 +3473,7 @@ int32_t WriteSsvcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum, pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->iNalCount = iCountNal; - + pLayerBsInfo->eFrameType = videoFrameTypeIDR; //point to next pLayerBsInfo ++ pLayerBsInfo; ++ pCtx->pOut->iLayerBsIndex; @@ -3514,7 +3514,7 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum, pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->iNalCount = iCountNal; - + pLayerBsInfo->eFrameType = videoFrameTypeIDR; //point to next pLayerBsInfo ++ pLayerBsInfo; ++ pCtx->pOut->iLayerBsIndex; @@ -3547,7 +3547,7 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum, pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->iNalCount = iCountNal; - + pLayerBsInfo->eFrameType = videoFrameTypeIDR; //point to next pLayerBsInfo ++ pLayerBsInfo; ++ pCtx->pOut->iLayerBsIndex; @@ -3595,7 +3595,7 @@ int32_t WriteSavcParaset_Listing (sWelsEncCtx* pCtx, const int32_t kiSpatialNum, pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->iNalCount = iCountNal; - + pLayerBsInfo->eFrameType = videoFrameTypeIDR; //point to next pLayerBsInfo ++ pLayerBsInfo; ++ pCtx->pOut->iLayerBsIndex; @@ -3630,7 +3630,7 @@ int32_t WriteSavcParaset_Listing (sWelsEncCtx* pCtx, const int32_t kiSpatialNum, pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->iNalCount = iCountNal; - + pLayerBsInfo->eFrameType = videoFrameTypeIDR; //point to next pLayerBsInfo ++ pLayerBsInfo; ++ pCtx->pOut->iLayerBsIndex; @@ -3745,6 +3745,9 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour pCtx->bCurFrameMarkedAsSceneLtr = false; pFbi->iLayerNum = 0; // for initialization pFbi->uiTimeStamp = pSrcPic->uiTimeStamp; + for (int32_t iNalIdx = 0; iNalIdx < MAX_LAYER_NUM_OF_FRAME; iNalIdx++) { + pFbi->sLayerInfo[iNalIdx].eFrameType = videoFrameTypeSkip; + } // perform csc/denoise/downsample/padding, generate spatial layers iSpatialNum = pCtx->pVpp->BuildSpatialPicList (pCtx, pSrcPic); if (pCtx->pFuncList->pfRc.pfWelsUpdateMaxBrWindowStatus) { @@ -3953,12 +3956,14 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour pLayerBsInfo->uiTemporalId = iCurTid; pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->iNalCount = ++ iNalIdxInLayer; + pLayerBsInfo->eFrameType = eFrameType; } // for dynamic slicing single threading.. else if ((SM_SIZELIMITED_SLICE == pParam->sSliceArgument.uiSliceMode) && (pSvcParam->iMultipleThreadIdc <= 1)) { const int32_t kiLastMbInFrame = pCtx->pCurDqLayer->sSliceEncCtx.iMbNumInFrame; pCtx->iEncoderError = WelsCodeOnePicPartition (pCtx, pFbi, pLayerBsInfo, &iNalIdxInLayer, &iLayerSize, 0, kiLastMbInFrame, 0); + pLayerBsInfo->eFrameType = eFrameType; WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS) } else { //other multi-slice uiSliceMode @@ -3984,7 +3989,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour pLayerBsInfo->uiTemporalId = pCtx->uiTemporalId; pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->iNalCount = 0; - + pLayerBsInfo->eFrameType = eFrameType; pCtx->pTaskManage->ExecuteTasks(); if (pCtx->iEncoderError) { WelsLog (pLogCtx, WELS_LOG_ERROR, @@ -4035,7 +4040,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour pLbi->uiTemporalId = pCtx->uiTemporalId; pLbi->uiQualityId = 0; pLbi->iNalCount = 0; - + pLbi->eFrameType = eFrameType; int32_t iIdx = 0; while (iIdx < kiPartitionCnt) { pCtx->pSliceThreading->pThreadPEncCtx[iIdx].pFrameBsInfo = pFbi; @@ -4103,6 +4108,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour pLayerBsInfo->uiTemporalId = iCurTid; pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->iNalCount = iNalIdxInLayer; + pLayerBsInfo->eFrameType = eFrameType; } } @@ -4281,6 +4287,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->iNalCount = 1; pLayerBsInfo->pNalLengthInByte[0] = iPaddingNalSize; + pLayerBsInfo->eFrameType = eFrameType; ++ pLayerBsInfo; ++ pCtx->pOut->iLayerBsIndex; pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; @@ -4314,6 +4321,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour "WelsEncoderEncodeExt(), Logic Error Found in Preprocess updating. ForceCodingIDR!"); //the above is to set the next frame IDR pFbi->eFrameType = eFrameType; + pLayerBsInfo->eFrameType = eFrameType; return ENC_RETURN_CORRECTED; } @@ -4326,9 +4334,10 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour if (ENC_RETURN_CORRECTED == pCtx->iEncoderError) { pCtx->pVpp->UpdateSpatialPictures (pCtx, pSvcParam, iCurTid, (pSpatialIndexMap + iSpatialIdx)->iDid); ForceCodingIDR (pCtx); - WelsLog (pLogCtx, WELS_LOG_WARNING, "WelsEncoderEncodeExt(), Logic Error Found in temporal level. ForceCodingIDR!"); + WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), Logic Error Found in temporal level. ForceCodingIDR!"); //the above is to set the next frame IDR pFbi->eFrameType = eFrameType; + pLayerBsInfo->eFrameType = eFrameType; return ENC_RETURN_CORRECTED; } @@ -4509,7 +4518,8 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa int32_t iTmpPpsIdList[MAX_DQ_LAYER_NUM * MAX_PPS_COUNT]; uint16_t uiTmpIdrPicId = (*ppCtx)->uiIdrPicId;//this is for LTR! - SEncoderStatistics sTempEncoderStatistics = (*ppCtx)->sEncoderStatistics; + SEncoderStatistics sTempEncoderStatistics[MAX_DEPENDENCY_LAYER]; + memcpy (sTempEncoderStatistics, (*ppCtx)->sEncoderStatistics, sizeof (sTempEncoderStatistics)); SExistingParasetList sExistingParasetList; SExistingParasetList* pExistingParasetList = NULL; @@ -4568,8 +4578,7 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa (*ppCtx)->uiIdrPicId = uiTmpIdrPicId; //for sEncoderStatistics - (*ppCtx)->sEncoderStatistics = sTempEncoderStatistics; - + memcpy ((*ppCtx)->sEncoderStatistics, sTempEncoderStatistics, sizeof (sTempEncoderStatistics)); //load back the needed structure for eSpsPpsIdStrategy if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy)) { memcpy ((*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable, @@ -4934,7 +4943,6 @@ int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx, pLayerBsInfo->uiTemporalId = pCtx->uiTemporalId; pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->iNalCount = iNalIdxInLayer; - return ENC_RETURN_SUCCESS; } } // namespace WelsEnc diff --git a/codec/encoder/plus/inc/welsEncoderExt.h b/codec/encoder/plus/inc/welsEncoderExt.h index eedad3b2..792dc863 100644 --- a/codec/encoder/plus/inc/welsEncoderExt.h +++ b/codec/encoder/plus/inc/welsEncoderExt.h @@ -99,8 +99,8 @@ class CWelsH264SVCEncoder : public ISVCEncoder { private: int InitializeInternal (SWelsSvcCodingParam* argv); void TraceParamInfo(SEncParamExt *pParam); - void LogStatistics (const int64_t kiCurrentFrameTs); - void UpdateStatistics(const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType, const int32_t kiCurrentFrameSize, const int64_t kiCurrentFrameMs); + void LogStatistics (const int64_t kiCurrentFrameTs,int32_t iMaxDid); + void UpdateStatistics(const int64_t kiCurrentFrameTs, SFrameBSInfo* pBsInfo, const int64_t kiCurrentFrameMs); sWelsEncCtx* m_pEncContext; diff --git a/codec/encoder/plus/src/welsEncoderExt.cpp b/codec/encoder/plus/src/welsEncoderExt.cpp index 39f0b043..992d5287 100644 --- a/codec/encoder/plus/src/welsEncoderExt.cpp +++ b/codec/encoder/plus/src/welsEncoderExt.cpp @@ -412,7 +412,7 @@ int CWelsH264SVCEncoder ::EncodeFrameInternal (const SSourcePicture* pSrcPic, S return cmUnknownReason; } - UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo->eFrameType, pBsInfo->iFrameSizeInBytes, kiCurrentFrameMs); + UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo, kiCurrentFrameMs); ///////////////////for test #ifdef OUTPUT_BIT_STREAM @@ -481,7 +481,7 @@ int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR) { ForceCodingIDR (m_pEncContext); - m_pEncContext->sEncoderStatistics.uiIDRReqNum++; + m_pEncContext->sEncoderStatistics[0].uiIDRReqNum++; return 0; } @@ -545,102 +545,125 @@ void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) { } } -void CWelsH264SVCEncoder::LogStatistics (const int64_t kiCurrentFrameTs) { - SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics); - WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, - "EncoderStatistics: %dx%d, SpeedInMs: %f, fAverageFrameRate=%f, " - "LastFrameRate=%f, LatestBitRate=%d, LastFrameQP=%d, uiInputFrameCount=%d, uiSkippedFrameCount=%d, " - "uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA, iTotalEncodedBytes=%" PRId64 - " at Ts = %" PRId64, - pStatistics->uiWidth, pStatistics->uiHeight, - pStatistics->fAverageFrameSpeedInMs, pStatistics->fAverageFrameRate, - pStatistics->fLatestFrameRate, pStatistics->uiBitRate, pStatistics->uiAverageFrameQP, - pStatistics->uiInputFrameCount, pStatistics->uiSkippedFrameCount, - pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRReqNum, pStatistics->uiIDRSentNum, - m_pEncContext->iTotalEncodedBytes, kiCurrentFrameTs); +void CWelsH264SVCEncoder::LogStatistics (const int64_t kiCurrentFrameTs, int32_t iMaxDid) { + for (int32_t iDid = 0; iDid <= iMaxDid; iDid++) { + SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics[iDid]); + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, + "EncoderStatistics: SpatialId = %d,%dx%d, SpeedInMs: %f, fAverageFrameRate=%f, " + "LastFrameRate=%f, LatestBitRate=%d, LastFrameQP=%d, uiInputFrameCount=%d, uiSkippedFrameCount=%d, " + "uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA, iTotalEncodedBytes=%" PRId64 + " at Ts = %" PRId64, + iDid, pStatistics->uiWidth, pStatistics->uiHeight, + pStatistics->fAverageFrameSpeedInMs, pStatistics->fAverageFrameRate, + pStatistics->fLatestFrameRate, pStatistics->uiBitRate, pStatistics->uiAverageFrameQP, + pStatistics->uiInputFrameCount, pStatistics->uiSkippedFrameCount, + pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRReqNum, pStatistics->uiIDRSentNum, + m_pEncContext->iTotalEncodedBytes[iDid], kiCurrentFrameTs); + } } -void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType, - const int32_t kiCurrentFrameSize, const int64_t kiCurrentFrameMs) { - SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics); +void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, SFrameBSInfo* pBsInfo, + const int64_t kiCurrentFrameMs) { int32_t iMaxDid = m_pEncContext->pSvcParam->iSpatialLayerNum - 1; - if ((0 != pStatistics->uiWidth && 0 != pStatistics->uiHeight) - && (pStatistics->uiWidth != (unsigned int) m_pEncContext->pSvcParam->sDependencyLayers[iMaxDid].iActualWidth - || pStatistics->uiHeight != (unsigned int) m_pEncContext->pSvcParam->sDependencyLayers[iMaxDid].iActualHeight)) { - pStatistics->uiResolutionChangeTimes ++; - } - pStatistics->uiWidth = m_pEncContext->pSvcParam->sDependencyLayers[iMaxDid].iActualWidth; - pStatistics->uiHeight = m_pEncContext->pSvcParam->sDependencyLayers[iMaxDid].iActualHeight; - - const bool kbCurrentFrameSkipped = (videoFrameTypeSkip == eFrameType); - pStatistics->uiInputFrameCount ++; - pStatistics->uiSkippedFrameCount += (kbCurrentFrameSkipped ? 1 : 0); - int32_t iProcessedFrameCount = pStatistics->uiInputFrameCount - pStatistics->uiSkippedFrameCount; - if (!kbCurrentFrameSkipped && iProcessedFrameCount != 0) { - pStatistics->fAverageFrameSpeedInMs += (kiCurrentFrameMs - pStatistics->fAverageFrameSpeedInMs) / iProcessedFrameCount; - } - - // rate control related - if (0 != m_pEncContext->uiStartTimestamp) { - if (kiCurrentFrameTs > m_pEncContext->uiStartTimestamp + 800) { - pStatistics->fAverageFrameRate = (static_cast (pStatistics->uiInputFrameCount) * 1000 / - (kiCurrentFrameTs - m_pEncContext->uiStartTimestamp)); - } - } else { - m_pEncContext->uiStartTimestamp = kiCurrentFrameTs; - } - //pStatistics->fLatestFrameRate = m_pEncContext->pWelsSvcRc->fLatestFrameRate; //TODO: finish the calculation in RC - //pStatistics->uiBitRate = m_pEncContext->pWelsSvcRc->iActualBitRate; //TODO: finish the calculation in RC - pStatistics->uiAverageFrameQP = m_pEncContext->pWelsSvcRc->iAverageFrameQp; - - if (videoFrameTypeIDR == eFrameType || videoFrameTypeI == eFrameType) { - pStatistics->uiIDRSentNum ++; - } - if (m_pEncContext->pLtr->bLTRMarkingFlag) { - pStatistics->uiLTRSentNum ++; - } - - m_pEncContext->iTotalEncodedBytes += kiCurrentFrameSize; - - const int32_t kiDeltaFrames = static_cast (pStatistics->uiInputFrameCount - - m_pEncContext->iLastStatisticsFrameCount); - if (kiDeltaFrames > (m_pEncContext->pSvcParam->fMaxFrameRate * 2)) { - const int64_t kiTimeDiff = kiCurrentFrameTs - pStatistics->iStatisticsTs; - if (kiTimeDiff) { - pStatistics->fLatestFrameRate = static_cast ((pStatistics->uiInputFrameCount - - m_pEncContext->iLastStatisticsFrameCount) * 1000 / - kiTimeDiff); - pStatistics->uiBitRate = static_cast ((m_pEncContext->iTotalEncodedBytes - - m_pEncContext->iLastStatisticsBytes) * 8 * 1000 / kiTimeDiff); - - if (WELS_ABS (pStatistics->fLatestFrameRate - m_pEncContext->pSvcParam->fMaxFrameRate) > 30) { - WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, - "Actual input fLatestFrameRate = %f is quite different from framerate in setting %f, please check setting or timestamp unit (ms), cur_Ts = %" - PRId64 " start_Ts = %" PRId64, - pStatistics->fLatestFrameRate, m_pEncContext->pSvcParam->fMaxFrameRate, kiCurrentFrameTs, - static_cast (pStatistics->iStatisticsTs)); - } - - if (m_pEncContext->pSvcParam->iRCMode == RC_QUALITY_MODE || m_pEncContext->pSvcParam->iRCMode == RC_BITRATE_MODE) { - if ((pStatistics->fLatestFrameRate > 0) - && WELS_ABS (m_pEncContext->pSvcParam->fMaxFrameRate - pStatistics->fLatestFrameRate) > 5) { - WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, - "Actual input framerate %f is different from framerate in setting %f, suggest to use other rate control modes", - pStatistics->fLatestFrameRate, m_pEncContext->pSvcParam->fMaxFrameRate); + SLayerBSInfo* pLayerInfo = &pBsInfo->sLayerInfo[0]; + for (int32_t iDid = 0; iDid <= iMaxDid; iDid++) { + EVideoFrameType eFrameType = videoFrameTypeInvalid; + int32_t kiCurrentFrameSize = 0; + if (pBsInfo->eFrameType == videoFrameTypeSkip) { + eFrameType = videoFrameTypeSkip; + } else { + for (int32_t iLayerNum = 0; iLayerNum < pBsInfo->iLayerNum; iLayerNum++) { + pLayerInfo = &pBsInfo->sLayerInfo[iLayerNum]; + if ((pLayerInfo->uiLayerType == VIDEO_CODING_LAYER) && (pLayerInfo->uiSpatialId == iDid)) { + eFrameType = pLayerInfo->eFrameType; + for (int32_t iNalIdx = 0; iNalIdx < pLayerInfo->iNalCount; iNalIdx++) { + kiCurrentFrameSize += pLayerInfo->pNalLengthInByte[iNalIdx]; + } } } + + } + SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics[iDid]); + + + if ((0 != pStatistics->uiWidth && 0 != pStatistics->uiHeight) + && (pStatistics->uiWidth != (unsigned int) m_pEncContext->pSvcParam->sDependencyLayers[iDid].iActualWidth + || pStatistics->uiHeight != (unsigned int) m_pEncContext->pSvcParam->sDependencyLayers[iDid].iActualHeight)) { + pStatistics->uiResolutionChangeTimes ++; + } + pStatistics->uiWidth = m_pEncContext->pSvcParam->sDependencyLayers[iDid].iActualWidth; + pStatistics->uiHeight = m_pEncContext->pSvcParam->sDependencyLayers[iDid].iActualHeight; + + const bool kbCurrentFrameSkipped = (videoFrameTypeSkip == eFrameType); + pStatistics->uiInputFrameCount ++; + pStatistics->uiSkippedFrameCount += (kbCurrentFrameSkipped ? 1 : 0); + int32_t iProcessedFrameCount = pStatistics->uiInputFrameCount - pStatistics->uiSkippedFrameCount; + if (!kbCurrentFrameSkipped && iProcessedFrameCount != 0) { + pStatistics->fAverageFrameSpeedInMs += (kiCurrentFrameMs - pStatistics->fAverageFrameSpeedInMs) / iProcessedFrameCount; + } + // rate control related + if (0 != m_pEncContext->uiStartTimestamp) { + if (kiCurrentFrameTs > m_pEncContext->uiStartTimestamp + 800) { + pStatistics->fAverageFrameRate = (static_cast (pStatistics->uiInputFrameCount) * 1000 / + (kiCurrentFrameTs - m_pEncContext->uiStartTimestamp)); + } + } else { + m_pEncContext->uiStartTimestamp = kiCurrentFrameTs; + } + //pStatistics->fLatestFrameRate = m_pEncContext->pWelsSvcRc->fLatestFrameRate; //TODO: finish the calculation in RC + //pStatistics->uiBitRate = m_pEncContext->pWelsSvcRc->iActualBitRate; //TODO: finish the calculation in RC + pStatistics->uiAverageFrameQP = m_pEncContext->pWelsSvcRc->iAverageFrameQp; + + if (videoFrameTypeIDR == eFrameType || videoFrameTypeI == eFrameType) { + pStatistics->uiIDRSentNum ++; + } + if (m_pEncContext->pLtr->bLTRMarkingFlag) { + pStatistics->uiLTRSentNum ++; } - // update variables - pStatistics->iStatisticsTs = kiCurrentFrameTs; - m_pEncContext->iLastStatisticsBytes = m_pEncContext->iTotalEncodedBytes; - m_pEncContext->iLastStatisticsFrameCount = pStatistics->uiInputFrameCount; + m_pEncContext->iTotalEncodedBytes[iDid] += kiCurrentFrameSize; - //TODO: the following statistics will be calculated and added later - //pStatistics->uiLTRSentNum + const int32_t kiDeltaFrames = static_cast (pStatistics->uiInputFrameCount - + m_pEncContext->iLastStatisticsFrameCount[iDid]); + if (kiDeltaFrames > (m_pEncContext->pSvcParam->fMaxFrameRate * 2)) { + const int64_t kiTimeDiff = kiCurrentFrameTs - pStatistics->iStatisticsTs; + if (kiTimeDiff) { + pStatistics->fLatestFrameRate = static_cast ((pStatistics->uiInputFrameCount - + m_pEncContext->iLastStatisticsFrameCount[iDid]) * 1000 / + kiTimeDiff); + pStatistics->uiBitRate = static_cast ((m_pEncContext->iTotalEncodedBytes[iDid] - + m_pEncContext->iLastStatisticsBytes[iDid]) * 8 * 1000 / kiTimeDiff); + + if (WELS_ABS (pStatistics->fLatestFrameRate - m_pEncContext->pSvcParam->fMaxFrameRate) > 30) { + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, + "Actual input fLatestFrameRate = %f is quite different from framerate in setting %f, please check setting or timestamp unit (ms), cur_Ts = %" + PRId64 " start_Ts = %" PRId64, + pStatistics->fLatestFrameRate, m_pEncContext->pSvcParam->fMaxFrameRate, kiCurrentFrameTs, + static_cast (pStatistics->iStatisticsTs)); + } + + if (m_pEncContext->pSvcParam->iRCMode == RC_QUALITY_MODE || m_pEncContext->pSvcParam->iRCMode == RC_BITRATE_MODE) { + if ((pStatistics->fLatestFrameRate > 0) + && WELS_ABS (m_pEncContext->pSvcParam->fMaxFrameRate - pStatistics->fLatestFrameRate) > 5) { + WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING, + "Actual input framerate %f is different from framerate in setting %f, suggest to use other rate control modes", + pStatistics->fLatestFrameRate, m_pEncContext->pSvcParam->fMaxFrameRate); + } + } + } + + // update variables + pStatistics->iStatisticsTs = kiCurrentFrameTs; + m_pEncContext->iLastStatisticsBytes[iDid] = m_pEncContext->iTotalEncodedBytes[iDid]; + m_pEncContext->iLastStatisticsFrameCount[iDid] = pStatistics->uiInputFrameCount; + + //TODO: the following statistics will be calculated and added later + //pStatistics->uiLTRSentNum + } } if (m_pEncContext->iStatisticsLogInterval > 0) { + SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics[0]); const int64_t kiTimeDiff = kiCurrentFrameTs - m_pEncContext->iLastStatisticsLogTs; if ((kiTimeDiff > m_pEncContext->iStatisticsLogInterval) || (0 == pStatistics->uiInputFrameCount % 300)) { if (WELS_ABS (pStatistics->fAverageFrameRate - m_pEncContext->pSvcParam->fMaxFrameRate) > 30) { @@ -650,7 +673,7 @@ void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVid pStatistics->fAverageFrameRate, m_pEncContext->pSvcParam->fMaxFrameRate, m_pEncContext->uiStartTimestamp); } - LogStatistics (kiCurrentFrameTs); + LogStatistics (kiCurrentFrameTs, iMaxDid); m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs; } } @@ -788,7 +811,7 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) { //LogStatistics WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, LogStatisticsBeforeNewEncoding"); - LogStatistics (m_pEncContext->iLastStatisticsLogTs); + LogStatistics (m_pEncContext->iLastStatisticsLogTs, sEncodingParam.iSpatialLayerNum - 1); } break; case ENCODER_OPTION_FRAME_RATE: { // Maximal input frame rate @@ -1214,22 +1237,23 @@ int CWelsH264SVCEncoder::GetOption (ENCODER_OPTION eOptionId, void* pOption) { break; case ENCODER_OPTION_GET_STATISTICS: { SEncoderStatistics* pStatistics = (static_cast (pOption)); - pStatistics->uiWidth = m_pEncContext->sEncoderStatistics.uiWidth; - pStatistics->uiHeight = m_pEncContext->sEncoderStatistics.uiHeight; - pStatistics->fAverageFrameSpeedInMs = m_pEncContext->sEncoderStatistics.fAverageFrameSpeedInMs; + SEncoderStatistics* pEncStatistics = &m_pEncContext->sEncoderStatistics[m_pEncContext->pSvcParam->iSpatialLayerNum - 1]; + pStatistics->uiWidth = pEncStatistics->uiWidth; + pStatistics->uiHeight = pEncStatistics->uiHeight; + pStatistics->fAverageFrameSpeedInMs = pEncStatistics->fAverageFrameSpeedInMs; // rate control related - pStatistics->fAverageFrameRate = m_pEncContext->sEncoderStatistics.fAverageFrameRate; - pStatistics->fLatestFrameRate = m_pEncContext->sEncoderStatistics.fLatestFrameRate; - pStatistics->uiBitRate = m_pEncContext->sEncoderStatistics.uiBitRate; + pStatistics->fAverageFrameRate = pEncStatistics->fAverageFrameRate; + pStatistics->fLatestFrameRate = pEncStatistics->fLatestFrameRate; + pStatistics->uiBitRate = pEncStatistics->uiBitRate; - pStatistics->uiInputFrameCount = m_pEncContext->sEncoderStatistics.uiInputFrameCount; - pStatistics->uiSkippedFrameCount = m_pEncContext->sEncoderStatistics.uiSkippedFrameCount; + pStatistics->uiInputFrameCount = pEncStatistics->uiInputFrameCount; + pStatistics->uiSkippedFrameCount = pEncStatistics->uiSkippedFrameCount; - pStatistics->uiResolutionChangeTimes = m_pEncContext->sEncoderStatistics.uiResolutionChangeTimes; - pStatistics->uiIDRReqNum = m_pEncContext->sEncoderStatistics.uiIDRReqNum; - pStatistics->uiIDRSentNum = m_pEncContext->sEncoderStatistics.uiIDRSentNum; - pStatistics->uiLTRSentNum = m_pEncContext->sEncoderStatistics.uiLTRSentNum; + pStatistics->uiResolutionChangeTimes = pEncStatistics->uiResolutionChangeTimes; + pStatistics->uiIDRReqNum = pEncStatistics->uiIDRReqNum; + pStatistics->uiIDRSentNum = pEncStatistics->uiIDRSentNum; + pStatistics->uiLTRSentNum = pEncStatistics->uiLTRSentNum; } break; case ENCODER_OPTION_STATISTICS_LOG_INTERVAL: {