enable cross IDR EC method
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
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);
|
||||
//case 1: no reference picture
|
||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = NULL;
|
||||
DoErrorConFrameCopy (pECCtx->pCtx);
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
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);
|
||||
//case 1: no reference picture
|
||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = NULL;
|
||||
DoAncErrorConSliceCopy (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);
|
||||
|
||||
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);
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user