[Encoder] add total length in encoder output and complete statistics
Unified · Split
| @@ -404,6 +404,7 @@ typedef struct { · 403 unmodified lines | |||
| 404 | SLayerBSInfo sLayerInfo[MAX_LAYER_NUM_OF_FRAME]; | 404 | SLayerBSInfo sLayerInfo[MAX_LAYER_NUM_OF_FRAME]; |
| 405 | 405 | ||
| 406 | EVideoFrameType eFrameType; | 406 | EVideoFrameType eFrameType; |
| 407 | int iFrameSizeInBytes; | ||
| 407 | long long uiTimeStamp; | 408 | long long uiTimeStamp; |
| 408 | } SFrameBSInfo, *PFrameBSInfo; | 409 | } SFrameBSInfo, *PFrameBSInfo; |
| 409 | 410 | ||
| @@ -221,6 +221,9 @@ typedef struct TagWelsEncCtx { · 220 unmodified lines | |||
| 221 | SEncoderStatistics sEncoderStatistics; | 221 | SEncoderStatistics sEncoderStatistics; |
| 222 | int32_t iStatisticsLogInterval; | 222 | int32_t iStatisticsLogInterval; |
| 223 | int64_t iLastStatisticsLogTs; | 223 | int64_t iLastStatisticsLogTs; |
| 224 | int64_t iTotalEncodedBits; | ||
| 225 | int64_t iLastStatisticsBits; | ||
| 226 | int64_t iLastStatisticsFrameCount; | ||
| 224 | 227 | ||
| 225 | int32_t iEncoderError; | 228 | int32_t iEncoderError; |
| 226 | WELS_MUTEX mutexEncoderError; | 229 | WELS_MUTEX mutexEncoderError; |
| @@ -2736,7 +2736,7 @@ void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable, · 2735 unmodified lines | |||
| 2736 | * \brief write all parameter sets introduced in SVC extension | 2736 | * \brief write all parameter sets introduced in SVC extension |
| 2737 | * \return writing results, success or error | 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 | int32_t iSize = 0; | 2740 | int32_t iSize = 0; |
| 2741 | int32_t iNal = 0; | 2741 | int32_t iNal = 0; |
| 2742 | int32_t iIdx = 0; | 2742 | int32_t iIdx = 0; |
| @@ -2748,6 +2748,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN · 5 unmodified lines | |||
| 2748 | if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal) | 2748 | if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal) |
| 2749 | return ENC_RETURN_UNEXPECTED; | 2749 | return ENC_RETURN_UNEXPECTED; |
| 2750 | 2750 | ||
| 2751 | *pTotalLength = 0; | ||
| 2751 | /* write all SPS */ | 2752 | /* write all SPS */ |
| 2752 | iIdx = 0; | 2753 | iIdx = 0; |
| 2753 | while (iIdx < pCtx->iSpsNum) { | 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 | *pNumNal = iCountNal; | 2837 | *pNumNal = iCountNal; |
| 2838 | *pTotalLength = iSize; | ||
| 2837 | 2839 | ||
| 2838 | return ENC_RETURN_SUCCESS; | 2840 | return ENC_RETURN_SUCCESS; |
| 2839 | } | 2841 | } |
| @@ -2944,13 +2946,14 @@ int32_t WelsEncoderEncodeParameterSets (sWelsEncCtx* pCtx, void* pDst) { · 104 unmodified lines | |||
| 2944 | SFrameBSInfo* pFbi = (SFrameBSInfo*)pDst; | 2946 | SFrameBSInfo* pFbi = (SFrameBSInfo*)pDst; |
| 2945 | SLayerBSInfo* pLayerBsInfo = &pFbi->sLayerInfo[0]; | 2947 | SLayerBSInfo* pLayerBsInfo = &pFbi->sLayerInfo[0]; |
| 2946 | int32_t iCountNal = 0; | 2948 | int32_t iCountNal = 0; |
| 2949 | int32_t iTotalLength = 0; | ||
| 2947 | 2950 | ||
| 2948 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs; | 2951 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs; |
| 2949 | pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen; | 2952 | pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen; |
| 2950 | InitBits (&pCtx->pOut->sBsWrite, pCtx->pOut->pBsBuffer, pCtx->pOut->uiSize); | 2953 | InitBits (&pCtx->pOut->sBsWrite, pCtx->pOut->pBsBuffer, pCtx->pOut->uiSize); |
| 2951 | 2954 | ||
| 2952 | pCtx->iPosBsBuffer = 0; | 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 | WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS) | 2957 | WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS) |
| 2955 | 2958 | ||
| 2956 | pLayerBsInfo->uiSpatialId = 0; | 2959 | pLayerBsInfo->uiSpatialId = 0; |
| @@ -3094,7 +3097,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour · 137 unmodified lines | |||
| 3094 | //if ( pSvcParam->bEnableSSEI ) | 3097 | //if ( pSvcParam->bEnableSSEI ) |
| 3095 | 3098 | ||
| 3096 | // write parameter sets bitstream here | 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 | WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS) | 3102 | WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS) |
| 3099 | 3103 | ||
| 3100 | pLayerBsInfo->uiSpatialId = 0; | 3104 | pLayerBsInfo->uiSpatialId = 0; |
| @@ -3107,6 +3111,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour · 6 unmodified lines | |||
| 3107 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; | 3111 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; |
| 3108 | pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal; | 3112 | pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal; |
| 3109 | ++ iLayerNum; | 3113 | ++ iLayerNum; |
| 3114 | |||
| 3115 | iFrameSize += iNonVclSize; | ||
| 3110 | } | 3116 | } |
| 3111 | 3117 | ||
| 3112 | pCtx->pCurDqLayer = pCtx->ppDqLayerList[pSpatialIndexMap->iDid]; | 3118 | pCtx->pCurDqLayer = pCtx->ppDqLayerList[pSpatialIndexMap->iDid]; |
| @@ -3605,6 +3611,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour · 492 unmodified lines | |||
| 3605 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; | 3611 | pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; |
| 3606 | pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + 1; | 3612 | pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + 1; |
| 3607 | ++ iLayerNum; | 3613 | ++ iLayerNum; |
| 3614 | |||
| 3615 | iFrameSize += iPaddingNalSize; | ||
| 3608 | } | 3616 | } |
| 3609 | 3617 | ||
| 3610 | if ((pParam->sSliceCfg.uiSliceMode == SM_FIXEDSLCNUM_SLICE || pParam->sSliceCfg.uiSliceMode == SM_AUTO_SLICE) | 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 | WelsEmms(); | 3685 | WelsEmms(); |
| 3678 | 3686 | ||
| 3679 | pFbi->eFrameType = eFrameType; | 3687 | pFbi->eFrameType = eFrameType; |
| 3688 | pFbi->iFrameSizeInBytes = iFrameSize; | ||
| 3680 | return ENC_RETURN_SUCCESS; | 3689 | return ENC_RETURN_SUCCESS; |
| 3681 | } | 3690 | } |
| 3682 | 3691 | ||
| @@ -102,7 +102,7 @@ class CWelsH264SVCEncoder : public ISVCEncoder { · 101 unmodified lines | |||
| 102 | void CheckLevelSetting (int32_t iLayer, ELevelIdc uiLevelIdc); | 102 | void CheckLevelSetting (int32_t iLayer, ELevelIdc uiLevelIdc); |
| 103 | void CheckReferenceNumSetting (int32_t iNumRef); | 103 | void CheckReferenceNumSetting (int32_t iNumRef); |
| 104 | void TraceParamInfo(SEncParamExt *pParam); | 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 | sWelsEncCtx* m_pEncContext; | 107 | sWelsEncCtx* m_pEncContext; |
| 108 | 108 | ||
| @@ -431,7 +431,7 @@ int CWelsH264SVCEncoder ::EncodeFrameInternal (const SSourcePicture* pSrcPic, S · 430 unmodified lines | |||
| 431 | return cmUnkonwReason; | 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 | ///////////////////for test | 436 | ///////////////////for test |
| 437 | #ifdef OUTPUT_BIT_STREAM | 437 | #ifdef OUTPUT_BIT_STREAM |
| @@ -504,6 +504,8 @@ int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR) { · 66 unmodified lines | |||
| 504 | 504 | ||
| 505 | ForceCodingIDR (m_pEncContext); | 505 | ForceCodingIDR (m_pEncContext); |
| 506 | 506 | ||
| 507 | m_pEncContext->sEncoderStatistics.uiIDRReqNum++; | ||
| 508 | |||
| 507 | return 0; | 509 | return 0; |
| 508 | } | 510 | } |
| 509 | void CWelsH264SVCEncoder::CheckProfileSetting (int32_t iLayer, EProfileIdc uiProfileIdc) { | 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 | void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType, | 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 | SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics); | 600 | SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics); |
| 599 | 601 | ||
| 600 | int32_t iMaxDid = m_pEncContext->pSvcParam->iSpatialLayerNum - 1; | 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 | if (m_pEncContext->pLtr->bLTRMarkingFlag) { | 635 | if (m_pEncContext->pLtr->bLTRMarkingFlag) { |
| 634 | pStatistics->uiLTRSentNum ++; | 636 | pStatistics->uiLTRSentNum ++; |
| 635 | } | 637 | } |
| 636 | //TODO: update uiIDRReqNum in forceIDR | 638 | |
| 639 | m_pEncContext->iTotalEncodedBits += kiCurrentFrameSize; | ||
| 637 | 640 | ||
| 638 | if (m_pEncContext->iStatisticsLogInterval > 0) { | 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 | WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, | 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 | pStatistics->uiWidth, pStatistics->uiHeight, | 658 | pStatistics->uiWidth, pStatistics->uiHeight, |
| 643 | pStatistics->fAverageFrameSpeedInMs, pStatistics->fAverageFrameRate, | 659 | pStatistics->fAverageFrameSpeedInMs, pStatistics->fAverageFrameRate, |
| 660 | pStatistics->fLatestFrameRate, pStatistics->uiBitRate, | ||
| 644 | pStatistics->uiInputFrameCount, pStatistics->uiSkippedFrameCount, | 661 | pStatistics->uiInputFrameCount, pStatistics->uiSkippedFrameCount, |
| 645 | pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRSentNum, pStatistics->uiLTRSentNum); | 662 | pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRReqNum, pStatistics->uiIDRSentNum); |
| 646 | //TODO: the following statistics will be calculated and added later | 663 | //TODO: the following statistics will be calculated and added later |
| 647 | //pStatistics->fLatestFrameRate, pStatistics->uiBitRate, | 664 | //pStatistics->uiLTRSentNum |
| 648 | //pStatistics->uiIDRReqNum, | ||
| 649 | m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs; | ||
| 650 | } | 665 | } |
| 651 | } | 666 | } |
| 652 | 667 | ||
| @@ -770,3 +770,31 @@ TEST_F (EncoderInterfaceTest, GetStatistics) { · 769 unmodified lines | |||
| 770 | // finish | 770 | // finish |
| 771 | pPtrEnc->Uninitialize(); | 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 | } | ||