diff --git a/codec/decoder/core/inc/error_code.h b/codec/decoder/core/inc/error_code.h index 2ce2b0eb..4fbd9258 100644 --- a/codec/decoder/core/inc/error_code.h +++ b/codec/decoder/core/inc/error_code.h @@ -184,6 +184,7 @@ ERR_INFO_NO_IDR_PIC = ERR_INFO_LOGIC_BASE, // NO IDR picture availa ERR_INFO_EC_NO_NEIGHBOUR_MBS, ERR_INFO_EC_UNEXPECTED_MB_TYPE, ERR_INFO_EC_NO_ENOUGH_NEIGHBOUR_MBS, +ERR_INFO_DUPLICATE_FRAME_NUM, //for LTR ERR_INFO_INVALID_MMCO_OPCODE_BASE, ERR_INFO_INVALID_MMCO_SHORT2UNUSED, diff --git a/codec/decoder/core/src/decoder_core.cpp b/codec/decoder/core/src/decoder_core.cpp index 3b6a794b..4be9be50 100644 --- a/codec/decoder/core/src/decoder_core.cpp +++ b/codec/decoder/core/src/decoder_core.cpp @@ -2360,6 +2360,8 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf if (uiNalRefIdc > 0) { iRet = WelsMarkAsRef (pCtx); if (iRet != ERR_NONE) { + if (iRet == ERR_INFO_DUPLICATE_FRAME_NUM) + pCtx->iErrorCode |= dsBitstreamError; if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) { pCtx->pDec = NULL; return iRet; diff --git a/codec/decoder/core/src/error_concealment.cpp b/codec/decoder/core/src/error_concealment.cpp index ab0b3576..345cf287 100644 --- a/codec/decoder/core/src/error_concealment.cpp +++ b/codec/decoder/core/src/error_concealment.cpp @@ -431,6 +431,7 @@ void DoErrorConSliceMVCopy (PWelsDecoderContext pCtx) { //Mark erroneous frame as Ref Pic into DPB int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx) { int32_t iRet = WelsMarkAsRef (pCtx); + // Under EC mode, the ERR_INFO_DUPLICATE_FRAME_NUM does not need to be process if (iRet != ERR_NONE) { return iRet; } diff --git a/codec/decoder/core/src/manage_dec_ref.cpp b/codec/decoder/core/src/manage_dec_ref.cpp index fe9366d8..fec60b7b 100644 --- a/codec/decoder/core/src/manage_dec_ref.cpp +++ b/codec/decoder/core/src/manage_dec_ref.cpp @@ -294,6 +294,7 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) { if (iRet != ERR_NONE) { if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) { iRet = RemainOneBufferInDpbForEC (pCtx); + WELS_VERIFY_RETURN_IF (iRet, iRet); } else { return iRet; } @@ -309,6 +310,7 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) { if (iRet != ERR_NONE) { if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) { iRet = RemainOneBufferInDpbForEC (pCtx); + WELS_VERIFY_RETURN_IF (iRet, iRet); } else { return iRet; } @@ -320,11 +322,12 @@ int32_t WelsMarkAsRef (PWelsDecoderContext pCtx) { if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX (1, pCtx->pSps->iNumRefFrames)) { if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) { iRet = RemainOneBufferInDpbForEC (pCtx); + WELS_VERIFY_RETURN_IF (iRet, iRet); } else { return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW; } } - AddShortTermToList (pRefPic, pCtx->pDec); + iRet = AddShortTermToList (pRefPic, pCtx->pDec); } return iRet; @@ -515,6 +518,15 @@ static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic) { pPic->bIsLongRef = false; pPic->iLongTermFrameIdx = -1; if (pRefPic->uiShortRefCount[LIST_0] > 0) { + // Check the duplicate frame_num in short ref list + for (int32_t iPos = 0; iPos < pRefPic->uiShortRefCount[LIST_0]; iPos++) { + if (pPic->iFrameNum == pRefPic->pShortRefList[LIST_0][iPos]->iFrameNum) { + // Replace the previous ref pic with the new one with the same frame_num + pRefPic->pShortRefList[LIST_0][iPos] = pPic; + return ERR_INFO_DUPLICATE_FRAME_NUM; + } + } + memmove (&pRefPic->pShortRefList[LIST_0][1], &pRefPic->pShortRefList[LIST_0][0], pRefPic->uiShortRefCount[LIST_0]*sizeof (PPicture));//confirmed_safe_unsafe_usage }