Merge pull request #1500 from syureyi/decoderstatics
decoder statictis adding
This commit is contained in:
commit
5cb5c28331
@ -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__
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
BIN
res/BA_MW_D_IDR_LOST.264
Normal file
Binary file not shown.
BIN
res/BA_MW_D_P_LOST.264
Normal file
BIN
res/BA_MW_D_P_LOST.264
Normal file
Binary file not shown.
BIN
res/Error_I_P.264
Normal file
BIN
res/Error_I_P.264
Normal file
Binary file not shown.
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user