Merge pull request #1500 from syureyi/decoderstatics

decoder statictis adding
This commit is contained in:
sijchen 2014-11-06 14:25:04 +08:00
commit 5cb5c28331
9 changed files with 213 additions and 6 deletions

View File

@ -484,14 +484,14 @@ typedef struct TagVideoDecoderStatistics {
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__

View File

@ -372,6 +372,8 @@ SWelsCabacCtx sWelsCabacContexts[4][WELS_QP_MAX + 1][WELS_CONTEXT_COUNT];
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) {

View File

@ -107,6 +107,14 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
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 @@ int32_t UpdateAccessUnit (PWelsDecoderContext pCtx) {
}
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;

View File

@ -98,9 +98,10 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
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 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
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 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
} //!pMbCorrectlyDecodedFlag[iMbXyIndex]
} //iMbX
} //iMbY
pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
+ ((iMbEcedNum * 100) / iMbNum) ;
}

View File

@ -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 @@ long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
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 @@ long CWelsDecoder::GetOption (DECODER_OPTION eOptID, void* pOption) {
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 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
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 @@ DECODING_STATE CWelsDecoder::DecodeFrame2 (const unsigned char* kpSrc,
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;
}

BIN
res/BA_MW_D_IDR_LOST.264 Normal file

Binary file not shown.

BIN
res/BA_MW_D_P_LOST.264 Normal file

Binary file not shown.

BIN
res/Error_I_P.264 Normal file

Binary file not shown.

View File

@ -30,6 +30,8 @@ class DecoderInterfaceTest : public ::testing::Test {
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 @@ class DecoderInterfaceTest : public ::testing::Test {
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 @@ void DecoderInterfaceTest::Uninit() {
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 @@ void DecoderInterfaceTest::TestTraceCallbackContext() {
//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 @@ TEST_F (DecoderInterfaceTest, DecoderInterfaceAll) {
TestTraceCallback();
//DECODER_OPTION_TRACE_CALLBACK_CONTEXT
TestTraceCallbackContext();
//DECODER_OPTION_GET_STATISTICS
TestGetDecStatistics();
}