shithub: openh264

Download patch

ref: d74c0f6ae63e1ad6aa4f8e6c60d8946cb6153518
parent: 3ad4d9070ef0cf73f220e0ea17df7e3bcae84ae1
parent: 9d182ee515dca45e69722049a208292a365b8b89
author: huili2 <[email protected]>
date: Thu Oct 16 10:22:43 EDT 2014

Merge pull request #1414 from HaiboZhu/LTR_EC

Add picture bIsComplete flag to reflect the status of decoder

--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -316,7 +316,6 @@
 int32_t iFeedbackTidInAu;
 
 bool bAuReadyFlag;   // true: one au is ready for decoding; false: default value
-bool bDecErrorConedFlag; //true: current decoder is error coned
 
 bool bPrintFrameErrorTraceFlag; //true: can print info for upper layer
 int32_t iIgnoredErrorInfoPacketCount; //store the packet number with error decoding info
--- a/codec/decoder/core/inc/decoder_core.h
+++ b/codec/decoder/core/inc/decoder_core.h
@@ -157,6 +157,7 @@
 void ForceResetCurrentAccessUnit (PAccessUnit pAu);
 void ForceClearCurrentNal (PAccessUnit pAu);
 
+bool bCheckRefPicturesComplete (PWelsDecoderContext pCtx); // Check whether all ref pictures are complete
 } // namespace WelsDec
 
 #endif//WELS_DECODER_CORE_H__
--- a/codec/decoder/core/inc/picture.h
+++ b/codec/decoder/core/inc/picture.h
@@ -63,6 +63,7 @@
 uint8_t		uiRefCount;
 bool		bAvailableFlag;	// indicate whether it is available in this picture memory block.
 
+bool            bIsComplete;	// indicate whether current picture is complete, not from EC
 /*******************************for future use****************************/
 uint8_t		uiTemporalId;
 uint8_t		uiSpatialId;
--- a/codec/decoder/core/src/decoder.cpp
+++ b/codec/decoder/core/src/decoder.cpp
@@ -297,7 +297,6 @@
   pCtx->bReferenceLostAtT0Flag	= true;	// should be true to waiting IDR at incoming AU bits following, 6/4/2010
 #endif //LONG_TERM_REF
   pCtx->bNewSeqBegin = true;
-  pCtx->bDecErrorConedFlag = false; //default: decoder normal status
   pCtx->bPrintFrameErrorTraceFlag = true;
   pCtx->iIgnoredErrorInfoPacketCount = 0;
   return iRet;
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -82,7 +82,7 @@
       return -1;
   } else if (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag
              && (pCtx->iErrorCode == dsErrorFree)) { //complete non-ECed IDR frame done
-    pCtx->bDecErrorConedFlag = false;
+    pCtx->pDec->bIsComplete = true;
   }
 
   pCtx->iTotalNumMbRec = 0;
@@ -104,10 +104,12 @@
   pDstInfo->iBufferStatus = 1;
 
   if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete
-    pDstInfo->iBufferStatus = (int32_t) bFrameCompleteFlag;
+    pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag
+                                         && pPic->bIsComplete); // When EC disable, ECed picture not output
 
-  if (!bFrameCompleteFlag) {
-    pCtx->iErrorCode |= dsBitstreamError;
+  if (pDstInfo->iBufferStatus == 0) {
+    if (!bFrameCompleteFlag)
+      pCtx->iErrorCode |= dsBitstreamError;
     return -1;
   }
 
@@ -1780,6 +1782,8 @@
   int32_t iPpsId = 0;
   int32_t iRet = ERR_NONE;
 
+  bool bAllRefComplete = true; // Assume default all ref picutres are complete
+
   const uint8_t kuiTargetLayerDqId = GetTargetDqId (pCtx->uiTargetDqId, pCtx->pParam);
   const uint8_t kuiDependencyIdMax = (kuiTargetLayerDqId & 0x7F) >> 4;
   int16_t iLastIdD = -1, iLastIdQ = -1;
@@ -1889,6 +1893,7 @@
                      "referencing pictures lost due frame gaps exist, prev_frame_num: %d, curr_frame_num: %d", pCtx->iPrevFrameNum,
                      pSh->iFrameNum);
 
+            bAllRefComplete = false;
             pCtx->iErrorCode |= dsRefLost;
             if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) {
 #ifdef LONG_TERM_REF
@@ -1905,6 +1910,7 @@
         if (iCurrIdD == kuiDependencyIdMax && iCurrIdQ == BASE_QUALITY_ID) {
           iRet = InitRefPicList (pCtx, uiNalRefIdc, pSh->iPicOrderCntLsb);
           if (iRet) {
+            bAllRefComplete = false; // RPLR error, set ref pictures complete flag false
             HandleReferenceLost (pCtx, pNalCur);
             WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
                      "reference picture introduced by this frame is lost during transmission! uiTId: %d",
@@ -1922,6 +1928,7 @@
           WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
                    "DecodeCurrentAccessUnit() failed (%d) in frame: %d uiDId: %d uiQId: %d",
                    iRet, pSh->iFrameNum, iCurrIdD, iCurrIdQ);
+          bAllRefComplete = false;
           HandleReferenceLostL0 (pCtx, pNalCur);
           if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) {
             return iRet;
@@ -1929,9 +1936,13 @@
         }
         if (bReconstructSlice)	{
           if (WelsDecodeConstructSlice (pCtx, pNalCur)) {
+            pCtx->pDec->bIsComplete = false; // reconstruction error, directly set the flag false
             return -1;
           }
         }
+        if (bAllRefComplete && (pCtx->sRefPic.uiRefCount[LIST_0] > 0 || pCtx->eSliceType != I_SLICE)) {
+          bAllRefComplete &= bCheckRefPicturesComplete (pCtx);
+        }
       }
 #if defined (_DEBUG) &&  !defined (CODEC_FOR_TESTBED)
       fprintf (stderr, "cur_frame : %d	iCurrIdD : %d\n ",
@@ -1954,6 +1965,12 @@
         break;
     }
 
+    // Set the current dec picture complete flag. The flag will be reset when current picture need do ErrorCon.
+    pCtx->pDec->bIsComplete = bAllRefComplete;
+    if (!pCtx->pDec->bIsComplete) {  // Ref pictures ECed, result in ECed
+      pCtx->iErrorCode |= dsDataErrorConcealed;
+    }
+
     // A dq layer decoded here
 #if defined (_DEBUG) &&  !defined (CODEC_FOR_TESTBED)
 #undef fprintf
@@ -2030,5 +2047,43 @@
     }
   }
   return ERR_NONE;
+}
+
+bool bCheckRefPicturesComplete (PWelsDecoderContext pCtx) {
+  // Multi Reference, RefIdx may differ
+  bool bAllRefComplete = true;
+  int32_t iRealMbIdx;
+  for (int32_t iMbIdx = 0; bAllRefComplete
+       && iMbIdx < pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.iTotalMbInCurSlice; iMbIdx++) {
+    iRealMbIdx = pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.iFirstMbInSlice + iMbIdx;
+    switch (pCtx->pCurDqLayer->pMbType[iRealMbIdx]) {
+    case MB_TYPE_SKIP:
+    case MB_TYPE_16x16:
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][0] ]->bIsComplete;
+      break;
+
+    case MB_TYPE_16x8:
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][0] ]->bIsComplete;
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][8] ]->bIsComplete;
+      break;
+
+    case MB_TYPE_8x16:
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][0] ]->bIsComplete;
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][2] ]->bIsComplete;
+      break;
+
+    case MB_TYPE_8x8:
+    case MB_TYPE_8x8_REF0:
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][0] ]->bIsComplete;
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][2] ]->bIsComplete;
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][8] ]->bIsComplete;
+      bAllRefComplete &= pCtx->sRefPic.pRefList[ LIST_0 ][ pCtx->pCurDqLayer->pRefIndex[0][iRealMbIdx][10] ]->bIsComplete;
+      break;
+
+    default:
+      break;
+    }
+  }
+  return bAllRefComplete;
 }
 } // namespace WelsDec
--- a/codec/decoder/core/src/error_concealment.cpp
+++ b/codec/decoder/core/src/error_concealment.cpp
@@ -189,7 +189,7 @@
     DoErrorConSliceCopy (pCtx);
   } //TODO add other EC methods here in the future
   pCtx->iErrorCode |= dsDataErrorConcealed;
-  pCtx->bDecErrorConedFlag = true;
+  pCtx->pDec->bIsComplete = false; // Set complete flag to false after do EC.
 }
 
 } // namespace WelsDec
--- a/codec/decoder/core/src/manage_dec_ref.cpp
+++ b/codec/decoder/core/src/manage_dec_ref.cpp
@@ -73,6 +73,7 @@
     pRef->uiTemporalId = -1;
     pRef->uiSpatialId = -1;
     pRef->iSpsId = -1;
+    pRef->bIsComplete = false;
   }
 }
 
@@ -115,6 +116,9 @@
     if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) { //IDR lost!, recover it for future decoding with data all set to 0
       PPicture pRef = PrefetchPic (pCtx->pPicBuff[0]);
       if (pRef != NULL) {
+        // 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);
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -438,17 +438,11 @@
     }
     if ((m_pDecContext->eErrorConMethod != ERROR_CON_DISABLE) && (pDstInfo->iBufferStatus == 1)) {
       //TODO after dec status updated
-      m_pDecContext->bDecErrorConedFlag = true;
       m_pDecContext->iErrorCode |= dsDataErrorConcealed;
     }
     return (DECODING_STATE) m_pDecContext->iErrorCode;
-  } else { //decoding correct, but may have ECed status
-    if (m_pDecContext->bDecErrorConedFlag) { //TODO after dec status updated
-      if (m_pDecContext->eErrorConMethod != ERROR_CON_DISABLE) //EC is on
-        m_pDecContext->iErrorCode |= dsDataErrorConcealed;
-      return (DECODING_STATE) m_pDecContext->iErrorCode;
-    }
   }
+  // else Error free, the current codec works well
 
   return dsErrorFree;
 }
@@ -457,7 +451,7 @@
     const int kiSrcLen,
     SParserBsInfo* pDstInfo) {
 //TODO, add function here
- return (DECODING_STATE) m_pDecContext->iErrorCode;
+  return (DECODING_STATE) m_pDecContext->iErrorCode;
 }
 
 DECODING_STATE CWelsDecoder::DecodeFrame (const unsigned char* kpSrc,
--- a/test/api/encode_decode_api_test.cpp
+++ b/test/api/encode_decode_api_test.cpp
@@ -103,6 +103,8 @@
 
 class EncodeDecodeTestAPI : public EncodeDecodeTestBase {
  public:
+  uint8_t iRandValue;
+ public:
   void SetUp() {
     EncodeDecodeTestBase::SetUp();
   }
@@ -115,17 +117,17 @@
     EncodeDecodeTestBase::prepareParam (width, height, framerate);
   }
 
-  void prepareEncDecParam(const EncodeDecodeFileParamBase EncDecFileParam);
+  void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam);
   void EncodeOneFrame() {
     int frameSize = EncPic.iPicWidth * EncPic.iPicHeight * 3 / 2;
-    memset (buf_.data(), rand() % 256, frameSize);
+    memset (buf_.data(), iRandValue, (frameSize >> 2));
+    memset (buf_.data() + (frameSize >> 2), rand() % 256, (frameSize - (frameSize >> 2)));
     int rv = encoder_->EncodeFrame (&EncPic, &info);
     ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
   }
 };
 
-void EncodeDecodeTestAPI::prepareEncDecParam(const EncodeDecodeFileParamBase EncDecFileParam)
-{
+void EncodeDecodeTestAPI::prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam) {
   // for encoder
   // I420: 1(Y) + 1/4(U) + 1/4(V)
   int frameSize = EncDecFileParam.width * EncDecFileParam.height * 3 / 2;
@@ -145,6 +147,9 @@
 
   //for decoder
   memset (&info, 0, sizeof (SFrameBSInfo));
+
+  //set a fixed random value
+  iRandValue = rand() % 256;
 }
 
 
@@ -165,7 +170,7 @@
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
 
   int iIdx = 0;
   while (iIdx <= p.numframes) {
@@ -201,7 +206,7 @@
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
 
   int32_t iEncFrameNum = -1;
   int32_t iDecFrameNum;
@@ -240,7 +245,7 @@
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
 
   int32_t iEncCurIdrPicId = 0;
   int32_t iDecCurIdrPicId;
@@ -479,7 +484,7 @@
   int rv = encoder_->InitializeExt (&param_);
   ASSERT_TRUE (rv == cmResultSuccess);
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
 
   int32_t iTraceLevel = WELS_LOG_QUIET;
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
@@ -574,7 +579,7 @@
   ASSERT_TRUE (rv == cmResultSuccess);
   m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
 
   int32_t iTraceLevel = WELS_LOG_QUIET;
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
@@ -593,7 +598,7 @@
   int iLossIdx = 0;
   bool bVCLLoss = false;
   while (iIdx <= p.numframes) {
-	EncodeOneFrame();
+    EncodeOneFrame();
     if (m_LTR_Recover_Request.uiFeedbackType == IDR_RECOVERY_REQUEST) {
       ASSERT_TRUE (info.eFrameType == videoFrameTypeIDR);
     }
@@ -639,7 +644,7 @@
   ASSERT_EQ (0, rv);
   m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
   int32_t iTraceLevel = WELS_LOG_QUIET;
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
@@ -695,7 +700,7 @@
   ASSERT_TRUE (rv == cmResultSuccess);
   m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
   int32_t iTraceLevel = WELS_LOG_QUIET;
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
@@ -752,7 +757,7 @@
   int rv = encoder_->InitializeExt (&param_);
   ASSERT_TRUE (rv == cmResultSuccess);
   m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
   int32_t iTraceLevel = WELS_LOG_QUIET;
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
@@ -825,7 +830,7 @@
   ASSERT_TRUE (rv == cmResultSuccess);
   m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
   int32_t iTraceLevel = WELS_LOG_QUIET;
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
@@ -887,7 +892,7 @@
   ASSERT_TRUE (rv == cmResultSuccess);
   m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
   int32_t iTraceLevel = WELS_LOG_QUIET;
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
@@ -944,7 +949,7 @@
   ASSERT_TRUE (rv == cmResultSuccess);
   m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
   int32_t iTraceLevel = WELS_LOG_QUIET;
   pFunc = TestOutPutTrace;
   pTraceInfo = &sTrace;
@@ -1009,7 +1014,7 @@
   ASSERT_TRUE (rv == cmResultSuccess);
   m_LTR_Recover_Request.uiFeedbackType = NO_RECOVERY_REQUSET;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
 
   int32_t iTraceLevel = WELS_LOG_QUIET;
   pFunc = NULL;
@@ -1082,7 +1087,7 @@
 
   //Start for enc/dec
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
   int32_t iTraceLevel = WELS_LOG_QUIET;
   encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &iTraceLevel);
   decoder_->SetOption (DECODER_OPTION_TRACE_LEVEL, &iTraceLevel);
@@ -1113,7 +1118,7 @@
         rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize,
                                      info.sLayerInfo[0].pNalLengthInByte[iPacketNum], pData, &dstBufInfo_);
         if (uiEcIdc == ERROR_CON_DISABLE)
-         EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+          EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
       }
       //EC_IDC should not change till now
       decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
@@ -1170,7 +1175,7 @@
   int len = 0;
   unsigned char* pData[3] = { NULL };
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
   //Frame 0: IDR, EC_IDC=DISABLE, loss = 0
   EncodeOneFrame();
   encToDecData (info, len);
@@ -1241,10 +1246,9 @@
   EXPECT_EQ (rv, 0); //parse correct
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
-  if (rv == 0) //TODO: should depend on if ref-frame is OK.
-    EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
-  else
-    EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+  //Ref picture is ECed, so current status is ECed, when EC disable, NO output
+  EXPECT_TRUE (rv & 32);
+  EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
   iIdx++;
 
   //Frame 5: P, EC_IDC=DISABLE, loss = 1
@@ -1269,7 +1273,7 @@
   pData[0] = pData[1] = pData[2] = 0;
   memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
   rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
-  EXPECT_TRUE (rv != 0); //parse correct, but previous decoding error, ECed
+  EXPECT_TRUE (rv == 0); // Now the parse process is Error_None, and the reconstruction will has error return
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //no output
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
   EXPECT_TRUE (rv != 0); //not sure if previous data drop would be detected in construction
@@ -1306,7 +1310,7 @@
   unsigned char* pData[3] = { NULL };
   int iTotalSliceSize = 0;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
 
   //Frame 0: IDR, EC_IDC=2, loss = 2
   EncodeOneFrame();
@@ -1325,7 +1329,7 @@
   rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, iTotalSliceSize, pData, &dstBufInfo_);
   EXPECT_EQ (rv, 0); //parse correct
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
-  EXPECT_EQ (rv, 0); //parse correct
+  EXPECT_EQ (rv, 0); // Reconstruct first slice OK
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //slice incomplete, no output
   iIdx++;
 
@@ -1361,10 +1365,9 @@
   rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
   EXPECT_EQ (rv, 0); //parse correct
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
-  if (rv == 0) //TODO: should depend on if ref-frame is OK.
-    EXPECT_EQ (dstBufInfo_.iBufferStatus, 1);
-  else
-    EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
+  // Ref picture is ECed, so reconstructed picture is ECed
+  EXPECT_TRUE (rv & 32);
+  EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
   iIdx++;
 
   //set EC=SLICE_COPY
@@ -1381,7 +1384,7 @@
   decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
   EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_FRAME_COPY);
   rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf + iTotalSliceSize, len, pData, &dstBufInfo_);
-  EXPECT_TRUE (rv & 32);
+  EXPECT_EQ (rv, 0); //parse correct
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 0);
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
   EXPECT_TRUE (rv & 32);
@@ -1402,10 +1405,10 @@
   EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_DISABLE);
   rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
   EXPECT_TRUE (rv != 0);
-  EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
+  EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); // EC_IDC=0, previous picture slice lost, no output
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
   EXPECT_TRUE (rv != 0);
-  EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
+  EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); // No ref picture, no output
   iIdx++;
 
 }
@@ -1440,7 +1443,7 @@
   unsigned char* pData[3] = { NULL };
   int iTotalSliceSize = 0;
 
-  prepareEncDecParam(p);
+  prepareEncDecParam (p);
 
   //set EC=DISABLE
   uiEcIdc = (uint32_t) (ERROR_CON_DISABLE);
@@ -1509,7 +1512,7 @@
   decoder_->GetOption (DECODER_OPTION_ERROR_CON_IDC, &uiGet);
   EXPECT_EQ (uiGet, (uint32_t) ERROR_CON_SLICE_COPY);
   rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, len, pData, &dstBufInfo_);
-  EXPECT_TRUE (rv & 32); //ECed
+  EXPECT_TRUE (rv & 32); //parse OK but frame 2 ECed
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //slice loss but ECed output Frame 2
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction
   EXPECT_TRUE (rv & 32);
@@ -1533,11 +1536,9 @@
   EXPECT_TRUE (rv != 0); //previous slice not outputted, will return error due to incomplete frame
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
-  //not sure if current frame can be correctly decoded
-  if (rv == 0)
-    EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //output previous pic
-  else
-    EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
+  // previous frame NOT output, no ref
+  EXPECT_TRUE (rv != 0);
+  EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
   iIdx++;
 
   //Frame 5: IDR, EC_IDC=2->0, loss = 0
@@ -1560,10 +1561,10 @@
   pData[0] = pData[1] = pData[2] = 0;
   memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
   rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, iTotalSliceSize, pData, &dstBufInfo_);
-  EXPECT_TRUE (rv != 0); //TODO: should be correct, now ECed status will return error
+  EXPECT_TRUE (rv == 0); // IDR status return error_free
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //frame incomplete
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
-  EXPECT_TRUE (rv != 0); //TODO: as above
+  EXPECT_TRUE (rv == 0);
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //output previous pic
   //set EC=DISABLE for slice 2
   encToDecSliceData (1, 1, info, len); //slice 1
@@ -1577,7 +1578,7 @@
   EXPECT_EQ (rv, 0); //Parse correct under no EC
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 0); //frame incomplete
   rv = decoder_->DecodeFrame2 (NULL, 0, pData, &dstBufInfo_); //reconstruction,
-  EXPECT_EQ (rv, 0); //Parse correct under no EC
+  EXPECT_EQ (rv, 0);
   EXPECT_EQ (dstBufInfo_.iBufferStatus, 1); //output previous pic
   iIdx++;