Merge pull request #709 from huili2/ec_mb_check
add EC frame/slice copy.
This commit is contained in:
commit
9b0322330c
@ -112,6 +112,7 @@ typedef enum {
|
||||
//enuerate the types of error concealment methods
|
||||
typedef enum {
|
||||
ERROR_CON_DISABLE = 0,
|
||||
ERROR_CON_FRAME_COPY,
|
||||
ERROR_CON_SLICE_COPY,
|
||||
} ERROR_CON_IDC;
|
||||
|
||||
|
@ -199,6 +199,8 @@ void H264DecodeInstance (ISVCDecoder* pDecoder, const char* kpH264FileName, cons
|
||||
pDecoder->GetOption (DECODER_OPTION_VCL_NAL, &iFeedbackVclNalInAu);
|
||||
int32_t iFeedbackTidInAu;
|
||||
pDecoder->GetOption (DECODER_OPTION_TEMPORAL_ID, &iFeedbackTidInAu);
|
||||
int32_t iErrorConMethod = ERROR_CON_SLICE_COPY;
|
||||
pDecoder->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iErrorConMethod);
|
||||
//~end for
|
||||
|
||||
iStart = WelsTime();
|
||||
|
@ -74,6 +74,7 @@ struct TagDqLayer {
|
||||
int8_t (*pNzcRs)[24];
|
||||
int8_t* pResidualPredFlag;
|
||||
int8_t* pInterPredictionDoneFlag;
|
||||
bool* pMbCorrectlyDecodedFlag;
|
||||
int16_t (*pScaledTCoeff)[MB_COEFF_LIST_SIZE];
|
||||
int8_t (*pIntraPredMode)[8]; //0~3 top4x4 ; 4~6 left 4x4; 7 intra16x16
|
||||
int8_t (*pIntra4x4FinalMode)[MB_BLOCK4x4_NUM];
|
||||
|
@ -211,6 +211,7 @@ typedef struct TagWelsDecoderContext {
|
||||
int32_t* pSliceIdc[LAYER_NUM_EXCHANGEABLE]; // using int32_t for slice_idc
|
||||
int8_t* pResidualPredFlag[LAYER_NUM_EXCHANGEABLE];
|
||||
int8_t* pInterPredictionDoneFlag[LAYER_NUM_EXCHANGEABLE];
|
||||
bool* pMbCorrectlyDecodedFlag[LAYER_NUM_EXCHANGEABLE];
|
||||
uint32_t iMbWidth;
|
||||
uint32_t iMbHeight;
|
||||
} sMb;
|
||||
@ -279,6 +280,7 @@ typedef struct TagWelsDecoderContext {
|
||||
#endif
|
||||
bool bNewSeqBegin;
|
||||
int32_t iErrorConMethod; //
|
||||
PPicture pPreviousDecodedPictureInDpb; //pointer to previously decoded picture in DPB for error concealment
|
||||
PGetIntraPredFunc pGetI16x16LumaPredFunc[7]; //h264_predict_copy_16x16;
|
||||
PGetIntraPredFunc pGetI4x4LumaPredFunc[14]; // h264_predict_4x4_t
|
||||
PGetIntraPredFunc pGetIChromaPredFunc[7]; // h264_predict_8x8_t
|
||||
@ -293,7 +295,7 @@ typedef struct TagWelsDecoderContext {
|
||||
|
||||
/* For Block */
|
||||
SBlockFunc sBlockFunc;
|
||||
/* For EC */
|
||||
|
||||
int32_t iCurSeqIntervalTargetDependId;
|
||||
int32_t iCurSeqIntervalMaxPicWidth;
|
||||
int32_t iCurSeqIntervalMaxPicHeight;
|
||||
|
@ -54,7 +54,7 @@ int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx);
|
||||
bool NeedErrorCon (PWelsDecoderContext pCtx);
|
||||
// ImplementErrorConceal
|
||||
// Do actual error concealment
|
||||
int32_t ImplementErrorCon (PWelsDecoderContext pCtx);
|
||||
void ImplementErrorCon (PWelsDecoderContext pCtx);
|
||||
|
||||
} // namespace WelsDec
|
||||
|
||||
|
@ -394,6 +394,7 @@ int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNal
|
||||
}
|
||||
|
||||
++pSlice->iTotalMbInCurSlice;
|
||||
pCurLayer->pMbCorrectlyDecodedFlag[iNextMbXyIndex] = true;
|
||||
|
||||
if (pSliceHeader->pPps->uiNumSliceGroups > 1) {
|
||||
iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex);
|
||||
|
@ -164,7 +164,8 @@ void WelsDecoderDefaults (PWelsDecoderContext pCtx) {
|
||||
pCtx->pPicBuff[LIST_1] = NULL;
|
||||
|
||||
pCtx->bAvcBasedFlag = true;
|
||||
pCtx->iErrorConMethod = ERROR_CON_DISABLE;
|
||||
pCtx->iErrorConMethod = ERROR_CON_SLICE_COPY;
|
||||
pCtx->pPreviousDecodedPictureInDpb = NULL;
|
||||
|
||||
}
|
||||
|
||||
|
@ -54,12 +54,21 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
|
||||
const int32_t kiHeight = pCurDq->iMbHeight << 4;
|
||||
|
||||
const int32_t kiTotalNumMbInCurLayer = pCurDq->iMbWidth * pCurDq->iMbHeight;
|
||||
bool bFrameCompleteFlag = true;
|
||||
|
||||
if (pCtx->iTotalNumMbRec != kiTotalNumMbInCurLayer) {
|
||||
if ((pCtx->iTotalNumMbRec != 0) && (I_SLICE == pCurDq->sLayerInfo.sSliceInLayer.eSliceType)) { //TODO should be IDR instead of I_SLICE!
|
||||
memcpy (& (pCtx->sFrameCrop), & (pCurDq->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader.pSps->sFrameCrop), sizeof (SPosOffset));
|
||||
#ifdef LONG_TERM_REF
|
||||
pCtx->bParamSetsLostFlag = false;
|
||||
#else
|
||||
pCtx->bReferenceLostAtT0Flag = false;
|
||||
#endif //LONG_TERM_REF
|
||||
}
|
||||
WelsLog (pCtx, WELS_LOG_WARNING,
|
||||
"DecodeFrameConstruction():::iTotalNumMbRec:%d, total_num_mb_sps:%d, cur_layer_mb_width:%d, cur_layer_mb_height:%d \n",
|
||||
pCtx->iTotalNumMbRec, kiTotalNumMbInCurLayer, pCurDq->iMbWidth, pCurDq->iMbHeight);
|
||||
return -1;
|
||||
bFrameCompleteFlag = false; //return later after output buffer is done
|
||||
}
|
||||
#ifdef NO_WAITING_AU
|
||||
pCtx->iTotalNumMbRec = 0;
|
||||
@ -99,6 +108,14 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
|
||||
ppDst[2] = ppDst[2] + pCtx->sFrameCrop.iTopOffset * pPic->iLinesize[1] + pCtx->sFrameCrop.iLeftOffset;
|
||||
pDstInfo->iBufferStatus = 1;
|
||||
|
||||
if (pCtx->iErrorConMethod == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete
|
||||
pDstInfo->iBufferStatus = (int32_t) bFrameCompleteFlag;
|
||||
|
||||
if (!bFrameCompleteFlag) {
|
||||
pCtx->iErrorCode |= dsBitstreamError;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -955,6 +972,8 @@ int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWid
|
||||
pCtx->sMb.pInterPredictionDoneFlag[i] = (int8_t*) WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (
|
||||
int8_t), "pCtx->sMb.pInterPredictionDoneFlag[]");
|
||||
|
||||
pCtx->sMb.pMbCorrectlyDecodedFlag[i] = (bool*) WelsMalloc (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (bool), "pCtx->sMb.pMbCorrectlyDecodedFlag[]");
|
||||
|
||||
// check memory block valid due above allocated..
|
||||
WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY,
|
||||
((NULL == pCtx->sMb.pMbType[i]) ||
|
||||
@ -972,7 +991,8 @@ int32_t InitialDqLayersContext (PWelsDecoderContext pCtx, const int32_t kiMaxWid
|
||||
(NULL == pCtx->sMb.pSubMbType[i]) ||
|
||||
(NULL == pCtx->sMb.pSliceIdc[i]) ||
|
||||
(NULL == pCtx->sMb.pResidualPredFlag[i]) ||
|
||||
(NULL == pCtx->sMb.pInterPredictionDoneFlag[i])
|
||||
(NULL == pCtx->sMb.pInterPredictionDoneFlag[i]) ||
|
||||
(NULL == pCtx->sMb.pMbCorrectlyDecodedFlag[i])
|
||||
)
|
||||
)
|
||||
|
||||
@ -1100,6 +1120,12 @@ void UninitialDqLayersContext (PWelsDecoderContext pCtx) {
|
||||
|
||||
pCtx->sMb.pInterPredictionDoneFlag[i] = NULL;
|
||||
}
|
||||
|
||||
if (pCtx->sMb.pMbCorrectlyDecodedFlag[i]) {
|
||||
WelsFree (pCtx->sMb.pMbCorrectlyDecodedFlag[i], "pCtx->sMb.pMbCorrectlyDecodedFlag[]");
|
||||
pCtx->sMb.pMbCorrectlyDecodedFlag[i] = NULL;
|
||||
}
|
||||
|
||||
WelsFree (pDq, "pDq");
|
||||
|
||||
pDq = NULL;
|
||||
@ -1560,8 +1586,6 @@ int32_t ConstructAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferI
|
||||
pCtx->bNewSeqBegin = false;
|
||||
if (ERR_NONE != iErr) {
|
||||
WelsLog (pCtx, WELS_LOG_INFO, "returned error from decoding:[0x%x]\n", iErr);
|
||||
|
||||
pDstInfo->iBufferStatus = 0;
|
||||
return iErr;
|
||||
}
|
||||
|
||||
@ -1651,6 +1675,7 @@ void InitCurDqLayerData (PWelsDecoderContext pCtx, PDqLayer pCurDq) {
|
||||
pCurDq->pSubMbType = pCtx->sMb.pSubMbType[0];
|
||||
pCurDq->pInterPredictionDoneFlag = pCtx->sMb.pInterPredictionDoneFlag[0];
|
||||
pCurDq->pResidualPredFlag = pCtx->sMb.pResidualPredFlag[0];
|
||||
pCurDq->pMbCorrectlyDecodedFlag = pCtx->sMb.pMbCorrectlyDecodedFlag[0];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1725,6 +1750,7 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, int3
|
||||
if (pCtx->iTotalNumMbRec == 0) { //Picture start to decode
|
||||
for (int32_t i = 0; i < LAYER_NUM_EXCHANGEABLE; ++ i)
|
||||
memset (pCtx->sMb.pSliceIdc[i], 0xff, (pCtx->sMb.iMbWidth * pCtx->sMb.iMbHeight * sizeof (int32_t)));
|
||||
memset (pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag, 0, pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight);
|
||||
}
|
||||
GetI4LumaIChromaAddrTable (pCtx->iDecBlockOffsetArray, pCtx->pDec->iLinesize[0], pCtx->pDec->iLinesize[1]);
|
||||
|
||||
@ -1796,15 +1822,16 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, int3
|
||||
"referencing pictures lost due frame gaps exist, prev_frame_num: %d, curr_frame_num: %d\n", pCtx->iPrevFrameNum,
|
||||
pSh->iFrameNum);
|
||||
|
||||
#ifdef LONG_TERM_REF
|
||||
pCtx->bParamSetsLostFlag = true;
|
||||
#else
|
||||
pCtx->bReferenceLostAtT0Flag = true;
|
||||
#endif
|
||||
ResetParameterSetsState (pCtx);
|
||||
|
||||
pCtx->iErrorCode |= dsRefLost;
|
||||
return ERR_INFO_REFERENCE_PIC_LOST;
|
||||
if (pCtx->iErrorConMethod == ERROR_CON_DISABLE) {
|
||||
#ifdef LONG_TERM_REF
|
||||
pCtx->bParamSetsLostFlag = true;
|
||||
#else
|
||||
pCtx->bReferenceLostAtT0Flag = true;
|
||||
#endif
|
||||
ResetParameterSetsState (pCtx);
|
||||
return ERR_INFO_REFERENCE_PIC_LOST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1875,6 +1902,9 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, int3
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //store latest decoded picture for EC
|
||||
|
||||
if (uiNalRefIdc > 0) {
|
||||
iRet = WelsMarkAsRef (pCtx);
|
||||
if (iRet != ERR_NONE) {
|
||||
|
@ -66,33 +66,130 @@ void InitErrorCon (PWelsDecoderContext pCtx) {
|
||||
|
||||
//Do error concealment using frame copy method
|
||||
void DoErrorConFrameCopy (PWelsDecoderContext pCtx) {
|
||||
//TODO
|
||||
PPicture pDstPic = pCtx->pDec;
|
||||
PPicture pSrcPic = pCtx->pPreviousDecodedPictureInDpb;
|
||||
uint32_t uiHeightInPixelY = (pCtx->pSps->iMbHeight) << 4;
|
||||
int32_t iStrideY = pDstPic->iLinesize[0];
|
||||
int32_t iStrideUV = pDstPic->iLinesize[1];
|
||||
if (pSrcPic == NULL) { //no ref pic, assign specific data to picture
|
||||
memset (pDstPic->pData[0], 0, uiHeightInPixelY * iStrideY);
|
||||
memset (pDstPic->pData[1], 0, (uiHeightInPixelY >> 1) * iStrideUV);
|
||||
memset (pDstPic->pData[2], 0, (uiHeightInPixelY >> 1) * iStrideUV);
|
||||
} else { //has ref pic here
|
||||
memcpy (pDstPic->pData[0], pSrcPic->pData[0], uiHeightInPixelY * iStrideY);
|
||||
memcpy (pDstPic->pData[1], pSrcPic->pData[1], (uiHeightInPixelY >> 1) * iStrideUV);
|
||||
memcpy (pDstPic->pData[2], pSrcPic->pData[2], (uiHeightInPixelY >> 1) * iStrideUV);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Do error concealment using slice copy method
|
||||
void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
|
||||
//TODO
|
||||
int32_t iMbWidth = (int32_t) pCtx->pSps->iMbWidth;
|
||||
int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
|
||||
PPicture pDstPic = pCtx->pDec;
|
||||
PPicture pSrcPic = pCtx->pPreviousDecodedPictureInDpb;
|
||||
|
||||
//uint8_t *pDstData[3], *pSrcData[3];
|
||||
bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
|
||||
|
||||
//Do slice copy late
|
||||
int32_t iMbXyIndex;
|
||||
uint8_t* pSrcData, *pDstData;
|
||||
uint32_t iSrcStride; // = pSrcPic->iLinesize[0];
|
||||
uint32_t iDstStride = pDstPic->iLinesize[0];
|
||||
for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
|
||||
for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
|
||||
iMbXyIndex = iMbY * iMbWidth + iMbX;
|
||||
if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
|
||||
if (pSrcPic != NULL) {
|
||||
iSrcStride = pSrcPic->iLinesize[0];
|
||||
//Y component
|
||||
pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;;
|
||||
pSrcData = pSrcPic->pData[0] + iMbY * 16 * iSrcStride + iMbX * 16;
|
||||
pCtx->sCopyFunc.pCopyLumaFunc (pDstData, iDstStride, pSrcData, iSrcStride);
|
||||
//U component
|
||||
pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
|
||||
pSrcData = pSrcPic->pData[1] + iMbY * 8 * iSrcStride / 2 + iMbX * 8;
|
||||
pCtx->sCopyFunc.pCopyChromaFunc (pDstData, iDstStride / 2, pSrcData, iSrcStride / 2);
|
||||
//V component
|
||||
pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
|
||||
pSrcData = pSrcPic->pData[2] + iMbY * 8 * iSrcStride / 2 + iMbX * 8;
|
||||
pCtx->sCopyFunc.pCopyChromaFunc (pDstData, iDstStride / 2, pSrcData, iSrcStride / 2);
|
||||
} else { //pSrcPic == NULL
|
||||
//Y component
|
||||
pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
|
||||
for (int32_t i = 0; i < 16; ++i) {
|
||||
memset (pDstData, 0, 16);
|
||||
pDstData += iDstStride;
|
||||
}
|
||||
//U component
|
||||
pDstData = pDstPic->pData[1] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
|
||||
for (int32_t i = 0; i < 8; ++i) {
|
||||
memset (pDstData, 0, 8);
|
||||
pDstData += iDstStride / 2;
|
||||
}
|
||||
//V component
|
||||
pDstData = pDstPic->pData[2] + iMbY * 8 * iDstStride / 2 + iMbX * 8;
|
||||
for (int32_t i = 0; i < 8; ++i) {
|
||||
memset (pDstData, 0, 8);
|
||||
pDstData += iDstStride / 2;
|
||||
}
|
||||
} //
|
||||
} //!pMbCorrectlyDecodedFlag[iMbXyIndex]
|
||||
} //iMbX
|
||||
} //iMbY
|
||||
}
|
||||
|
||||
|
||||
//Mark erroneous frame as Ref Pic into DPB
|
||||
int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx) {
|
||||
//TODO
|
||||
int32_t iRet = WelsMarkAsRef (pCtx);
|
||||
if (iRet != ERR_NONE) {
|
||||
pCtx->pDec = NULL;
|
||||
return iRet;
|
||||
}
|
||||
ExpandReferencingPicture (pCtx->pDec, pCtx->sExpandPicFunc.pExpandLumaPicture,
|
||||
pCtx->sExpandPicFunc.pExpandChromaPicture);
|
||||
pCtx->pDec = NULL;
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
bool NeedErrorCon (PWelsDecoderContext pCtx) {
|
||||
bool bNeedEC = false;
|
||||
//TODO
|
||||
int32_t iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
|
||||
for (int32_t i = 0; i < iMbNum; ++i) {
|
||||
if (!pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag[i]) {
|
||||
bNeedEC = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bNeedEC;
|
||||
}
|
||||
|
||||
// ImplementErrorConceal
|
||||
// Do actual error concealment
|
||||
int32_t ImplementErrorCon (PWelsDecoderContext pCtx) {
|
||||
int32_t iRet = ERR_NONE;
|
||||
//TODO
|
||||
return iRet;
|
||||
void ImplementErrorCon (PWelsDecoderContext pCtx) {
|
||||
if (!NeedErrorCon (pCtx))
|
||||
return;
|
||||
|
||||
if (ERROR_CON_DISABLE == pCtx->iErrorConMethod) {
|
||||
pCtx->iErrorCode |= dsBitstreamError;
|
||||
return;
|
||||
} else if (ERROR_CON_FRAME_COPY == pCtx->iErrorConMethod) {
|
||||
DoErrorConFrameCopy (pCtx);
|
||||
} else if (ERROR_CON_SLICE_COPY == pCtx->iErrorConMethod) {
|
||||
DoErrorConSliceCopy (pCtx);
|
||||
} //TODO add other EC methods here in the future
|
||||
|
||||
//mark the erroneous frame as Ref pic in DPB
|
||||
MarkECFrameAsRef (pCtx);
|
||||
//need update frame_num due current frame is well decoded
|
||||
pCtx->iPrevFrameNum = pCtx->pSliceHeader->iFrameNum;
|
||||
if (pCtx->bLastHasMmco5)
|
||||
pCtx->iPrevFrameNum = 0;
|
||||
|
||||
}
|
||||
|
||||
} // namespace WelsDec
|
||||
|
Loading…
x
Reference in New Issue
Block a user