shithub: openh264

Download patch

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,