shithub: openh264

Download patch

ref: 9a08b7f97c23eeae3ee0839fb09cc67c20c2eb41
parent: 8e39cb3a3af8014505d496b89a4a815f6472a482
parent: 504cabf1065afd0f306deb3f78996cd4b6ef5562
author: ruil2 <ruil2@cisco.com>
date: Mon Dec 1 07:43:22 EST 2014

Merge pull request #1574 from huili2/dec_stat_add_freeze

add dec status for freezing

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -613,13 +613,17 @@
   float fAverageFrameSpeedInMs;                ///< average_Decoding_Time
   unsigned int uiDecodedFrameCount;            ///< number of frames
   unsigned int uiResolutionChangeTimes;        ///< uiResolutionChangeTimes
-  unsigned int uiIDRRecvNum;	               ///< number of actual IDR received
+  unsigned int uiIDRCorrectNum;	               ///< number of correct IDR received
   //EC on related
   unsigned int
   uiAvgEcRatio;                                ///< when EC is on, the average ratio of correct or EC areas, can be an indicator of reconstruction quality
   unsigned int uiEcIDRNum;                     ///< number of actual unintegrity IDR or not received but eced
   unsigned int uiEcFrameNum;                   ///<
-  unsigned int uiIDRLostNum;                   ///< decoder detect the number of lost IDR
+  unsigned int uiIDRLostNum;                   ///< number of lost IDR
+  unsigned int uiFreezingIDRNum;               ///< number of freezing IDR with error
+  unsigned int uiFreezingNonIDRNum;            ///< number of freezing non-IDR with error
+  int iAvgLumaQp;                              ///< average luma QP. default: -1, no correct frame outputted
+
 } SDecoderStatistics; // in building, coming soon
 
 #endif//WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__
--- a/codec/decoder/core/inc/decoder.h
+++ b/codec/decoder/core/inc/decoder.h
@@ -135,6 +135,14 @@
 void GetVclNalTemporalId (PWelsDecoderContext pCtx); //get the info that whether or not have VCL NAL in current AU,
 //and if YES, get the temporal ID
 
+//reset decoder number related statistics info
+void ResetDecStatNums (SDecoderStatistics* pDecStat);
+//update information when freezing occurs, including IDR/non-IDR number
+void UpdateDecStatFreezingInfo (const bool kbIdrFlag, SDecoderStatistics* pDecStat);
+//update information when no freezing occurs, including QP, correct IDR number, ECed IDR number
+void UpdateDecStatNoFreezingInfo (PWelsDecoderContext pCtx);
+//update decoder statistics information
+void UpdateDecStat (PWelsDecoderContext pCtx, const bool kbOutput);
 #ifdef __cplusplus
 }
 #endif//__cplusplus
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -237,7 +237,7 @@
 int32_t				iImgHeightInPixel;// height of image in pixel reconstruction picture to be output
 int32_t				iLastImgWidthInPixel;	// width of image in last successful pixel reconstruction picture to be output
 int32_t				iLastImgHeightInPixel;// height of image in last successful pixel reconstruction picture to be output
-bool bFreezeOutput;
+bool bFreezeOutput; // indicating current frame freezing. Default: true
 
 
 // Derived common elements
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -147,7 +147,7 @@
   pCtx->iImgHeightInPixel		= 0;		// alloc picture data when picture size is available
   pCtx->iLastImgWidthInPixel		= 0;
   pCtx->iLastImgHeightInPixel		= 0;
-  pCtx->bFreezeOutput = false;
+  pCtx->bFreezeOutput = true;
 
   pCtx->iFrameNum				= -1;
   pCtx->iPrevFrameNum			= -1;
@@ -165,6 +165,7 @@
   pCtx->bAvcBasedFlag			= true;
   pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
   pCtx->pPreviousDecodedPictureInDpb = NULL;
+  pCtx->sDecoderStatistics.iAvgLumaQp = -1;
 
 }
 
@@ -275,7 +276,7 @@
   pCtx->iImgHeightInPixel = 0;
   pCtx->iLastImgWidthInPixel	= 0;
   pCtx->iLastImgHeightInPixel = 0;
-  pCtx->bFreezeOutput = false;
+  pCtx->bFreezeOutput = true;
   pCtx->bHaveGotMemory	= false;
   WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
 }
@@ -776,5 +777,63 @@
 
   WelsBlockFuncInit (&pCtx->sBlockFunc, pCtx->uiCpuFlag);
 }
+
+//reset decoder number related statistics info
+void ResetDecStatNums (SDecoderStatistics* pDecStat) {
+  uint32_t uiWidth = pDecStat->uiWidth;
+  uint32_t uiHeight = pDecStat->uiHeight;
+  int32_t iAvgLumaQp = pDecStat->iAvgLumaQp;
+  memset (pDecStat, 0, sizeof (SDecoderStatistics));
+  pDecStat->uiWidth = uiWidth;
+  pDecStat->uiHeight = uiHeight;
+  pDecStat->iAvgLumaQp = iAvgLumaQp;
+}
+
+//update information when freezing occurs, including IDR/non-IDR number
+void UpdateDecStatFreezingInfo (const bool kbIdrFlag, SDecoderStatistics* pDecStat) {
+  if (kbIdrFlag)
+    pDecStat->uiFreezingIDRNum++;
+  else
+    pDecStat->uiFreezingNonIDRNum++;
+}
+
+//update information when no freezing occurs, including QP, correct IDR number, ECed IDR number
+void UpdateDecStatNoFreezingInfo (PWelsDecoderContext pCtx) {
+  PDqLayer pCurDq = pCtx->pCurDqLayer;
+  PPicture pPic = pCtx->pDec;
+  SDecoderStatistics* pDecStat = &pCtx->sDecoderStatistics;
+
+  if (pDecStat->iAvgLumaQp == -1) //first correct frame received
+    pDecStat->iAvgLumaQp = 0;
+
+  //update QP info
+  int32_t iTotalQp = 0;
+  const int32_t kiMbNum = pCurDq->iMbWidth * pCurDq->iMbHeight;
+  for (int32_t iMb = 0; iMb < kiMbNum; ++iMb) {
+    iTotalQp += pCurDq->pLumaQp[iMb] * pCurDq->pMbCorrectlyDecodedFlag[iMb];
+  }
+  iTotalQp /= kiMbNum;
+  if (pDecStat->uiDecodedFrameCount + 1 == 0) { //maximum uint32_t reached
+    ResetDecStatNums (pDecStat);
+    pDecStat->iAvgLumaQp = iTotalQp;
+  } else
+    pDecStat->iAvgLumaQp = (uint64_t) (pDecStat->iAvgLumaQp * pDecStat->uiDecodedFrameCount + iTotalQp) /
+                           (pDecStat->uiDecodedFrameCount + 1);
+
+  //update IDR number
+  if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag) {
+    pDecStat->uiIDRCorrectNum += (pPic->bIsComplete);
+    pDecStat->uiEcIDRNum += (!pPic->bIsComplete);
+  }
+}
+
+//update decoder statistics information
+void UpdateDecStat (PWelsDecoderContext pCtx, const bool kbOutput) {
+  if (pCtx->bFreezeOutput)
+    UpdateDecStatFreezingInfo (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag, &pCtx->sDecoderStatistics);
+  else if (kbOutput)
+    UpdateDecStatNoFreezingInfo (pCtx);
+}
+
 
 } // namespace WelsDec
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -44,7 +44,6 @@
 #include "error_concealment.h"
 
 namespace WelsDec {
-
 static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferInfo* pDstInfo) {
   PDqLayer pCurDq = pCtx->pCurDqLayer;
   PPicture pPic = pCtx->pDec;
@@ -88,24 +87,22 @@
 
   pCtx->iTotalNumMbRec = 0;
 
-  if (!pCtx->bParseOnly) {
-    //////output:::normal path
-    pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp;
-    ppDst[0]      = pPic->pData[0];
-    ppDst[1]      = pPic->pData[1];
-    ppDst[2]      = pPic->pData[2];
+  //////output:::normal path
+  pDstInfo->uiOutYuvTimeStamp = pPic->uiTimeStamp;
+  ppDst[0]      = pPic->pData[0];
+  ppDst[1]      = pPic->pData[1];
+  ppDst[2]      = pPic->pData[2];
 
-    pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420;
+  pDstInfo->UsrData.sSystemBuffer.iFormat = videoFormatI420;
 
-    pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2;
-    pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2;
-    pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0];
-    pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1];
-    ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2;
-    ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset  * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
-    ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset  * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
-    pDstInfo->iBufferStatus = 1;
-  }
+  pDstInfo->UsrData.sSystemBuffer.iWidth = kiWidth - (pCtx->sFrameCrop.iLeftOffset + pCtx->sFrameCrop.iRightOffset) * 2;
+  pDstInfo->UsrData.sSystemBuffer.iHeight = kiHeight - (pCtx->sFrameCrop.iTopOffset + pCtx->sFrameCrop.iBottomOffset) * 2;
+  pDstInfo->UsrData.sSystemBuffer.iStride[0] = pPic->iLinesize[0];
+  pDstInfo->UsrData.sSystemBuffer.iStride[1] = pPic->iLinesize[1];
+  ppDst[0] = ppDst[0] + pCtx->sFrameCrop.iTopOffset * 2 * pPic->iLinesize[0] + pCtx->sFrameCrop.iLeftOffset * 2;
+  ppDst[1] = ppDst[1] + pCtx->sFrameCrop.iTopOffset  * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
+  ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset  * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
+  pDstInfo->iBufferStatus = 1;
 
   bool bOutResChange = (pCtx->iLastImgWidthInPixel != pDstInfo->UsrData.sSystemBuffer.iWidth)
                        || (pCtx->iLastImgHeightInPixel != pDstInfo->UsrData.sSystemBuffer.iHeight);
@@ -119,13 +116,6 @@
            && pCtx->iErrorCode && bOutResChange)
     pCtx->bFreezeOutput = true;
 
-  if ((pDstInfo->iBufferStatus == 1) && (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag)) {
-    if (pPic->bIsComplete)
-      pCtx->sDecoderStatistics.uiIDRRecvNum++;
-    else
-      pCtx->sDecoderStatistics.uiEcIDRNum++;
-  }
-
   if (pDstInfo->iBufferStatus == 0) {
     if (!bFrameCompleteFlag)
       pCtx->iErrorCode |= dsBitstreamError;
@@ -137,6 +127,7 @@
       WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "DecodeFrameConstruction():New sequence detected, but freezed.");
     }
   }
+  UpdateDecStat (pCtx, pDstInfo->iBufferStatus);
 
   return 0;
 }
--- a/codec/decoder/core/src/error_concealment.cpp
+++ b/codec/decoder/core/src/error_concealment.cpp
@@ -157,8 +157,9 @@
     } //iMbX
   } //iMbY
 
-  pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
-                                          + ((iMbEcedNum * 100) / iMbNum) ;
+  if (!pCtx->bFreezeOutput)
+    pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
+                                            + ((iMbEcedNum * 100) / iMbNum) ;
 }
 
 //Do error concealment using slice MV copy method
@@ -415,8 +416,9 @@
     } //iMbX
   } //iMbY
 
-  pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
-                                          + ((iMbEcedNum * 100) / iMbNum) ;
+  if (!pCtx->bFreezeOutput)
+    pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
+                                            + ((iMbEcedNum * 100) / iMbNum) ;
 }
 
 //Mark erroneous frame as Ref Pic into DPB
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -373,8 +373,9 @@
 
     pDecoderStatistics->fAverageFrameSpeedInMs = (float) (m_pDecContext->dDecTime) /
         (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount);
-    memset (&m_pDecContext->sDecoderStatistics, 0, sizeof (SDecoderStatistics));
+    ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
     m_pDecContext->dDecTime = 0;
+
     return cmResultSuccess;
   }
 
@@ -478,6 +479,10 @@
 
       }
       m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+      if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
+        ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
+        m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+      }
       m_pDecContext->sDecoderStatistics.uiEcFrameNum++;
       m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiAvgEcRatio /
           m_pDecContext->sDecoderStatistics.uiEcFrameNum;
@@ -490,14 +495,18 @@
 
   if (pDstInfo->iBufferStatus == 1) {
 
+    m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+    if (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount == 0) { //exceed max value of uint32_t
+        ResetDecStatNums (&m_pDecContext->sDecoderStatistics);
+        m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
+    }
+
     if ((m_pDecContext->sDecoderStatistics.uiWidth != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iWidth)
         || (m_pDecContext->sDecoderStatistics.uiHeight != (unsigned int) pDstInfo->UsrData.sSystemBuffer.iHeight)) {
       m_pDecContext->sDecoderStatistics.uiResolutionChangeTimes++;
       m_pDecContext->sDecoderStatistics.uiWidth = pDstInfo->UsrData.sSystemBuffer.iWidth;
       m_pDecContext->sDecoderStatistics.uiHeight = pDstInfo->UsrData.sSystemBuffer.iHeight;
-
     }
-    m_pDecContext->sDecoderStatistics.uiDecodedFrameCount++;
   }
   iEnd = WelsTime();
   m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
@@ -529,7 +538,7 @@
   m_pDecContext->pParserBsInfo = pDstInfo;
   pDstInfo->iNalNum = 0;
   pDstInfo->iSpsWidthInPixel = pDstInfo->iSpsHeightInPixel = 0;
-  if(pDstInfo) {
+  if (pDstInfo) {
     m_pDecContext->uiTimeStamp = pDstInfo->uiInBsTimeStamp;
     pDstInfo->uiOutBsTimeStamp = 0;
   } else {
--- a/test/decoder/DecUT_DecExt.cpp
+++ b/test/decoder/DecUT_DecExt.cpp
@@ -122,7 +122,7 @@
 
 #if defined(ANDROID_NDK)
   std::string filename = std::string ("/sdcard/") + sFileName;
-  ASSERT_TRUE (pH264File = fopen (filename.c_str(),"rb"));
+  ASSERT_TRUE (pH264File = fopen (filename.c_str(), "rb"));
 #else
   ASSERT_TRUE (pH264File = fopen (sFileName, "rb"));
 #endif
@@ -130,7 +130,7 @@
   iFileSize = (int32_t) ftell (pH264File);
   fseek (pH264File, 0L, SEEK_SET);
   pBuf = new uint8_t[iFileSize + 4];
-  ASSERT_EQ(fread (pBuf, 1, iFileSize, pH264File), (unsigned int) iFileSize);
+  ASSERT_EQ (fread (pBuf, 1, iFileSize, pH264File), (unsigned int) iFileSize);
   memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage
   while (true) {
     if (iBufPos >= iFileSize) {
@@ -416,7 +416,7 @@
   EXPECT_EQ (57u, sDecStatic.uiAvgEcRatio);
   EXPECT_EQ (5u, sDecStatic.uiDecodedFrameCount);
   EXPECT_EQ (288u, sDecStatic.uiHeight);
-  EXPECT_EQ (1u, sDecStatic.uiIDRRecvNum);
+  EXPECT_EQ (1u, sDecStatic.uiIDRCorrectNum);
   EXPECT_EQ (3u, sDecStatic.uiResolutionChangeTimes);
   EXPECT_EQ (352u, sDecStatic.uiWidth);
   EXPECT_EQ (4u, sDecStatic.uiEcFrameNum);
@@ -433,7 +433,7 @@
   EXPECT_EQ (0u, sDecStatic.uiAvgEcRatio);
   EXPECT_EQ (97u, sDecStatic.uiDecodedFrameCount);
   EXPECT_EQ (144u, sDecStatic.uiHeight);
-  EXPECT_EQ (3u, sDecStatic.uiIDRRecvNum);
+  EXPECT_EQ (3u, sDecStatic.uiIDRCorrectNum);
   EXPECT_EQ (0u, sDecStatic.uiEcIDRNum);
   EXPECT_EQ (1u, sDecStatic.uiResolutionChangeTimes);
   EXPECT_EQ (176u, sDecStatic.uiWidth);
@@ -452,7 +452,7 @@
   EXPECT_EQ (0u, sDecStatic.uiAvgEcRatio);
   EXPECT_EQ (99u, sDecStatic.uiDecodedFrameCount);
   EXPECT_EQ (144u, sDecStatic.uiHeight);
-  EXPECT_EQ (4u, sDecStatic.uiIDRRecvNum);
+  EXPECT_EQ (4u, sDecStatic.uiIDRCorrectNum);
   EXPECT_EQ (0u, sDecStatic.uiEcIDRNum);
   EXPECT_EQ (1u, sDecStatic.uiResolutionChangeTimes);
   EXPECT_EQ (176u, sDecStatic.uiWidth);
@@ -472,7 +472,7 @@
   EXPECT_EQ (0u, sDecStatic.uiAvgEcRatio);
   EXPECT_EQ (9u, sDecStatic.uiDecodedFrameCount);
   EXPECT_EQ (192u, sDecStatic.uiHeight);
-  EXPECT_EQ (1u, sDecStatic.uiIDRRecvNum);
+  EXPECT_EQ (1u, sDecStatic.uiIDRCorrectNum);
   EXPECT_EQ (1u, sDecStatic.uiResolutionChangeTimes);
   EXPECT_EQ (320u, sDecStatic.uiWidth);
   EXPECT_EQ (0u, sDecStatic.uiEcFrameNum);