enable cross IDR EC method

This commit is contained in:
huili2
2014-11-03 18:17:32 -08:00
parent c5029ef275
commit 103fa5bbed
6 changed files with 75 additions and 48 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);
} }