shithub: openh264

Download patch

ref: 703bbef12849115b79b730b320fa7cfb2dbe3fa1
parent: aed7b2316c03d17904ba13374b62209df2953f72
parent: b56b8725fc0928f5295d2a38776766c7e60c0fad
author: ruil2 <ruil2@cisco.com>
date: Fri Nov 14 06:20:45 EST 2014

Merge pull request #1530 from sijchen/after_review

[Encoder] add total length in encoder output and complete statistics

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -404,6 +404,7 @@
   SLayerBSInfo	sLayerInfo[MAX_LAYER_NUM_OF_FRAME];
 
   EVideoFrameType eFrameType;
+  int   iFrameSizeInBytes;
   long long uiTimeStamp;
 } SFrameBSInfo, *PFrameBSInfo;
 
--- a/codec/encoder/core/inc/encoder_context.h
+++ b/codec/encoder/core/inc/encoder_context.h
@@ -221,6 +221,9 @@
   SEncoderStatistics sEncoderStatistics;
   int32_t            iStatisticsLogInterval;
   int64_t            iLastStatisticsLogTs;
+  int64_t            iTotalEncodedBits;
+  int64_t            iLastStatisticsBits;
+  int64_t            iLastStatisticsFrameCount;
 
   int32_t iEncoderError;
   WELS_MUTEX					mutexEncoderError;
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -2736,7 +2736,7 @@
  * \brief	write all parameter sets introduced in SVC extension
  * \return	writing results, success or error
  */
-int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pNumNal) {
+int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pNumNal, int32_t* pTotalLength) {
   int32_t iSize	= 0;
   int32_t iNal	= 0;
   int32_t	iIdx	= 0;
@@ -2748,6 +2748,7 @@
   if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal)
     return ENC_RETURN_UNEXPECTED;
 
+  *pTotalLength = 0;
   /* write all SPS */
   iIdx = 0;
   while (iIdx < pCtx->iSpsNum) {
@@ -2834,6 +2835,7 @@
   }
 
   *pNumNal = iCountNal;
+  *pTotalLength = iSize;
 
   return ENC_RETURN_SUCCESS;
 }
@@ -2944,6 +2946,7 @@
   SFrameBSInfo* pFbi          = (SFrameBSInfo*)pDst;
   SLayerBSInfo* pLayerBsInfo  = &pFbi->sLayerInfo[0];
   int32_t iCountNal           = 0;
+  int32_t iTotalLength        = 0;
 
   pLayerBsInfo->pBsBuf = pCtx->pFrameBs;
   pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen;
@@ -2950,7 +2953,7 @@
   InitBits (&pCtx->pOut->sBsWrite, pCtx->pOut->pBsBuffer, pCtx->pOut->uiSize);
 
   pCtx->iPosBsBuffer = 0;
-  int32_t iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal);
+  int32_t iReturn = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iTotalLength);
   WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
 
   pLayerBsInfo->uiSpatialId   = 0;
@@ -3094,7 +3097,8 @@
     //if ( pSvcParam->bEnableSSEI )
 
     // write parameter sets bitstream here
-    pCtx->iEncoderError = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal);
+    int32_t iNonVclSize = 0;
+    pCtx->iEncoderError = WelsWriteParameterSets (pCtx, &pLayerBsInfo->pNalLengthInByte[0], &iCountNal, &iNonVclSize);
     WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
 
     pLayerBsInfo->uiSpatialId		= 0;
@@ -3107,6 +3111,8 @@
     pLayerBsInfo->pBsBuf			= pCtx->pFrameBs + pCtx->iPosBsBuffer;
     pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
     ++ iLayerNum;
+
+    iFrameSize += iNonVclSize;
   }
 
   pCtx->pCurDqLayer				= pCtx->ppDqLayerList[pSpatialIndexMap->iDid];
@@ -3605,6 +3611,8 @@
       pLayerBsInfo->pBsBuf	= pCtx->pFrameBs + pCtx->iPosBsBuffer;
       pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + 1;
       ++ iLayerNum;
+
+      iFrameSize += iPaddingNalSize;
     }
 
     if ((pParam->sSliceCfg.uiSliceMode == SM_FIXEDSLCNUM_SLICE || pParam->sSliceCfg.uiSliceMode == SM_AUTO_SLICE)
@@ -3677,6 +3685,7 @@
   WelsEmms();
 
   pFbi->eFrameType = eFrameType;
+  pFbi->iFrameSizeInBytes = iFrameSize;
   return ENC_RETURN_SUCCESS;
 }
 
--- a/codec/encoder/plus/inc/welsEncoderExt.h
+++ b/codec/encoder/plus/inc/welsEncoderExt.h
@@ -102,7 +102,7 @@
   void CheckLevelSetting (int32_t iLayer, ELevelIdc uiLevelIdc);
   void CheckReferenceNumSetting (int32_t iNumRef);
   void TraceParamInfo(SEncParamExt *pParam);
-  void UpdateStatistics(const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType,  const int64_t kiCurrentFrameMs);
+  void UpdateStatistics(const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType,  const int32_t kiCurrentFrameSize, const int64_t kiCurrentFrameMs);
 
   sWelsEncCtx*	m_pEncContext;
 
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -431,7 +431,7 @@
     return cmUnkonwReason;
   }
 
-  UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo->eFrameType, kiCurrentFrameMs);
+  UpdateStatistics (pSrcPic->uiTimeStamp, pBsInfo->eFrameType, pBsInfo->iFrameSizeInBytes, kiCurrentFrameMs);
 
   ///////////////////for test
 #ifdef OUTPUT_BIT_STREAM
@@ -504,6 +504,8 @@
 
   ForceCodingIDR (m_pEncContext);
 
+  m_pEncContext->sEncoderStatistics.uiIDRReqNum++;
+
   return 0;
 }
 void CWelsH264SVCEncoder::CheckProfileSetting (int32_t iLayer, EProfileIdc uiProfileIdc) {
@@ -594,7 +596,7 @@
 }
 
 void CWelsH264SVCEncoder::UpdateStatistics (const int64_t kiCurrentFrameTs, EVideoFrameType eFrameType,
-    const int64_t kiCurrentFrameMs) {
+    const int32_t kiCurrentFrameSize, const int64_t kiCurrentFrameMs) {
   SEncoderStatistics* pStatistics = & (m_pEncContext->sEncoderStatistics);
 
   int32_t iMaxDid = m_pEncContext->pSvcParam->iSpatialLayerNum - 1;
@@ -633,20 +635,33 @@
   if (m_pEncContext->pLtr->bLTRMarkingFlag) {
     pStatistics->uiLTRSentNum ++;
   }
-  //TODO: update uiIDRReqNum in forceIDR
 
+  m_pEncContext->iTotalEncodedBits += kiCurrentFrameSize;
+
   if (m_pEncContext->iStatisticsLogInterval > 0) {
-    if (WELS_ABS (kiCurrentFrameTs - m_pEncContext->iLastStatisticsLogTs) > m_pEncContext->iStatisticsLogInterval) {
+    int64_t iTimeDiff = kiCurrentFrameTs - m_pEncContext->iLastStatisticsLogTs;
+    if (iTimeDiff > m_pEncContext->iStatisticsLogInterval) {
+      pStatistics->fLatestFrameRate = (pStatistics->uiInputFrameCount - m_pEncContext->iLastStatisticsFrameCount) * 1000 /
+                                      iTimeDiff;
+      pStatistics->uiBitRate = static_cast<unsigned int> ((m_pEncContext->iTotalEncodedBits -
+                               m_pEncContext->iLastStatisticsBits) * 1000 / iTimeDiff);
+
+      // update variables
+      m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs;
+      m_pEncContext->iLastStatisticsBits = m_pEncContext->iTotalEncodedBits;
+      m_pEncContext->iLastStatisticsFrameCount = pStatistics->uiInputFrameCount;
+
       WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
-               "EncoderStatistics: %dx%d, SpeedInMs: %f, AverFrameRate=%f, LastFrameRate=NA, LatestBitRate=NA, uiInputFrameCount=%d, uiSkippedFrameCount=%d, uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA",
+               "EncoderStatistics: %dx%d, SpeedInMs: %f, fAverageFrameRate=%f, \
+               LastFrameRate=%f, LatestBitRate=%d, uiInputFrameCount=%d, uiSkippedFrameCount=%d, \
+               uiResolutionChangeTimes=%d, uIDRReqNum=%d, uIDRSentNum=%d, uLTRSentNum=NA",
                pStatistics->uiWidth, pStatistics->uiHeight,
                pStatistics->fAverageFrameSpeedInMs, pStatistics->fAverageFrameRate,
+               pStatistics->fLatestFrameRate, pStatistics->uiBitRate,
                pStatistics->uiInputFrameCount, pStatistics->uiSkippedFrameCount,
-               pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRSentNum, pStatistics->uiLTRSentNum);
+               pStatistics->uiResolutionChangeTimes, pStatistics->uiIDRReqNum, pStatistics->uiIDRSentNum);
       //TODO: the following statistics will be calculated and added later
-      //pStatistics->fLatestFrameRate, pStatistics->uiBitRate,
-      //pStatistics->uiIDRReqNum,
-      m_pEncContext->iLastStatisticsLogTs = kiCurrentFrameTs;
+      //pStatistics->uiLTRSentNum
     }
   }
 
--- a/test/encoder/EncUT_EncoderExt.cpp
+++ b/test/encoder/EncUT_EncoderExt.cpp
@@ -770,3 +770,31 @@
   // finish
   pPtrEnc->Uninitialize();
 }
+
+TEST_F (EncoderInterfaceTest, FrameSizeCheck) {
+  SEncParamBase sEncParamBase;
+  GetValidEncParamBase (&sEncParamBase);
+
+  int iResult = pPtrEnc->Initialize (&sEncParamBase);
+  EXPECT_EQ (iResult, static_cast<int> (cmResultSuccess));
+  if (iResult != cmResultSuccess) {
+    fprintf (stderr, "Unexpected ParamBase? \
+             iUsageType=%d, Pic=%dx%d, TargetBitrate=%d, iRCMode=%d, fMaxFrameRate=%.1f\n",
+             sEncParamBase.iUsageType, sEncParamBase.iPicWidth, sEncParamBase.iPicHeight,
+             sEncParamBase.iTargetBitrate, sEncParamBase.iRCMode, sEncParamBase.fMaxFrameRate);
+  }
+
+  PrepareOneSrcFrame();
+  iResult = pPtrEnc->EncodeFrame (pSrcPic, &sFbi);
+
+  uint32_t length = 0;
+  for (int i = 0; i < sFbi.iLayerNum; ++i) {
+    for (int j = 0; j < sFbi.sLayerInfo[i].iNalCount; ++j) {
+      length += sFbi.sLayerInfo[i].pNalLengthInByte[j];
+    }
+  }
+  EXPECT_EQ (length, sFbi.iFrameSizeInBytes);
+
+  // finish
+  pPtrEnc->Uninitialize();
+}