shithub: openh264

Download patch

ref: 5cb5c283319233b6178a439ed0ee6ccf24faeeab
parent: 3d2182590155771e9bafe3b02369c096e855315b
parent: 45ef803e4db99776fe9ea9634f59ee995b764e32
author: sijchen <sijchen@cisco.com>
date: Thu Nov 6 09:25:04 EST 2014

Merge pull request #1500 from syureyi/decoderstatics

decoder statictis adding

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -484,14 +484,14 @@
   unsigned int uiWidth;					// the width of encode/decode frame
   unsigned int uiHeight;					// the height of encode/decode frame
   float fAverageFrameSpeedInMs; // Average_Decoding_Time
-
   unsigned int uiDecodedFrameCount; // number of frames
   unsigned int uiResolutionChangeTimes; // uiResolutionChangeTimes
-  unsigned int
-  uiAvgEcRatio; // when EC is on, the average ratio of correct or EC areas, can be an indicator of reconstruction quality
-  unsigned int uiIDRReqNum;	// number of actual IDR request
-  unsigned int uiLTRReqNum;	// number of actual LTR request
   unsigned int uiIDRRecvNum;	// number of actual 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 out the number of lost IDR lost
 } SDecoderStatistics; // in building, coming soon
 
 #endif//WELS_VIDEO_CODEC_APPLICATION_DEFINITION_H__
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -372,6 +372,8 @@
 bool bCabacInited;
 SWelsCabacCtx   pCabacCtx[WELS_CONTEXT_COUNT];
 PWelsCabacDecEngine   pCabacDecEngine;
+double dDecTime;
+SDecoderStatistics sDecoderStatistics;// For real time debugging
 } SWelsDecoderContext, *PWelsDecoderContext;
 
 static inline void ResetActiveSPSForEachLayer (PWelsDecoderContext pCtx) {
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -107,6 +107,14 @@
     pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag
                                          && pPic->bIsComplete); // When EC disable, ECed picture not output
 
+
+  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;
@@ -974,6 +982,8 @@
     }
     if (uiActualIdx ==
         pCurAu->uiActualUnitsNum) {	// no found IDR nal within incoming AU, need exit to avoid mosaic issue, 11/19/2009
+
+      pCtx->sDecoderStatistics.uiIDRLostNum++;
       WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
                "UpdateAccessUnit():::::Key frame lost.....CAN NOT find IDR from current AU.");
       pCtx->iErrorCode |= dsRefLost;
--- a/codec/decoder/core/src/error_concealment.cpp
+++ b/codec/decoder/core/src/error_concealment.cpp
@@ -98,9 +98,10 @@
   PPicture pDstPic = pCtx->pDec;
   PPicture pSrcPic = pCtx->pPreviousDecodedPictureInDpb;
 
+  int32_t iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
   //uint8_t *pDstData[3], *pSrcData[3];
   bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
-
+  int32_t iMbEcedNum = 0;
   //Do slice copy late
   int32_t iMbXyIndex;
   uint8_t* pSrcData, *pDstData;
@@ -110,6 +111,7 @@
     for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
       iMbXyIndex = iMbY * iMbWidth + iMbX;
       if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
+        iMbEcedNum++;
         if (pSrcPic != NULL) {
           iSrcStride = pSrcPic->iLinesize[0];
           //Y component
@@ -147,6 +149,9 @@
       } //!pMbCorrectlyDecodedFlag[iMbXyIndex]
     } //iMbX
   } //iMbY
+
+  pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
+                                          + ((iMbEcedNum * 100) / iMbNum) ;
 }
 
 
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -53,6 +53,7 @@
 #include "decoder_core.h"
 #include "error_concealment.h"
 
+#include "measure_time.h"
 extern "C" {
 #include "decoder_core.h"
 #include "manage_dec_ref.h"
@@ -301,8 +302,13 @@
       m_pWelsTrace->SetTraceCallbackContext (ctx);
     }
     return cmResultSuccess;
+  } else if (eOptID == DECODER_OPTION_GET_STATISTICS) {
+    WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_WARNING,
+             "CWelsDecoder::SetOption():DECODER_OPTION_GET_STATISTICS: this option is get-only!");
+    return cmInitParaError;
   }
 
+
   return cmInitParaError;
 }
 
@@ -358,6 +364,16 @@
     iVal = (int) m_pDecContext->eErrorConMethod;
     * ((int*)pOption) = iVal;
     return cmResultSuccess;
+  } else if (DECODER_OPTION_GET_STATISTICS == eOptID) { // get decoder statistics info for real time debugging
+    SDecoderStatistics* pDecoderStatistics = (static_cast<SDecoderStatistics*> (pOption));
+
+    memcpy (pDecoderStatistics, &m_pDecContext->sDecoderStatistics, sizeof (SDecoderStatistics));
+
+    pDecoderStatistics->fAverageFrameSpeedInMs = (m_pDecContext->dDecTime) /
+        (m_pDecContext->sDecoderStatistics.uiDecodedFrameCount);
+    memset (&m_pDecContext->sDecoderStatistics, 0, sizeof (SDecoderStatistics));
+    m_pDecContext->dDecTime = 0;
+    return cmResultSuccess;
   }
 
   return cmInitParaError;
@@ -389,6 +405,8 @@
     m_pDecContext->bInstantDecFlag = true;
   }
 
+  int64_t iStart, iEnd;
+  iStart = WelsTime();
   ppDst[0] = ppDst[1] = ppDst[2] = NULL;
   m_pDecContext->iErrorCode             = dsErrorFree; //initialize at the starting of AU decoding.
   m_pDecContext->iFeedbackVclNalInAu = FEEDBACK_UNKNOWN_NAL; //initialize
@@ -439,11 +457,43 @@
     if ((m_pDecContext->eErrorConMethod != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
       //TODO after dec status updated
       m_pDecContext->iErrorCode |= dsDataErrorConcealed;
+      if (m_pDecContext->eErrorConMethod == ERROR_CON_FRAME_COPY)
+
+        m_pDecContext->sDecoderStatistics.uiAvgEcRatio = (m_pDecContext->sDecoderStatistics.uiAvgEcRatio *
+            m_pDecContext->sDecoderStatistics.uiEcFrameNum) + 100;
+
+      //
+      if ((m_pDecContext->sDecoderStatistics.uiWidth != pDstInfo->UsrData.sSystemBuffer.iWidth)
+          || (m_pDecContext->sDecoderStatistics.uiHeight != 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++;
+      m_pDecContext->sDecoderStatistics.uiEcFrameNum++;
+      m_pDecContext->sDecoderStatistics.uiAvgEcRatio = m_pDecContext->sDecoderStatistics.uiAvgEcRatio /
+          m_pDecContext->sDecoderStatistics.uiEcFrameNum;
     }
+    iEnd = WelsTime();
+    m_pDecContext->dDecTime += (iEnd - iStart) / 1e3;
     return (DECODING_STATE) m_pDecContext->iErrorCode;
   }
   // else Error free, the current codec works well
 
+  if (pDstInfo->iBufferStatus == 1) {
+
+    if ((m_pDecContext->sDecoderStatistics.uiWidth != pDstInfo->UsrData.sSystemBuffer.iWidth)
+        || (m_pDecContext->sDecoderStatistics.uiHeight != 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;
   return dsErrorFree;
 }
 
binary files /dev/null b/res/BA_MW_D_IDR_LOST.264 differ
binary files /dev/null b/res/BA_MW_D_P_LOST.264 differ
binary files /dev/null b/res/Error_I_P.264 differ
--- a/test/decoder/DecUT_DecExt.cpp
+++ b/test/decoder/DecUT_DecExt.cpp
@@ -30,6 +30,8 @@
   void Uninit();
   //Mock input data for test
   void MockPacketType (const EWelsNalUnitType eNalUnitType, const int iPacketLength);
+  //Decoder real bitstream
+  void DecoderBs (const char* sFileName);
   //Test Initialize/Uninitialize
   void TestInitUninit();
   //DECODER_OPTION_DATAFORMAT
@@ -56,6 +58,8 @@
   void TestTraceCallback();
   //DECODER_OPTION_TRACE_CALLBACK_CONTEXT
   void TestTraceCallbackContext();
+  //DECODER_OPTION_GET_DECODER_STATICTIS
+  void TestGetDecStatistics();
   //Do whole tests here
   void DecoderInterfaceAll();
 
@@ -104,6 +108,58 @@
   m_iBufLength = 0;
 }
 
+void DecoderInterfaceTest::DecoderBs (const char* sFileName) {
+
+  uint8_t* pBuf = NULL;
+  int32_t iBufPos = 0;
+  int32_t iFileSize;
+  int32_t i = 0;
+  int32_t iSliceSize;
+  int32_t iSliceIndex = 0;
+  int32_t iEndOfStreamFlag = 0;
+  FILE* pH264File;
+  uint8_t uiStartCode[4] = {0, 0, 0, 1};
+
+#if defined(ANDROID_NDK)
+  std::string filename = std::string ("/sdcard/") + sFileName;
+  ASSERT_TRUE (pH264File = fopen (filename.c_str()));
+#else
+  ASSERT_TRUE (pH264File = fopen (sFileName, "rb"));
+#endif
+  fseek (pH264File, 0L, SEEK_END);
+  iFileSize = (int32_t) ftell (pH264File);
+  fseek (pH264File, 0L, SEEK_SET);
+  pBuf = new uint8_t[iFileSize + 4];
+  fread (pBuf, 1, iFileSize, pH264File);
+  memcpy (pBuf + iFileSize, &uiStartCode[0], 4); //confirmed_safe_unsafe_usage
+  while (true) {
+    if (iBufPos >= iFileSize) {
+      iEndOfStreamFlag = true;
+      if (iEndOfStreamFlag)
+        m_pDec->SetOption (DECODER_OPTION_END_OF_STREAM, (void*)&iEndOfStreamFlag);
+      break;
+    }
+    for (i = 0; i < iFileSize; i++) {
+      if ((pBuf[iBufPos + i] == 0 && pBuf[iBufPos + i + 1] == 0 && pBuf[iBufPos + i + 2] == 0 && pBuf[iBufPos + i + 3] == 1
+           && i > 0)) {
+        break;
+      }
+    }
+    iSliceSize = i;
+    m_pDec->DecodeFrame2 (pBuf + iBufPos, iSliceSize, m_pData, &m_sBufferInfo);
+    m_pDec->DecodeFrame2 (NULL, 0, m_pData, &m_sBufferInfo);
+    iBufPos += iSliceSize;
+    ++ iSliceIndex;
+  }
+
+  fclose (pH264File);
+  if (pBuf) {
+    delete[] pBuf;
+    pBuf = NULL;
+  }
+
+
+}
 //Mock input data for test
 void DecoderInterfaceTest::MockPacketType (const EWelsNalUnitType eNalUnitType, const int iPacketLength) {
   switch (eNalUnitType) {
@@ -340,7 +396,89 @@
   //TODO
 }
 
+//DECODER_OPTION_GET_STATISTICS
+void DecoderInterfaceTest::TestGetDecStatistics() {
+  CM_RETURN eRet;
+  SDecoderStatistics sDecStatic;
+  int32_t iError = 0;
 
+  Init();
+  // setoption not support,
+  eRet = (CM_RETURN)m_pDec->SetOption (DECODER_OPTION_GET_STATISTICS, NULL);
+  EXPECT_EQ (eRet, cmInitParaError);
+  //EC on UT
+  iError = 2;
+  m_pDec->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iError);
+  //Decoder error bs
+  DecoderBs ("res/Error_I_P.264");
+  m_pDec->GetOption (DECODER_OPTION_GET_STATISTICS, &sDecStatic);
+  EXPECT_EQ (57, sDecStatic.uiAvgEcRatio);
+  EXPECT_EQ (5, sDecStatic.uiDecodedFrameCount);
+  EXPECT_EQ (288, sDecStatic.uiHeight);
+  EXPECT_EQ (1, sDecStatic.uiIDRRecvNum);
+  EXPECT_EQ (3, sDecStatic.uiResolutionChangeTimes);
+  EXPECT_EQ (352, sDecStatic.uiWidth);
+  EXPECT_EQ (4, sDecStatic.uiEcFrameNum);
+  EXPECT_EQ (2, sDecStatic.uiEcIDRNum);
+  EXPECT_EQ (0, sDecStatic.uiIDRLostNum);
+  Uninit();
+
+  //Decoder error bs when the first IDR lost
+  Init();
+  iError = 2;
+  m_pDec->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iError);
+  DecoderBs ("res/BA_MW_D_IDR_LOST.264");
+  m_pDec->GetOption (DECODER_OPTION_GET_STATISTICS, &sDecStatic);
+  EXPECT_EQ (0, sDecStatic.uiAvgEcRatio);
+  EXPECT_EQ (97, sDecStatic.uiDecodedFrameCount);
+  EXPECT_EQ (144, sDecStatic.uiHeight);
+  EXPECT_EQ (3, sDecStatic.uiIDRRecvNum);
+  EXPECT_EQ (0, sDecStatic.uiEcIDRNum);
+  EXPECT_EQ (1, sDecStatic.uiResolutionChangeTimes);
+  EXPECT_EQ (176, sDecStatic.uiWidth);
+  EXPECT_EQ (27, sDecStatic.uiEcFrameNum);
+  EXPECT_EQ (1, sDecStatic.uiIDRLostNum);
+  Uninit();
+
+  //ecoder error bs when the first P lost
+  Init();
+  iError = 2;
+  m_pDec->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iError);
+
+  DecoderBs ("res/BA_MW_D_P_LOST.264");
+
+  m_pDec->GetOption (DECODER_OPTION_GET_STATISTICS, &sDecStatic);
+  EXPECT_EQ (0, sDecStatic.uiAvgEcRatio);
+  EXPECT_EQ (99, sDecStatic.uiDecodedFrameCount);
+  EXPECT_EQ (144, sDecStatic.uiHeight);
+  EXPECT_EQ (4, sDecStatic.uiIDRRecvNum);
+  EXPECT_EQ (0, sDecStatic.uiEcIDRNum);
+  EXPECT_EQ (1, sDecStatic.uiResolutionChangeTimes);
+  EXPECT_EQ (176, sDecStatic.uiWidth);
+  EXPECT_EQ (28, sDecStatic.uiEcFrameNum);
+  EXPECT_EQ (0, sDecStatic.uiIDRLostNum);
+  Uninit();
+  //EC enable
+
+  //EC Off UT just correc bitstream
+  Init();
+  iError = 0;
+  m_pDec->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iError);
+  DecoderBs ("res/test_vd_1d.264");
+
+  m_pDec->GetOption (DECODER_OPTION_GET_STATISTICS, &sDecStatic);
+
+  EXPECT_EQ (0, sDecStatic.uiAvgEcRatio);
+  EXPECT_EQ (9, sDecStatic.uiDecodedFrameCount);
+  EXPECT_EQ (192, sDecStatic.uiHeight);
+  EXPECT_EQ (1, sDecStatic.uiIDRRecvNum);
+  EXPECT_EQ (1, sDecStatic.uiResolutionChangeTimes);
+  EXPECT_EQ (320, sDecStatic.uiWidth);
+  EXPECT_EQ (0, sDecStatic.uiEcFrameNum);
+  EXPECT_EQ (0, sDecStatic.uiIDRLostNum);
+  Uninit();
+
+}
 //TEST here for whole tests
 TEST_F (DecoderInterfaceTest, DecoderInterfaceAll) {
 
@@ -370,6 +508,8 @@
   TestTraceCallback();
   //DECODER_OPTION_TRACE_CALLBACK_CONTEXT
   TestTraceCallbackContext();
+  //DECODER_OPTION_GET_STATISTICS
+  TestGetDecStatistics();
 }