[Encoder] add total length in encoder output and complete statistics
Unified · Split
| @@ -404,6 +404,7 @@ typedef struct { · 403 unmodified lines | ||
| 404 | 404 | SLayerBSInfo sLayerInfo[MAX_LAYER_NUM_OF_FRAME]; |
| 405 | 405 | |
| 406 | 406 | EVideoFrameType eFrameType; |
| 407 | + int iFrameSizeInBytes; | |
| 407 | 408 | long long uiTimeStamp; |
| 408 | 409 | } SFrameBSInfo, *PFrameBSInfo; |
| 409 | 410 | |
| @@ -221,6 +221,9 @@ typedef struct TagWelsEncCtx { · 220 unmodified lines | ||
| 221 | 221 | SEncoderStatistics sEncoderStatistics; |
| 222 | 222 | int32_t iStatisticsLogInterval; |
| 223 | 223 | int64_t iLastStatisticsLogTs; |
| 224 | + int64_t iTotalEncodedBits; | |
| 225 | + int64_t iLastStatisticsBits; | |
| 226 | + int64_t iLastStatisticsFrameCount; | |
| 224 | 227 | |
| 225 | 228 | int32_t iEncoderError; |
| 226 | 229 | WELS_MUTEX mutexEncoderError; |
| @@ -2736,7 +2736,7 @@ void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable, · 2735 unmodified lines | ||
| 2736 | 2736 | * \brief write all parameter sets introduced in SVC extension |
| 2737 | 2737 | * \return writing results, success or error |
| 2738 | 2738 | */ |
| 2739 | −int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pNumNal) { | |
| 2739 | +int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pNumNal, int32_t* pTotalLength) { | |
| 2740 | 2740 | int32_t iSize = 0; |
| 2741 | 2741 | int32_t iNal = 0; |
| 2742 | 2742 | int32_t iIdx = 0; |
| @@ -2748,6 +2748,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN · 5 unmodified lines | ||
| 2748 | 2748 | if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal) |
| 2749 | 2749 | return ENC_RETURN_UNEXPECTED; |
| 2750 | 2750 | |
| 2751 | + *pTotalLength = 0; | |
| 2751 | 2752 | /* write all SPS */ |
| 2752 | 2753 | iIdx = 0; |
| 2753 | 2754 | while (iIdx < pCtx->iSpsNum) { |
| @@ -2834,6 +2835,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN · 80 unmodified lines | ||
| 2834 | 2835 | } |
| 2835 | 2836 | |
| 2836 | 2837 | *pNumNal = iCountNal; |
| 2838 | + *pTotalLength = iSize; | |
| 2837 | 2839 | |
| 2838 | 2840 | return ENC_RETURN_SUCCESS; |
| 2839 | 2841 | } |
| @@ -2944,13 +2946,14 @@ int32_t WelsEncoderEncodeParameterSets (sWelsEncCtx* pCtx, void* pDst) { · 104 unmodified lines | ||
| 2944 | 2946 | SFrameBSInfo* pFbi = (SFrameBSInfo*)pDst; |
| 2945 | 2947 | SLayerBSInfo* pLayerBsInfo = &pFbi->sLayerInfo[0]; |
| 2946 | 2948 | int32_t iCountNal = 0; |
| 2949 | + int32_t iTotalLength = 0; | |
| 2947 | 2950 | |
| 2948 | 2951 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs; |
| 2949 | 2952 | pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen; |
| 2950 | 2953 | InitBits (&pCtx->pOut->sBsWrite, pCtx->pOut->pBsBuffer, pCtx->pOut->uiSize); |
| 2951 | 2954 | |
| 2952 | 2955 | pCtx->iPosBsBuffer = 0; |
| 2953 | − int32_t iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal); | |
| 2956 | + int32_t iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iTotalLength); | |
| 2954 | 2957 | WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS) |
| 2955 | 2958 | |
| 2956 | 2959 | pLayerBsInfo->uiSpatialId = 0; |
| @@ -3094,7 +3097,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour · 137 unmodified lines | ||
| 3094 | 3097 | //if ( pSvcParam->bEnableSSEI ) |
| 3095 | 3098 | |
| 3096 | 3099 | // write parameter sets bitstream here |
| 3097 | − pCtx->iEncoderError = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal); | |
| 3100 | + int32_t iNonVclSize = 0; | |
| 3101 | + pCtx->iEncoderError = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iNonVclSize); | |
| 3098 | 3102 | WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS) |
| 3099 | 3103 | |
| 3100 | 3104 | pLayerBsInfo->uiSpatialId = 0; |
| @@ -3107,6 +3111,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour · 6 unmodified lines | ||
| 3107 | 3111 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; |
| 3108 | 3112 | pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal; |
| 3109 | 3113 | ++ iLayerNum; |
| 3114 | + | |
| 3115 | + iFrameSize += iNonVclSize; | |
| 3110 | 3116 | } |
| 3111 | 3117 | |
| 3112 | 3118 | pCtx->pCurDqLayer = pCtx->ppDqLayerList[pSpatialIndexMap->iDid]; |
| @@ -3605,6 +3611,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour · 492 unmodified lines | ||
| 3605 | 3611 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; |
| 3606 | 3612 | pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + 1; |
| 3607 | 3613 | ++ iLayerNum; |
| 3614 | + | |
| 3615 | + iFrameSize += iPaddingNalSize; | |
| 3608 | 3616 | } |
| 3609 | 3617 | |
| 3610 | 3618 | if ((pParam->sSliceCfg.uiSliceMode == SM_FIXEDSLCNUM_SLICE || pParam->sSliceCfg.uiSliceMode == SM_AUTO_SLICE) |
| @@ -3677,6 +3685,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour · 66 unmodified lines | ||
| 3677 | 3685 | WelsEmms(); |
| 3678 | 3686 | |
| 3679 | 3687 | pFbi->eFrameType = eFrameType; |
| 3688 | + pFbi->iFrameSizeInBytes = iFrameSize; | |
| 3680 | 3689 | return ENC_RETURN_SUCCESS; |
| 3681 | 3690 | } |
| 3682 | 3691 | |
| @@ -102,7 +102,7 @@ class CWelsH264SVCEncoder : public ISVCEncoder { · 101 unmodified lines | ||
| 102 | 102 | void CheckLevelSetting (int32_t iLayer, ELevelIdc uiLevelIdc); |
| 103 | 103 | void CheckReferenceNumSetting (int32_t iNumRef); |
| 104 | 104 | void TraceParamInfo(SEncParamExt *pParam); |
| 105 | − void UpdateStatistics(const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType, const int64_t kiCurrentFrameMs); | |
| 105 | + void UpdateStatistics(const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType, const int32_t kiCurrentFrameSize, const int64_t kiCurrentFrameMs); | |
| 106 | 106 | |
| 107 | 107 | sWelsEncCtx* m_pEncContext; |
| 108 | 108 | |
| @@ -431,7 +431,7 @@ int CWelsH264SVCEncoder ::EncodeFrameInternal (const SSourcePicture* pSrcPic, S · 430 unmodified lines | ||
| 431 | 431 | return cmUnkonwReason; |
| 432 | 432 | } |
| 433 | 433 | |
| 434 | − UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo->eFrameType, kiCurrentFrameMs); | |
| 434 | + UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo->eFrameType, pBsInfo->iFrameSizeInBytes, kiCurrentFrameMs); | |
| 435 | 435 | |
| 436 | 436 | ///////////////////for test |
| 437 | 437 | #ifdef OUTPUT_BIT_STREAM |
| @@ -504,6 +504,8 @@ int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR) { · 66 unmodified lines | ||
| 504 | 504 | |
| 505 | 505 | ForceCodingIDR (m_pEncContext); |
| 506 | 506 | |
| 507 | + m_pEncContext->sEncoderStatistics.uiIDRReqNum++; | |
| 508 | + | |
| 507 | 509 | return 0; |
| 508 | 510 | } |
| 509 | 511 | void CWelsH264SVCEncoder::CheckProfileSetting (int32_t iLayer, EProfileIdc uiProfileIdc) { |
| @@ -594,7 +596,7 @@ void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) { · 84 unmodified lines | ||
| 594 | 596 | } |
| 595 | 597 | |
| 596 | 598 | void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType, |
| 597 | − const int64_t kiCurrentFrameMs) { | |
| 599 | + const int32_t kiCurrentFrameSize, const int64_t kiCurrentFrameMs) { | |
| 598 | 600 | SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics); |
| 599 | 601 | |
| 600 | 602 | int32_t iMaxDid = m_pEncContext->pSvcParam->iSpatialLayerNum - 1; |
| @@ -633,20 +635,33 @@ void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVid · 32 unmodified lines | ||
| 633 | 635 | if (m_pEncContext->pLtr->bLTRMarkingFlag) { |
| 634 | 636 | pStatistics->uiLTRSentNum ++; |
| 635 | 637 | } |
| 636 | − //TODO: update uiIDRReqNum in forceIDR | |
| 638 | + | |
| 639 | + m_pEncContext->iTotalEncodedBits += kiCurrentFrameSize; | |
| 637 | 640 | |
| 638 | 641 | if (m_pEncContext->iStatisticsLogInterval > 0) { |
| 639 | − if (WELS_ABS (kiCurrentFrameTs - m_pEncContext->iLastStatisticsLogTs) > m_pEncContext->iStatisticsLogInterval) { | |
| 642 | + int64_t iTimeDiff = kiCurrentFrameTs - m_pEncContext->iLastStatisticsLogTs; | |
| 643 | + if (iTimeDiff > m_pEncContext->iStatisticsLogInterval) { | |
| 644 | + pStatistics->fLatestFrameRate = (pStatistics->uiInputFrameCount - m_pEncContext->iLastStatisticsFrameCount) * 1000 / | |
| 645 | + iTimeDiff; | |
| 646 | + pStatistics->uiBitRate = static_cast<unsigned int> ((m_pEncContext->iTotalEncodedBits - | |
| 647 | + m_pEncContext->iLastStatisticsBits) * 1000 / iTimeDiff); | |
| 648 | + | |
| 649 | + // update variables | |
| 650 | + m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs; | |
| 651 | + m_pEncContext->iLastStatisticsBits = m_pEncContext->iTotalEncodedBits; | |
| 652 | + m_pEncContext->iLastStatisticsFrameCount = pStatistics->uiInputFrameCount; | |
| 653 | + | |
| 640 | 654 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, |
| 641 | − "EncoderStatistics: %dx%d, SpeedInMs: %f, AverFrameRate=%f, LastFrameRate=NA, LatestBitRate=NA, uiInputFrameCount=%d, uiSkippedFrameCount=%d, uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA", | |
| 655 | + "EncoderStatistics: %dx%d, SpeedInMs: %f, fAverageFrameRate=%f, \ | |
| 656 | + LastFrameRate=%f, LatestBitRate=%d, uiInputFrameCount=%d, uiSkippedFrameCount=%d, \ | |
| 657 | + uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA", | |
| 642 | 658 | pStatistics->uiWidth, pStatistics->uiHeight, |
| 643 | 659 | pStatistics->fAverageFrameSpeedInMs, pStatistics->fAverageFrameRate, |
| 660 | + pStatistics->fLatestFrameRate, pStatistics->uiBitRate, | |
| 644 | 661 | pStatistics->uiInputFrameCount, pStatistics->uiSkippedFrameCount, |
| 645 | − pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRSentNum, pStatistics->uiLTRSentNum); | |
| 662 | + pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRReqNum, pStatistics->uiIDRSentNum); | |
| 646 | 663 | //TODO: the following statistics will be calculated and added later |
| 647 | − //pStatistics->fLatestFrameRate, pStatistics->uiBitRate, | |
| 648 | − //pStatistics->uiIDRReqNum, | |
| 649 | − m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs; | |
| 664 | + //pStatistics->uiLTRSentNum | |
| 650 | 665 | } |
| 651 | 666 | } |
| 652 | 667 | |
| @@ -770,3 +770,31 @@ TEST_F (EncoderInterfaceTest, GetStatistics) { · 769 unmodified lines | ||
| 770 | 770 | // finish |
| 771 | 771 | pPtrEnc->Uninitialize(); |
| 772 | 772 | } |
| 773 | + | |
| 774 | +TEST_F (EncoderInterfaceTest, FrameSizeCheck) { | |
| 775 | + SEncParamBase sEncParamBase; | |
| 776 | + GetValidEncParamBase (&sEncParamBase); | |
| 777 | + | |
| 778 | + int iResult = pPtrEnc->Initialize (&sEncParamBase); | |
| 779 | + EXPECT_EQ (iResult, static_cast<int> (cmResultSuccess)); | |
| 780 | + if (iResult != cmResultSuccess) { | |
| 781 | + fprintf (stderr, "Unexpected ParamBase? \ | |
| 782 | + iUsageType=%d, Pic=%dx%d, TargetBitrate=%d, iRCMode=%d, fMaxFrameRate=%.1f\n", | |
| 783 | + sEncParamBase.iUsageType, sEncParamBase.iPicWidth, sEncParamBase.iPicHeight, | |
| 784 | + sEncParamBase.iTargetBitrate, sEncParamBase.iRCMode, sEncParamBase.fMaxFrameRate); | |
| 785 | + } | |
| 786 | + | |
| 787 | + PrepareOneSrcFrame(); | |
| 788 | + iResult = pPtrEnc->EncodeFrame (pSrcPic, &sFbi); | |
| 789 | + | |
| 790 | + uint32_t length = 0; | |
| 791 | + for (int i = 0; i < sFbi.iLayerNum; ++i) { | |
| 792 | + for (int j = 0; j < sFbi.sLayerInfo[i].iNalCount; ++j) { | |
| 793 | + length += sFbi.sLayerInfo[i].pNalLengthInByte[j]; | |
| 794 | + } | |
| 795 | + } | |
| 796 | + EXPECT_EQ (length, sFbi.iFrameSizeInBytes); | |
| 797 | + | |
| 798 | + // finish | |
| 799 | + pPtrEnc->Uninitialize(); | |
| 800 | +} | |