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