From 103fa5bbedc49d9032b014c9b5cc0afb11b8f7bf Mon Sep 17 00:00:00 2001 From: huili2 Date: Mon, 3 Nov 2014 18:17:32 -0800 Subject: [PATCH] enable cross IDR EC method --- codec/api/svc/codec_app_def.h | 4 +- codec/decoder/core/src/decoder.cpp | 8 +- codec/decoder/core/src/error_concealment.cpp | 12 ++- codec/decoder/core/src/manage_dec_ref.cpp | 16 +++- codec/decoder/plus/src/welsDecoderExt.cpp | 2 +- test/decoder/DecUT_ErrorConcealment.cpp | 81 +++++++++++--------- 6 files changed, 75 insertions(+), 48 deletions(-) diff --git a/codec/api/svc/codec_app_def.h b/codec/api/svc/codec_app_def.h index 3889831b..6031229e 100644 --- a/codec/api/svc/codec_app_def.h +++ b/codec/api/svc/codec_app_def.h @@ -133,7 +133,9 @@ typedef enum { 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 diff --git a/codec/decoder/core/src/decoder.cpp b/codec/decoder/core/src/decoder.cpp index 5f7ebe63..15f3a7a9 100644 --- a/codec/decoder/core/src/decoder.cpp +++ b/codec/decoder/core/src/decoder.cpp @@ -160,7 +160,7 @@ void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) { 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 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in } 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 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in //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); diff --git a/codec/decoder/core/src/error_concealment.cpp b/codec/decoder/core/src/error_concealment.cpp index 78f29873..34b510d8 100644 --- 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 @@ void DoErrorConFrameCopy (PWelsDecoderContext pCtx) { 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 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) { 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 //uint8_t *pDstData[3], *pSrcData[3]; bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag; @@ -183,9 +187,11 @@ void ImplementErrorCon (PWelsDecoderContext pCtx) { 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; diff --git a/codec/decoder/core/src/manage_dec_ref.cpp b/codec/decoder/core/src/manage_dec_ref.cpp index ebfbab6a..06ba8114 100644 --- a/codec/decoder/core/src/manage_dec_ref.cpp +++ b/codec/decoder/core/src/manage_dec_ref.cpp @@ -119,9 +119,19 @@ int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) { // 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; diff --git a/codec/decoder/plus/src/welsDecoderExt.cpp b/codec/decoder/plus/src/welsDecoderExt.cpp index 230c1520..3b8d41c4 100644 --- a/codec/decoder/plus/src/welsDecoderExt.cpp +++ b/codec/decoder/plus/src/welsDecoderExt.cpp @@ -274,7 +274,7 @@ long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) { 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, diff --git a/test/decoder/DecUT_ErrorConcealment.cpp b/test/decoder/DecUT_ErrorConcealment.cpp index d9477f1e..98f28bad 100644 --- a/test/decoder/DecUT_ErrorConcealment.cpp +++ b/test/decoder/DecUT_ErrorConcealment.cpp @@ -121,6 +121,9 @@ void DoAncErrorConSliceCopy (PECInputCtx pECCtx) { 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,26 +234,30 @@ TEST (ErrorConTest, DoErrorConFrameCopy) { 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); - - //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); + 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 FreeInputData (pECCtx); } @@ -263,25 +270,25 @@ TEST (ErrorConTest, DoErrorConSliceCopy) { 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); }