enable cross IDR EC method
This commit is contained in:
@@ -133,7 +133,9 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
ERROR_CON_DISABLE = 0,
|
ERROR_CON_DISABLE = 0,
|
||||||
ERROR_CON_FRAME_COPY,
|
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;
|
} ERROR_CON_IDC;
|
||||||
|
|
||||||
typedef enum { //feedback that whether or not have VCL NAL in current AU
|
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->pPicBuff[LIST_1] = NULL;
|
||||||
|
|
||||||
pCtx->bAvcBasedFlag = true;
|
pCtx->bAvcBasedFlag = true;
|
||||||
pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY;
|
pCtx->eErrorConMethod = ERROR_CON_SLICE_COPY_CROSS_IDR;
|
||||||
pCtx->pPreviousDecodedPictureInDpb = NULL;
|
pCtx->pPreviousDecodedPictureInDpb = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -468,7 +468,8 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
iConsumedBytes = 0;
|
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);
|
pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
|
||||||
if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
|
if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
|
||||||
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
|
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
|
||||||
@@ -528,7 +529,8 @@ int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const in
|
|||||||
//last NAL decoding
|
//last NAL decoding
|
||||||
|
|
||||||
iConsumedBytes = 0;
|
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);
|
pNalPayload = ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);
|
||||||
if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
|
if (IS_VCL_NAL (pCtx->sCurNalHead.eNalUnitType, 1)) {
|
||||||
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
|
CheckAndFinishLastPic (pCtx, ppDst, pDstBufInfo);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
namespace WelsDec {
|
namespace WelsDec {
|
||||||
//Init
|
//Init
|
||||||
void InitErrorCon (PWelsDecoderContext pCtx) {
|
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.pCopyLumaFunc = WelsCopy16x16_c;
|
||||||
pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_c;
|
pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_c;
|
||||||
|
|
||||||
@@ -79,6 +79,8 @@ void DoErrorConFrameCopy (PWelsDecoderContext pCtx) {
|
|||||||
uint32_t uiHeightInPixelY = (pCtx->pSps->iMbHeight) << 4;
|
uint32_t uiHeightInPixelY = (pCtx->pSps->iMbHeight) << 4;
|
||||||
int32_t iStrideY = pDstPic->iLinesize[0];
|
int32_t iStrideY = pDstPic->iLinesize[0];
|
||||||
int32_t iStrideUV = pDstPic->iLinesize[1];
|
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
|
if (pSrcPic == NULL) { //no ref pic, assign specific data to picture
|
||||||
memset (pDstPic->pData[0], 128, uiHeightInPixelY * iStrideY);
|
memset (pDstPic->pData[0], 128, uiHeightInPixelY * iStrideY);
|
||||||
memset (pDstPic->pData[1], 128, (uiHeightInPixelY >> 1) * iStrideUV);
|
memset (pDstPic->pData[1], 128, (uiHeightInPixelY >> 1) * iStrideUV);
|
||||||
@@ -97,6 +99,8 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
|
|||||||
int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
|
int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
|
||||||
PPicture pDstPic = pCtx->pDec;
|
PPicture pDstPic = pCtx->pDec;
|
||||||
PPicture pSrcPic = pCtx->pPreviousDecodedPictureInDpb;
|
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];
|
//uint8_t *pDstData[3], *pSrcData[3];
|
||||||
bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
|
bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
|
||||||
@@ -183,9 +187,11 @@ void ImplementErrorCon (PWelsDecoderContext pCtx) {
|
|||||||
if (ERROR_CON_DISABLE == pCtx->eErrorConMethod) {
|
if (ERROR_CON_DISABLE == pCtx->eErrorConMethod) {
|
||||||
pCtx->iErrorCode |= dsBitstreamError;
|
pCtx->iErrorCode |= dsBitstreamError;
|
||||||
return;
|
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);
|
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);
|
DoErrorConSliceCopy (pCtx);
|
||||||
} //TODO add other EC methods here in the future
|
} //TODO add other EC methods here in the future
|
||||||
pCtx->iErrorCode |= dsDataErrorConcealed;
|
pCtx->iErrorCode |= dsDataErrorConcealed;
|
||||||
|
|||||||
@@ -119,9 +119,19 @@ int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
|
|||||||
// IDR lost, set new
|
// IDR lost, set new
|
||||||
pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture
|
pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture
|
||||||
pCtx->iErrorCode |= dsDataErrorConcealed;
|
pCtx->iErrorCode |= dsDataErrorConcealed;
|
||||||
memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel);
|
bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|
||||||
memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
|
|| (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)) && (NULL != pCtx->pPreviousDecodedPictureInDpb);
|
||||||
memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
|
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->iFrameNum = 0;
|
||||||
pRef->iFramePoc = 0;
|
pRef->iFramePoc = 0;
|
||||||
pRef->uiTemporalId = pRef->uiQualityId = 0;
|
pRef->uiTemporalId = pRef->uiQualityId = 0;
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ long CWelsDecoder::SetOption (DECODER_OPTION eOptID, void* pOption) {
|
|||||||
return cmInitParaError;
|
return cmInitParaError;
|
||||||
|
|
||||||
iVal = * ((int*)pOption); // int value for error concealment idc
|
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;
|
m_pDecContext->eErrorConMethod = (ERROR_CON_IDC) iVal;
|
||||||
InitErrorCon (m_pDecContext);
|
InitErrorCon (m_pDecContext);
|
||||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
||||||
|
|||||||
@@ -121,6 +121,9 @@ void DoAncErrorConSliceCopy (PECInputCtx pECCtx) {
|
|||||||
int32_t iMbHeight = (int32_t) pECCtx->iMbHeight;
|
int32_t iMbHeight = (int32_t) pECCtx->iMbHeight;
|
||||||
PPicture pDstPic = &pECCtx->sAncPic;
|
PPicture pDstPic = &pECCtx->sAncPic;
|
||||||
PPicture pSrcPic = pECCtx->pCtx->pPreviousDecodedPictureInDpb;
|
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];
|
//uint8_t *pDstData[3], *pSrcData[3];
|
||||||
bool* pMbCorrectlyDecodedFlag = pECCtx->pMbCorrectlyDecodedFlag;
|
bool* pMbCorrectlyDecodedFlag = pECCtx->pMbCorrectlyDecodedFlag;
|
||||||
@@ -231,26 +234,30 @@ TEST (ErrorConTest, DoErrorConFrameCopy) {
|
|||||||
return;
|
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
|
||||||
InitECCopyData (pECCtx);
|
pECCtx->pCtx->eErrorConMethod = iEC > 0 ? ERROR_CON_FRAME_COPY_CROSS_IDR : ERROR_CON_FRAME_COPY;
|
||||||
//case 1: no reference picture
|
InitECCopyData (pECCtx);
|
||||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = NULL;
|
int32_t iLumaSize = pECCtx->iMbWidth * pECCtx->iMbHeight * 256;
|
||||||
DoErrorConFrameCopy (pECCtx->pCtx);
|
|
||||||
|
|
||||||
int32_t iLumaSize = pECCtx->iMbWidth * pECCtx->iMbHeight * 256;
|
for (int iRef = 0; iRef < 2; ++ iRef) { //no ref, with ref
|
||||||
memset (pECCtx->sAncPic.pData[0], 128, iLumaSize * 3 / 2); //should be the same as known EC method, here all 128
|
pECCtx->pCtx->pPreviousDecodedPictureInDpb = iRef ? &pECCtx->sSrcPic : NULL;
|
||||||
bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
|
for (int iIDR = 0; iIDR < 2; ++ iIDR) { //non IDR, IDR
|
||||||
pECCtx->iMbHeight * 16);
|
pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag = (iIDR > 0);
|
||||||
EXPECT_EQ (bOK, true);
|
//Do reference code method
|
||||||
|
DoErrorConFrameCopy (pECCtx->pCtx);
|
||||||
//case 2: with reference picture
|
//Do anchor method
|
||||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = &pECCtx->sSrcPic;
|
if (iRef && ! ((pECCtx->pCtx->eErrorConMethod == ERROR_CON_FRAME_COPY)
|
||||||
DoErrorConFrameCopy (pECCtx->pCtx);
|
&& (pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag)))
|
||||||
|
memcpy (pECCtx->sAncPic.pData[0], pECCtx->sSrcPic.pData[0], iLumaSize * 3 / 2);
|
||||||
memcpy (pECCtx->sAncPic.pData[0], pECCtx->sSrcPic.pData[0], iLumaSize * 3 / 2);
|
else
|
||||||
bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
|
memset (pECCtx->sAncPic.pData[0], 128, iLumaSize * 3 / 2); //should be the same as known EC method, here all 128
|
||||||
pECCtx->iMbHeight * 16);
|
//Compare results
|
||||||
EXPECT_EQ (bOK, true);
|
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);
|
FreeInputData (pECCtx);
|
||||||
}
|
}
|
||||||
@@ -263,25 +270,25 @@ TEST (ErrorConTest, DoErrorConSliceCopy) {
|
|||||||
FreeInputData (pECCtx);
|
FreeInputData (pECCtx);
|
||||||
return;
|
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],
|
for (int iEC = 0; iEC < 2; ++ iEC) { //ERROR_CON_SLICE_COPY, ERROR_CON_SLICE_COPY_CROSS_IDR
|
||||||
pECCtx->iMbHeight * 16);
|
pECCtx->pCtx->eErrorConMethod = iEC > 0 ? ERROR_CON_SLICE_COPY_CROSS_IDR : ERROR_CON_SLICE_COPY;
|
||||||
EXPECT_EQ (bOK, true);
|
InitECCopyData (pECCtx);
|
||||||
|
for (int iRef = 0; iRef < 2; ++ iRef) { //no ref, with ref
|
||||||
//case 2: with reference picture
|
pECCtx->pCtx->pPreviousDecodedPictureInDpb = iRef ? &pECCtx->sSrcPic : NULL;
|
||||||
pECCtx->pCtx->pPreviousDecodedPictureInDpb = &pECCtx->sSrcPic;
|
for (int iIDR = 0; iIDR < 2; ++ iIDR) { //non IDR, IDR
|
||||||
DoAncErrorConSliceCopy (pECCtx);
|
pECCtx->pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.bIdrFlag = (iIDR > 0);
|
||||||
DoErrorConSliceCopy (pECCtx->pCtx);
|
//Do reference code method
|
||||||
|
DoErrorConSliceCopy (pECCtx->pCtx);
|
||||||
bOK = ComparePictureDataI420 (pECCtx->sAncPic.pData[0], pECCtx->sWelsPic.pData[0], pECCtx->iLinesize[0],
|
//Do anchor method
|
||||||
pECCtx->iMbHeight * 16);
|
DoAncErrorConSliceCopy (pECCtx);
|
||||||
EXPECT_EQ (bOK, true);
|
//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);
|
FreeInputData (pECCtx);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user