shithub: openh264

Download patch

ref: 789603a8b1df82f0fcf1f8e28f5786d91b08dc56
parent: 0fa667ac5f1dccad32d1fb79b1e6f2fc0d474999
parent: 103fa5bbedc49d9032b014c9b5cc0afb11b8f7bf
author: dongzha <[email protected]>
date: Thu Nov 6 12:24:17 EST 2014

Merge pull request #1503 from huili2/ec_crossIDR

enable cross IDR EC method

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -133,7 +133,9 @@
 typedef enum {
   ERROR_CON_DISABLE = 0,
   ERROR_CON_FRAME_COPY,
-  ERROR_CON_SLICE_COPY
+  ERROR_CON_SLICE_COPY,
+  ERROR_CON_FRAME_COPY_CROSS_IDR,
+  ERROR_CON_SLICE_COPY_CROSS_IDR
 } ERROR_CON_IDC;
 
 typedef enum { //feedback that whether or not have VCL NAL in current AU
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -160,7 +160,7 @@
   pCtx->pPicBuff[LIST_1]		= NULL;
 
   pCtx->bAvcBasedFlag			= true;
-  pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY;
+  pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY_CROSS_IDR;
   pCtx->pPreviousDecodedPictureInDpb = NULL;
 
 }
@@ -468,7 +468,8 @@
         } else {
 
           iConsumedBytes = 0;
-          pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] = 0; // set 4 reserved bytes to zero
+          pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] =
+                               0; // set 4 reserved bytes to zero
           pNalPayload	= ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
           if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
             CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
@@ -528,7 +529,8 @@
     //last NAL decoding
 
     iConsumedBytes = 0;
-    pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] = 0; // set 4 reserved bytes to zero
+    pDstNal[iDstIdx] = pDstNal[iDstIdx + 1] = pDstNal[iDstIdx + 2] = pDstNal[iDstIdx + 3] =
+                         0; // set 4 reserved bytes to zero
     pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
     if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
       CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
--- a/codec/decoder/core/src/error_concealment.cpp
+++ b/codec/decoder/core/src/error_concealment.cpp
@@ -41,7 +41,7 @@
 namespace WelsDec {
 //Init
 void InitErrorCon (PWelsDecoderContext pCtx) {
-  if (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) {
+  if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) || (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR)) {
     pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_c;
     pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_c;
 
@@ -79,6 +79,8 @@
   uint32_t uiHeightInPixelY = (pCtx->pSps->iMbHeight) << 4;
   int32_t iStrideY = pDstPic->iLinesize[0];
   int32_t iStrideUV = pDstPic->iLinesize[1];
+  if ((pCtx->eErrorConMethod == ERROR_CON_FRAME_COPY) && (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag))
+    pSrcPic = NULL; //no cross IDR method, should fill in data instead of copy
   if (pSrcPic == NULL) { //no ref pic, assign specific data to picture
     memset (pDstPic->pData[0], 128, uiHeightInPixelY * iStrideY);
     memset (pDstPic->pData[1], 128, (uiHeightInPixelY >> 1) * iStrideUV);
@@ -97,6 +99,8 @@
   int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
   PPicture pDstPic = pCtx->pDec;
   PPicture pSrcPic = pCtx->pPreviousDecodedPictureInDpb;
+  if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) && (pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag))
+    pSrcPic = NULL; //no cross IDR method, should fill in data instead of copy
 
   int32_t iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
   //uint8_t *pDstData[3], *pSrcData[3];
@@ -188,9 +192,11 @@
   if (ERROR_CON_DISABLE == pCtx->eErrorConMethod) {
     pCtx->iErrorCode |= dsBitstreamError;
     return;
-  } else if (ERROR_CON_FRAME_COPY == pCtx->eErrorConMethod) {
+  } else if ((ERROR_CON_FRAME_COPY == pCtx->eErrorConMethod)
+             || (ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)) {
     DoErrorConFrameCopy (pCtx);
-  } else if (ERROR_CON_SLICE_COPY == pCtx->eErrorConMethod) {
+  } else if ((ERROR_CON_SLICE_COPY == pCtx->eErrorConMethod)
+             || (ERROR_CON_SLICE_COPY_CROSS_IDR == 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
@@ -119,9 +119,19 @@
         // IDR lost, set new
         pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture
         pCtx->iErrorCode |= dsDataErrorConcealed;
-        memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel);
-        memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
-        memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
+        bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)
+                              || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)) && (NULL != pCtx->pPreviousDecodedPictureInDpb);
+        bCopyPrevious = bCopyPrevious && (pRef->iWidthInPixel == pCtx->pPreviousDecodedPictureInDpb->iWidthInPixel)
+                        && (pRef->iHeightInPixel == pCtx->pPreviousDecodedPictureInDpb->iHeightInPixel);
+        if (bCopyPrevious) {
+          memcpy (pRef->pData[0], pCtx->pPreviousDecodedPictureInDpb->pData[0], pRef->iLinesize[0] * pRef->iHeightInPixel);
+          memcpy (pRef->pData[1], pCtx->pPreviousDecodedPictureInDpb->pData[1], pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
+          memcpy (pRef->pData[2], pCtx->pPreviousDecodedPictureInDpb->pData[2], pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
+        } else {
+          memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel);
+          memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
+          memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
+        }
         pRef->iFrameNum = 0;
         pRef->iFramePoc = 0;
         pRef->uiTemporalId = pRef->uiQualityId = 0;
--- 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);
+    iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_COPY_CROSS_IDR);
     m_pDecContext->eErrorConMethod = (ERROR_CON_IDC) iVal;
     InitErrorCon (m_pDecContext);
     WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
--- a/test/decoder/DecUT_ErrorConcealment.cpp
+++ b/test/decoder/DecUT_ErrorConcealment.cpp
@@ -121,6 +121,9 @@
   int32_t iMbHeight = (int32_t) pECCtx->iMbHeight;
   PPicture pDstPic = &pECCtx->sAncPic;
   PPicture pSrcPic = pECCtx->pCtx->pPreviousDecodedPictureInDpb;
+  if ((pECCtx->pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY)
+      && (pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag))
+    pSrcPic = NULL;
 
   //uint8_t *pDstData[3], *pSrcData[3];
   bool* pMbCorrectlyDecodedFlag = pECCtx->pMbCorrectlyDecodedFlag;
@@ -231,27 +234,31 @@
     return;
   }
 
-  pECCtx->pCtx->eErrorConMethod = ERROR_CON_FRAME_COPY;
-  InitECCopyData (pECCtx);
-  //case 1: no reference picture
-  pECCtx->pCtx->pPreviousDecodedPictureInDpb = NULL;
-  DoErrorConFrameCopy (pECCtx->pCtx);
+  for (int iEC = 0; iEC < 2; ++ iEC) { //ERROR_CON_FRAME_COPY, ERROR_CON_FRAME_COPY_CROSS_IDR
+    pECCtx->pCtx->eErrorConMethod = iEC > 0 ? ERROR_CON_FRAME_COPY_CROSS_IDR : ERROR_CON_FRAME_COPY;
+    InitECCopyData (pECCtx);
+    int32_t iLumaSize = pECCtx->iMbWidth * pECCtx->iMbHeight * 256;
 
-  int32_t iLumaSize = pECCtx->iMbWidth * pECCtx->iMbHeight * 256;
-  memset (pECCtx->sAncPic.pData[0], 128, iLumaSize * 3 / 2); //should be the same as known EC method, here all 128
-  bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
-                                pECCtx->iMbHeight * 16);
-  EXPECT_EQ (bOK, true);
+    for (int iRef = 0; iRef < 2; ++ iRef) { //no ref, with ref
+      pECCtx->pCtx->pPreviousDecodedPictureInDpb = iRef ? &pECCtx->sSrcPic : NULL;
+      for (int iIDR = 0; iIDR < 2; ++ iIDR) { //non IDR, IDR
+        pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag = (iIDR > 0);
+        //Do reference code method
+        DoErrorConFrameCopy (pECCtx->pCtx);
+        //Do anchor method
+        if (iRef && ! ((pECCtx->pCtx->eErrorConMethod == ERROR_CON_FRAME_COPY)
+                       && (pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag)))
+          memcpy (pECCtx->sAncPic.pData[0], pECCtx->sSrcPic.pData[0], iLumaSize * 3 / 2);
+        else
+          memset (pECCtx->sAncPic.pData[0], 128, iLumaSize * 3 / 2); //should be the same as known EC method, here all 128
+        //Compare results
+        bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
+                                      pECCtx->iMbHeight * 16);
+        EXPECT_EQ (bOK, true);
+      } //non IDR, IDR
+    } // no ref, with ref
+  } //FRAME_COPY methods
 
-  //case 2: with reference picture
-  pECCtx->pCtx->pPreviousDecodedPictureInDpb = &pECCtx->sSrcPic;
-  DoErrorConFrameCopy (pECCtx->pCtx);
-
-  memcpy (pECCtx->sAncPic.pData[0], pECCtx->sSrcPic.pData[0], iLumaSize * 3 / 2);
-  bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
-                                pECCtx->iMbHeight * 16);
-  EXPECT_EQ (bOK, true);
-
   FreeInputData (pECCtx);
 }
 
@@ -263,25 +270,25 @@
     FreeInputData (pECCtx);
     return;
   }
-  pECCtx->pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY;
-  InitECCopyData (pECCtx);
-  //case 1: no reference picture
-  pECCtx->pCtx->pPreviousDecodedPictureInDpb = NULL;
-  DoAncErrorConSliceCopy (pECCtx);
-  DoErrorConSliceCopy (pECCtx->pCtx);
 
-  bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
-                                pECCtx->iMbHeight * 16);
-  EXPECT_EQ (bOK, true);
-
-  //case 2: with reference picture
-  pECCtx->pCtx->pPreviousDecodedPictureInDpb = &pECCtx->sSrcPic;
-  DoAncErrorConSliceCopy (pECCtx);
-  DoErrorConSliceCopy (pECCtx->pCtx);
-
-  bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
-                                pECCtx->iMbHeight * 16);
-  EXPECT_EQ (bOK, true);
+  for (int iEC = 0; iEC < 2; ++ iEC) { //ERROR_CON_SLICE_COPY, ERROR_CON_SLICE_COPY_CROSS_IDR
+    pECCtx->pCtx->eErrorConMethod = iEC > 0 ? ERROR_CON_SLICE_COPY_CROSS_IDR : ERROR_CON_SLICE_COPY;
+    InitECCopyData (pECCtx);
+    for (int iRef = 0; iRef < 2; ++ iRef) { //no ref, with ref
+      pECCtx->pCtx->pPreviousDecodedPictureInDpb = iRef ? &pECCtx->sSrcPic : NULL;
+      for (int iIDR = 0; iIDR < 2; ++ iIDR) { //non IDR, IDR
+        pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag = (iIDR > 0);
+        //Do reference code method
+        DoErrorConSliceCopy (pECCtx->pCtx);
+        //Do anchor method
+        DoAncErrorConSliceCopy (pECCtx);
+        //Compare results
+        bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
+                                      pECCtx->iMbHeight * 16);
+        EXPECT_EQ (bOK, true);
+      } //non IDR, IDR
+    } // no ref, with ref
+  } //FRAME_COPY methods
 
   FreeInputData (pECCtx);
 }