ref: 0d16fd61b28fa19a460dc4c85148551c875c04b8
parent: aed7b2316c03d17904ba13374b62209df2953f72
author: huili2 <huili2@cisco.com>
date: Thu Nov 13 14:26:10 EST 2014
add EC method to freeze sequence when resolution changed and decoding IDR error
--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -135,7 +135,8 @@
ERROR_CON_FRAME_COPY,
ERROR_CON_SLICE_COPY,
ERROR_CON_FRAME_COPY_CROSS_IDR,
- ERROR_CON_SLICE_COPY_CROSS_IDR
+ ERROR_CON_SLICE_COPY_CROSS_IDR,
+ ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE
} ERROR_CON_IDC;
typedef enum { //feedback that whether or not have VCL NAL in current AU
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -221,6 +221,10 @@
int32_t iImgWidthInPixel; // width of image in pixel reconstruction picture to be output
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;
+
// Derived common elements
SNalUnitHeader sCurNalHead;
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -145,6 +145,9 @@
pCtx->iImgWidthInPixel = 0;
pCtx->iImgHeightInPixel = 0; // alloc picture data when picture size is available
+ pCtx->iLastImgWidthInPixel = 0;
+ pCtx->iLastImgHeightInPixel = 0;
+ pCtx->bFreezeOutput = false;
pCtx->iFrameNum = -1;
pCtx->iPrevFrameNum = -1;
@@ -160,7 +163,7 @@
pCtx->pPicBuff[LIST_1] = NULL;
pCtx->bAvcBasedFlag = true;
- pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY_CROSS_IDR;
+ pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
pCtx->pPreviousDecodedPictureInDpb = NULL;
}
@@ -270,6 +273,9 @@
// added for safe memory
pCtx->iImgWidthInPixel = 0;
pCtx->iImgHeightInPixel = 0;
+ pCtx->iLastImgWidthInPixel = 0;
+ pCtx->iLastImgHeightInPixel = 0;
+ pCtx->bFreezeOutput = false;
pCtx->bHaveGotMemory = false;
WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
}
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -83,6 +83,7 @@
} else if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag
&& (pCtx->iErrorCode == dsErrorFree)) { //complete non-ECed IDR frame done
pCtx->pDec->bIsComplete = true;
+ pCtx->bFreezeOutput = false;
}
pCtx->iTotalNumMbRec = 0;
@@ -103,9 +104,15 @@
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);
+ pCtx->iLastImgWidthInPixel = pDstInfo->UsrData.sSystemBuffer.iWidth;
+ pCtx->iLastImgHeightInPixel = pDstInfo->UsrData.sSystemBuffer.iHeight;
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete
pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag
&& pPic->bIsComplete); // When EC disable, ECed picture not output
+ else if (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE && pCtx->iErrorCode && bOutResChange)
+ pCtx->bFreezeOutput = true;
if ((pDstInfo->iBufferStatus == 1) && (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag)) {
@@ -120,6 +127,8 @@
pCtx->iErrorCode |= dsBitstreamError;
return -1;
}
+ if (pCtx->bFreezeOutput)
+ pDstInfo->iBufferStatus = 0;
return 0;
}
@@ -394,6 +403,9 @@
pCtx->bEndOfStreamFlag = false;
pCtx->iImgWidthInPixel = 0;
pCtx->iImgHeightInPixel = 0;
+ pCtx->iLastImgWidthInPixel = 0;
+ pCtx->iLastImgHeightInPixel = 0;
+ pCtx->bFreezeOutput = false;
return ERR_NONE;
}
--- a/codec/decoder/core/src/error_concealment.cpp
+++ b/codec/decoder/core/src/error_concealment.cpp
@@ -41,7 +41,8 @@
namespace WelsDec {
//Init
void InitErrorCon (PWelsDecoderContext pCtx) {
- if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) || (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR)) {
+ if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) || (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR)
+ || (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE)) {
pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_c;
pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_c;
@@ -196,7 +197,8 @@
|| (ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)) {
DoErrorConFrameCopy (pCtx);
} else if ((ERROR_CON_SLICE_COPY == pCtx->eErrorConMethod)
- || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)) {
+ || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)
+ || (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod)) {
DoErrorConSliceCopy (pCtx);
} //TODO add other EC methods here in the future
pCtx->iErrorCode |= dsDataErrorConcealed;
--- a/codec/decoder/core/src/manage_dec_ref.cpp
+++ b/codec/decoder/core/src/manage_dec_ref.cpp
@@ -120,7 +120,9 @@
pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture
pCtx->iErrorCode |= dsDataErrorConcealed;
bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)
- || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)) && (NULL != pCtx->pPreviousDecodedPictureInDpb);
+ || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)
+ || (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod))
+ && (NULL != pCtx->pPreviousDecodedPictureInDpb);
bCopyPrevious = bCopyPrevious && (pRef->iWidthInPixel == pCtx->pPreviousDecodedPictureInDpb->iWidthInPixel)
&& (pRef->iHeightInPixel == pCtx->pPreviousDecodedPictureInDpb->iHeightInPixel);
if (bCopyPrevious) {
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -275,7 +275,7 @@
return cmInitParaError;
iVal = * ((int*)pOption); // int value for error concealment idc
- iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_COPY_CROSS_IDR);
+ iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
m_pDecContext->eErrorConMethod = (ERROR_CON_IDC) iVal;
InitErrorCon (m_pDecContext);
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,