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();
}