add EC MV copy
This commit is contained in:
@@ -159,7 +159,9 @@ typedef enum {
|
||||
ERROR_CON_SLICE_COPY,
|
||||
ERROR_CON_FRAME_COPY_CROSS_IDR,
|
||||
ERROR_CON_SLICE_COPY_CROSS_IDR,
|
||||
ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE
|
||||
ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE,
|
||||
ERROR_CON_SLICE_MV_COPY_CROSS_IDR,
|
||||
ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE
|
||||
} ERROR_CON_IDC;
|
||||
/**
|
||||
* @brief Feedback that whether or not have VCL NAL in current AU
|
||||
|
||||
@@ -336,6 +336,7 @@ HRESULT CD3D9ExUtils::Render (void* pDst[3], SBufferInfo* pInfo) {
|
||||
|| m_nHeight != pInfo->UsrData.sSystemBuffer.iHeight) {
|
||||
m_nWidth = pInfo->UsrData.sSystemBuffer.iWidth;
|
||||
m_nHeight = pInfo->UsrData.sSystemBuffer.iHeight;
|
||||
MoveWindow(m_hWnd,0,0,pInfo->UsrData.sSystemBuffer.iWidth,pInfo->UsrData.sSystemBuffer.iHeight,true);
|
||||
SAFE_RELEASE (m_lpD3D9RawSurfaceShare);
|
||||
SAFE_RELEASE (m_lpD3D9Device);
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ 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 = (int32_t) ERROR_CON_SLICE_COPY;
|
||||
int32_t iErrorConMethod = (int32_t) ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
|
||||
pDecoder->SetOption (DECODER_OPTION_ERROR_CON_IDC, &iErrorConMethod);
|
||||
//~end for
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ int32_t WelsTargetSliceConstruction (PWelsDecoderContext pCtx); //construction b
|
||||
|
||||
int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur);
|
||||
|
||||
|
||||
int32_t WelsTargetMbConstruction (PWelsDecoderContext pCtx);
|
||||
|
||||
int32_t WelsMbIntraPredictionConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer, bool bOutput);
|
||||
|
||||
@@ -400,6 +400,8 @@ SWelsCabacCtx pCabacCtx[WELS_CONTEXT_COUNT];
|
||||
PWelsCabacDecEngine pCabacDecEngine;
|
||||
double dDecTime;
|
||||
SDecoderStatistics sDecoderStatistics;// For real time debugging
|
||||
int32_t iECMVs[16][2];
|
||||
PPicture pECRefPic[16];
|
||||
} SWelsDecoderContext, *PWelsDecoderContext;
|
||||
|
||||
static inline void ResetActiveSPSForEachLayer (PWelsDecoderContext pCtx) {
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#ifndef WELS_ERROR_CONCEALMENT_H__
|
||||
#define WELS_ERROR_CONCEALMENT_H__
|
||||
#include "typedefs.h"
|
||||
#include "rec_mb.h"
|
||||
#include "decoder_context.h"
|
||||
|
||||
namespace WelsDec {
|
||||
@@ -48,6 +49,10 @@ void InitErrorCon (PWelsDecoderContext pCtx);
|
||||
void DoErrorConFrameCopy (PWelsDecoderContext pCtx);
|
||||
//Do error concealment using slice copy method
|
||||
void DoErrorConSliceCopy (PWelsDecoderContext pCtx);
|
||||
//Do error concealment using slice MV copy method
|
||||
void DoMbECMvCopy (PWelsDecoderContext pCtx, PPicture pDec, PPicture pRef, int32_t iMbXy, int32_t iMbX, int32_t iMbY, sMCRefMember* pMCRefMem, int32_t iCurrPoc);
|
||||
void GetAvilInfoFromCorrectMb (PWelsDecoderContext pCtx);
|
||||
void DoErrorConSliceMVCopy (PWelsDecoderContext pCtx);
|
||||
//Mark erroneous frame as Ref Pic into DPB
|
||||
int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx);
|
||||
//Judge if EC is needed to current frame
|
||||
|
||||
@@ -50,6 +50,9 @@ int32_t iLinesize[4];// linesize of picture planes respectively used currently
|
||||
int32_t iPlanes; // How many planes are introduced due to color space format?
|
||||
// picture information
|
||||
|
||||
/*******************************from EC mv copy****************************/
|
||||
bool bIdrFlag;
|
||||
|
||||
/*******************************from other standard syntax****************************/
|
||||
/*from sps*/
|
||||
int32_t iWidthInPixel; // picture width in pixel
|
||||
|
||||
@@ -48,6 +48,27 @@
|
||||
#include "decoder_context.h"
|
||||
|
||||
namespace WelsDec {
|
||||
typedef struct TagMCRefMember {
|
||||
uint8_t* pDstY;
|
||||
uint8_t* pDstU;
|
||||
uint8_t* pDstV;
|
||||
|
||||
uint8_t* pSrcY;
|
||||
uint8_t* pSrcU;
|
||||
uint8_t* pSrcV;
|
||||
|
||||
int32_t iSrcLineLuma;
|
||||
int32_t iSrcLineChroma;
|
||||
|
||||
int32_t iDstLineLuma;
|
||||
int32_t iDstLineChroma;
|
||||
|
||||
int32_t iPicWidth;
|
||||
int32_t iPicHeight;
|
||||
} sMCRefMember;
|
||||
|
||||
void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
|
||||
int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]);
|
||||
|
||||
void WelsFillRecNeededMbInfo (PWelsDecoderContext pCtx, bool bOutput, PDqLayer pCurLayer);
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ PSps pSps;
|
||||
PPps pPps;
|
||||
int32_t iSpsId;
|
||||
int32_t iPpsId;
|
||||
bool bIdrFlag;
|
||||
|
||||
/*********************got from other layer for efficency if possible*********************/
|
||||
SRefPicListReorderSyn pRefPicListReordering; // Reference picture list reordering syntaxs
|
||||
|
||||
@@ -113,7 +113,9 @@ static inline int32_t DecodeFrameConstruction (PWelsDecoderContext pCtx, uint8_t
|
||||
if (pCtx->eErrorConMethod == ERROR_CON_DISABLE) //no buffer output if EC is disabled and frame incomplete
|
||||
pDstInfo->iBufferStatus = (int32_t) (bFrameCompleteFlag
|
||||
&& pPic->bIsComplete); // When EC disable, ECed picture not output
|
||||
else if (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE && pCtx->iErrorCode && bOutResChange)
|
||||
else if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE
|
||||
|| pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
|
||||
&& pCtx->iErrorCode && bOutResChange)
|
||||
pCtx->bFreezeOutput = true;
|
||||
|
||||
if ((pDstInfo->iBufferStatus == 1) && (pCurDq->sLayerInfo.sNalHeaderExt.bIdrFlag)) {
|
||||
@@ -620,6 +622,7 @@ int32_t ParseSliceHeaderSyntaxs (PWelsDecoderContext pCtx, PBitStringAux pBs, co
|
||||
pSliceHeadExt->pSubsetSps = pSubsetSps;
|
||||
|
||||
bIdrFlag = (!kbExtensionFlag && eNalType == NAL_UNIT_CODED_SLICE_IDR) || (kbExtensionFlag && pNalHeaderExt->bIdrFlag);
|
||||
pSliceHead->bIdrFlag = bIdrFlag;
|
||||
|
||||
if (pSps->uiLog2MaxFrameNum == 0) {
|
||||
WelsLog (pLogCtx, WELS_LOG_WARNING, "non existing SPS referenced");
|
||||
@@ -1961,6 +1964,8 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
|
||||
memcpy (&pLayerInfo.sNalHeaderExt, &pNalCur->sNalHeaderExt, sizeof (SNalUnitHeaderExt)); //confirmed_safe_unsafe_usage
|
||||
|
||||
pCtx->pDec->iFrameNum = pSh->iFrameNum;
|
||||
pCtx->pDec->iFramePoc = pSh->iPicOrderCntLsb; // still can not obtain correct, because current do not support POCtype 2
|
||||
pCtx->pDec->bIdrFlag = pNalCur->sNalHeaderExt.bIdrFlag;
|
||||
|
||||
memcpy (&pLayerInfo.sSliceInLayer.sSliceHeaderExt, pShExt, sizeof (SSliceHeaderExt)); //confirmed_safe_unsafe_usage
|
||||
pLayerInfo.sSliceInLayer.bSliceHeaderExtFlag = pNalCur->sNalData.sVclNal.bSliceHeaderExtFlag;
|
||||
@@ -2126,6 +2131,9 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, SBuf
|
||||
pCtx->pDec->iLinesize,
|
||||
pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture);
|
||||
pCtx->pDec = NULL;
|
||||
} else if (pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR || pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE) {
|
||||
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //store latest decoded picture for MV Copy EC
|
||||
pCtx->pDec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2156,6 +2164,8 @@ bool CheckAndFinishLastPic (PWelsDecoderContext pCtx, uint8_t** ppDst, SBufferIn
|
||||
if (pCtx->sLastNalHdrExt.sNalUnitHeader.uiNalRefIdc > 0) {
|
||||
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //save ECed pic for future use
|
||||
MarkECFrameAsRef (pCtx);
|
||||
} else if (pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR || pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE) {
|
||||
pCtx->pPreviousDecodedPictureInDpb = pCtx->pDec; //save ECed pic for future MV Copy use
|
||||
}
|
||||
} else {
|
||||
if (DecodeFrameConstruction (pCtx, ppDst, pDstInfo))
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace WelsDec {
|
||||
//Init
|
||||
void InitErrorCon (PWelsDecoderContext pCtx) {
|
||||
if ((pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY) || (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR)
|
||||
|| (pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR)
|
||||
|| (pCtx->eErrorConMethod == ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE)
|
||||
|| (pCtx->eErrorConMethod == ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE)) {
|
||||
pCtx->sCopyFunc.pCopyLumaFunc = WelsCopy16x16_c;
|
||||
pCtx->sCopyFunc.pCopyChromaFunc = WelsCopy8x8_c;
|
||||
@@ -159,6 +161,263 @@ void DoErrorConSliceCopy (PWelsDecoderContext pCtx) {
|
||||
+ ((iMbEcedNum * 100) / iMbNum) ;
|
||||
}
|
||||
|
||||
//Do error concealment using slice MV copy method
|
||||
void DoMbECMvCopy (PWelsDecoderContext pCtx, PPicture pDec, PPicture pRef, int32_t iMbXy, int32_t iMbX, int32_t iMbY,
|
||||
sMCRefMember* pMCRefMem) {
|
||||
int16_t iMVs[2];
|
||||
int32_t iMbXInPix = iMbX << 4;
|
||||
int32_t iMbYInPix = iMbY << 4;
|
||||
int32_t iScale0;
|
||||
int32_t iScale1;
|
||||
uint8_t* pDst[3];
|
||||
int32_t iCurrPoc = pDec->iFramePoc;
|
||||
pDst[0] = pDec->pData[0] + iMbXInPix + iMbYInPix * pMCRefMem->iDstLineLuma;
|
||||
pDst[1] = pDec->pData[1] + (iMbXInPix >> 1) + (iMbYInPix >> 1) * pMCRefMem->iDstLineChroma;
|
||||
pDst[2] = pDec->pData[2] + (iMbXInPix >> 1) + (iMbYInPix >> 1) * pMCRefMem->iDstLineChroma;
|
||||
if (pDec->bIdrFlag == true || pCtx->pECRefPic[0] == NULL) {
|
||||
uint8_t* pSrcData;
|
||||
//Y component
|
||||
pSrcData = pMCRefMem->pSrcY + iMbY * 16 * pMCRefMem->iSrcLineLuma + iMbX * 16;
|
||||
pCtx->sCopyFunc.pCopyLumaFunc (pDst[0], pMCRefMem->iDstLineLuma, pSrcData, pMCRefMem->iSrcLineLuma);
|
||||
//U component
|
||||
pSrcData = pMCRefMem->pSrcU + iMbY * 8 * pMCRefMem->iSrcLineChroma + iMbX * 8;
|
||||
pCtx->sCopyFunc.pCopyChromaFunc (pDst[1], pMCRefMem->iDstLineChroma, pSrcData, pMCRefMem->iSrcLineChroma);
|
||||
//V component
|
||||
pSrcData = pMCRefMem->pSrcV + iMbY * 8 * pMCRefMem->iSrcLineChroma + iMbX * 8;
|
||||
pCtx->sCopyFunc.pCopyChromaFunc (pDst[2], pMCRefMem->iDstLineChroma, pSrcData, pMCRefMem->iSrcLineChroma);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pCtx->pECRefPic[0]) {
|
||||
if (pCtx->pECRefPic[0] == pRef) {
|
||||
iMVs[0] = pCtx->iECMVs[0][0];
|
||||
iMVs[1] = pCtx->iECMVs[0][1];
|
||||
} else {
|
||||
iScale0 = pCtx->pECRefPic[0]->iFramePoc - iCurrPoc;
|
||||
iScale1 = pRef->iFramePoc - iCurrPoc;
|
||||
iMVs[0] = pCtx->iECMVs[0][0] * iScale1 / iScale0;
|
||||
iMVs[1] = pCtx->iECMVs[0][1] * iScale1 / iScale0;
|
||||
}
|
||||
pMCRefMem->pDstY = pDst[0];
|
||||
pMCRefMem->pDstU = pDst[1];
|
||||
pMCRefMem->pDstV = pDst[2];
|
||||
int32_t iFullMVx = (iMbXInPix << 2) + iMVs[0]; //quarter pixel
|
||||
int32_t iFullMVy = (iMbYInPix << 2) + iMVs[1];
|
||||
// only use to be output pixels to EC;
|
||||
int32_t iPicWidthLeftLimit = 0;
|
||||
int32_t iPicHeightTopLimit = 0;
|
||||
int32_t iPicWidthRightLimit = pMCRefMem->iPicWidth;
|
||||
int32_t iPicHeightBottomLimit = pMCRefMem->iPicHeight;
|
||||
if (pCtx->pSps->bFrameCroppingFlag) {
|
||||
iPicWidthLeftLimit = 0 + pCtx->sFrameCrop.iLeftOffset * 2;
|
||||
iPicWidthRightLimit = (pMCRefMem->iPicWidth - pCtx->sFrameCrop.iRightOffset * 2);
|
||||
iPicHeightTopLimit = 0 + pCtx->sFrameCrop.iTopOffset * 2;
|
||||
iPicHeightBottomLimit = (pMCRefMem->iPicHeight - pCtx->sFrameCrop.iTopOffset * 2);
|
||||
}
|
||||
// further make sure no need to expand picture
|
||||
int32_t iMinLeftOffset = (iPicWidthLeftLimit + 2) << 2;
|
||||
int32_t iMaxRightOffset = ((iPicWidthRightLimit - 19) << 2);
|
||||
int32_t iMinTopOffset = (iPicHeightTopLimit + 2) << 2;
|
||||
int32_t iMaxBottomOffset = ((iPicHeightBottomLimit - 19) << 2);
|
||||
if (iFullMVx < iMinLeftOffset) {
|
||||
iFullMVx = (iFullMVx >> 2) << 2;
|
||||
iFullMVx = WELS_MAX (iPicWidthLeftLimit, iFullMVx);
|
||||
} else if (iFullMVx > iMaxRightOffset) {
|
||||
iFullMVx = (iFullMVx >> 2) << 2;
|
||||
iFullMVx = WELS_MIN (((iPicWidthRightLimit - 17) << 2), iFullMVx);
|
||||
}
|
||||
if (iFullMVy < iMinTopOffset) {
|
||||
iFullMVy = (iFullMVy >> 2) << 2;
|
||||
iFullMVy = WELS_MAX (iPicHeightTopLimit, iFullMVy);
|
||||
} else if (iFullMVy > iMaxBottomOffset) {
|
||||
iFullMVy = (iFullMVy >> 2) << 2;
|
||||
iFullMVy = WELS_MIN (((iPicHeightBottomLimit - 17) << 2), iFullMVy);
|
||||
}
|
||||
iMVs[0] = iFullMVx - (iMbXInPix << 2);
|
||||
iMVs[1] = iFullMVy - (iMbYInPix << 2);
|
||||
BaseMC (pMCRefMem, iMbXInPix, iMbYInPix, &pCtx->sMcFunc, 16, 16, iMVs);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
void GetAvilInfoFromCorrectMb (PWelsDecoderContext pCtx) {
|
||||
int32_t iMbWidth = (int32_t) pCtx->pSps->iMbWidth;
|
||||
int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
|
||||
bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
|
||||
PDqLayer pCurDqLayer = pCtx->pCurDqLayer;
|
||||
int32_t iInterMbCorrectNum[16];
|
||||
int32_t iMbXyIndex;
|
||||
|
||||
int8_t iRefIdx;
|
||||
memset (pCtx->iECMVs, 0, sizeof (int32_t) * 32);
|
||||
memset (pCtx->pECRefPic, 0, sizeof (PPicture) * 16);
|
||||
memset (iInterMbCorrectNum, 0, sizeof (int32_t) * 16);
|
||||
|
||||
for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
|
||||
for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
|
||||
iMbXyIndex = iMbY * iMbWidth + iMbX;
|
||||
if (pMbCorrectlyDecodedFlag[iMbXyIndex] && IS_INTER (pCurDqLayer->pMbType[iMbXyIndex])) {
|
||||
int32_t iMBType = pCurDqLayer->pMbType[iMbXyIndex];
|
||||
switch (iMBType) {
|
||||
case MB_TYPE_SKIP:
|
||||
case MB_TYPE_16x16:
|
||||
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][0];
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][0][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][0][1];
|
||||
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
|
||||
iInterMbCorrectNum[iRefIdx]++;
|
||||
break;
|
||||
case MB_TYPE_16x8:
|
||||
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][0];
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][0][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][0][1];
|
||||
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
|
||||
iInterMbCorrectNum[iRefIdx]++;
|
||||
|
||||
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][8];
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][8][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][8][1];
|
||||
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
|
||||
iInterMbCorrectNum[iRefIdx]++;
|
||||
break;
|
||||
case MB_TYPE_8x16:
|
||||
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][0];
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][0][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][0][1];
|
||||
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
|
||||
iInterMbCorrectNum[iRefIdx]++;
|
||||
|
||||
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][2];
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][2][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][2][1];
|
||||
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
|
||||
iInterMbCorrectNum[iRefIdx]++;
|
||||
break;
|
||||
case MB_TYPE_8x8:
|
||||
case MB_TYPE_8x8_REF0: {
|
||||
uint32_t iSubMBType;
|
||||
int32_t i, j, iIIdx, iJIdx;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
iSubMBType = pCurDqLayer->pSubMbType[iMbXyIndex][i];
|
||||
iIIdx = ((i >> 1) << 3) + ((i & 1) << 1);
|
||||
iRefIdx = pCurDqLayer->pRefIndex[0][iMbXyIndex][iIIdx];
|
||||
pCtx->pECRefPic[iRefIdx] = pCtx->sRefPic.pRefList[LIST_0][iRefIdx];
|
||||
switch (iSubMBType) {
|
||||
case SUB_MB_TYPE_8x8:
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][1];
|
||||
iInterMbCorrectNum[iRefIdx]++;
|
||||
|
||||
break;
|
||||
case SUB_MB_TYPE_8x4:
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][1];
|
||||
|
||||
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + 4][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + 4][1];
|
||||
iInterMbCorrectNum[iRefIdx] += 2;
|
||||
|
||||
break;
|
||||
case SUB_MB_TYPE_4x8:
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx][1];
|
||||
|
||||
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + 1][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + 1][1];
|
||||
iInterMbCorrectNum[iRefIdx] += 2;
|
||||
break;
|
||||
case SUB_MB_TYPE_4x4: {
|
||||
for (j = 0; j < 4; j++) {
|
||||
iJIdx = ((j >> 1) << 2) + (j & 1);
|
||||
pCtx->iECMVs[iRefIdx][0] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + iJIdx][0];
|
||||
pCtx->iECMVs[iRefIdx][1] += pCurDqLayer->pMv[0][iMbXyIndex][iIIdx + iJIdx][1];
|
||||
}
|
||||
iInterMbCorrectNum[iRefIdx] += 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} //pMbCorrectlyDecodedFlag[iMbXyIndex]
|
||||
} //iMbX
|
||||
} //iMbY
|
||||
for (int32_t i = 0; i < 16; i++) {
|
||||
if (iInterMbCorrectNum[i]) {
|
||||
pCtx->iECMVs[i][0] = pCtx->iECMVs[i][0] / iInterMbCorrectNum[i];
|
||||
pCtx->iECMVs[i][1] = pCtx->iECMVs[i][1] / iInterMbCorrectNum[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoErrorConSliceMVCopy (PWelsDecoderContext pCtx) {
|
||||
int32_t iMbWidth = (int32_t) pCtx->pSps->iMbWidth;
|
||||
int32_t iMbHeight = (int32_t) pCtx->pSps->iMbHeight;
|
||||
PPicture pDstPic = pCtx->pDec;
|
||||
PPicture pSrcPic = pCtx->pPreviousDecodedPictureInDpb;
|
||||
|
||||
int32_t iMbNum = pCtx->pSps->iMbWidth * pCtx->pSps->iMbHeight;
|
||||
bool* pMbCorrectlyDecodedFlag = pCtx->pCurDqLayer->pMbCorrectlyDecodedFlag;
|
||||
int32_t iMbEcedNum = 0;
|
||||
int32_t iMbXyIndex;
|
||||
uint8_t* pDstData;
|
||||
uint32_t iDstStride = pDstPic->iLinesize[0];
|
||||
sMCRefMember sMCRefMem;
|
||||
if (pSrcPic != NULL) {
|
||||
sMCRefMem.iSrcLineLuma = pSrcPic->iLinesize[0];
|
||||
sMCRefMem.iSrcLineChroma = pSrcPic->iLinesize[1];
|
||||
sMCRefMem.pSrcY = pSrcPic->pData[0];
|
||||
sMCRefMem.pSrcU = pSrcPic->pData[1];
|
||||
sMCRefMem.pSrcV = pSrcPic->pData[2];
|
||||
sMCRefMem.iDstLineLuma = pDstPic->iLinesize[0];
|
||||
sMCRefMem.iDstLineChroma = pDstPic->iLinesize[1];
|
||||
sMCRefMem.iPicWidth = pDstPic->iWidthInPixel;
|
||||
sMCRefMem.iPicHeight = pDstPic->iHeightInPixel;
|
||||
}
|
||||
|
||||
for (int32_t iMbY = 0; iMbY < iMbHeight; ++iMbY) {
|
||||
for (int32_t iMbX = 0; iMbX < iMbWidth; ++iMbX) {
|
||||
iMbXyIndex = iMbY * iMbWidth + iMbX;
|
||||
if (!pMbCorrectlyDecodedFlag[iMbXyIndex]) {
|
||||
iMbEcedNum++;
|
||||
if (pSrcPic != NULL) {
|
||||
DoMbECMvCopy (pCtx, pDstPic, pSrcPic, iMbXyIndex, iMbX, iMbY, &sMCRefMem);
|
||||
} else { //pSrcPic == NULL
|
||||
//Y component
|
||||
pDstData = pDstPic->pData[0] + iMbY * 16 * iDstStride + iMbX * 16;
|
||||
for (int32_t i = 0; i < 16; ++i) {
|
||||
memset (pDstData, 128, 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, 128, 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, 128, 8);
|
||||
pDstData += iDstStride / 2;
|
||||
}
|
||||
} //
|
||||
|
||||
} //!pMbCorrectlyDecodedFlag[iMbXyIndex]
|
||||
} //iMbX
|
||||
} //iMbY
|
||||
|
||||
pCtx->sDecoderStatistics.uiAvgEcRatio = (pCtx->sDecoderStatistics.uiAvgEcRatio * pCtx->sDecoderStatistics.uiEcFrameNum)
|
||||
+ ((iMbEcedNum * 100) / iMbNum) ;
|
||||
}
|
||||
|
||||
//Mark erroneous frame as Ref Pic into DPB
|
||||
int32_t MarkECFrameAsRef (PWelsDecoderContext pCtx) {
|
||||
@@ -200,6 +459,10 @@ void ImplementErrorCon (PWelsDecoderContext pCtx) {
|
||||
|| (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|
||||
|| (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod)) {
|
||||
DoErrorConSliceCopy (pCtx);
|
||||
} else if ((ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|
||||
|| (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod)) {
|
||||
GetAvilInfoFromCorrectMb (pCtx);
|
||||
DoErrorConSliceMVCopy (pCtx);
|
||||
} //TODO add other EC methods here in the future
|
||||
pCtx->iErrorCode |= dsDataErrorConcealed;
|
||||
pCtx->pDec->bIsComplete = false; // Set complete flag to false after do EC.
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "manage_dec_ref.h"
|
||||
#include "error_concealment.h"
|
||||
#include "error_code.h"
|
||||
|
||||
namespace WelsDec {
|
||||
@@ -67,7 +68,7 @@ static void SetUnRef (PPicture pRef) {
|
||||
pRef->bUsedAsRef = false;
|
||||
pRef->bIsLongRef = false;
|
||||
pRef->iFrameNum = -1;
|
||||
pRef->iFramePoc = 0;
|
||||
//pRef->iFramePoc = 0;
|
||||
pRef->iLongTermFrameIdx = -1;
|
||||
pRef->uiQualityId = -1;
|
||||
pRef->uiTemporalId = -1;
|
||||
@@ -121,10 +122,13 @@ int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
|
||||
pCtx->iErrorCode |= dsDataErrorConcealed;
|
||||
bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|
||||
|| (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|
||||
|| (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod))
|
||||
|| (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod)
|
||||
|| (ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->eErrorConMethod)
|
||||
|| (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == 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);
|
||||
|
||||
@@ -81,6 +81,7 @@ PPicture AllocPicture (PWelsDecoderContext pCtx, const int32_t kiPicWidth, const
|
||||
|
||||
iLumaSize = iPicWidth * iPicHeight;
|
||||
iChromaSize = iPicChromaWidth * iPicChromaHeight;
|
||||
|
||||
pPic->pBuffer[0] = static_cast<uint8_t*> (WelsMalloc (iLumaSize /* luma */
|
||||
+ (iChromaSize << 1) /* Cb,Cr */, "_pic->buffer[0]"));
|
||||
memset (pPic->pBuffer[0], 128, (iLumaSize + (iChromaSize << 1)));
|
||||
@@ -94,8 +95,6 @@ PPicture AllocPicture (PWelsDecoderContext pCtx, const int32_t kiPicWidth, const
|
||||
pPic->pData[1] = pPic->pBuffer[1] + /*WELS_ALIGN*/ (((1 + pPic->iLinesize[1]) * PADDING_LENGTH) >> 1);
|
||||
pPic->pData[2] = pPic->pBuffer[2] + /*WELS_ALIGN*/ (((1 + pPic->iLinesize[2]) * PADDING_LENGTH) >> 1);
|
||||
|
||||
|
||||
|
||||
pPic->iPlanes = 3; // yv12 in default
|
||||
pPic->iWidthInPixel = kiPicWidth;
|
||||
pPic->iHeightInPixel = kiPicHeight;
|
||||
|
||||
@@ -164,24 +164,7 @@ int32_t RecI16x16Mb (int32_t iMBXY, PWelsDecoderContext pCtx, int16_t* pScoeffLe
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
typedef struct TagMCRefMember {
|
||||
uint8_t* pDstY;
|
||||
uint8_t* pDstU;
|
||||
uint8_t* pDstV;
|
||||
|
||||
uint8_t* pSrcY;
|
||||
uint8_t* pSrcU;
|
||||
uint8_t* pSrcV;
|
||||
|
||||
int32_t iSrcLineLuma;
|
||||
int32_t iSrcLineChroma;
|
||||
|
||||
int32_t iDstLineLuma;
|
||||
int32_t iDstLineChroma;
|
||||
|
||||
int32_t iPicWidth;
|
||||
int32_t iPicHeight;
|
||||
} sMCRefMember;
|
||||
//according to current 8*8 block ref_index to gain reference picture
|
||||
static inline void GetRefPic (sMCRefMember* pMCRefMem, PWelsDecoderContext pCtx, int8_t* pRefIdxList,
|
||||
int32_t iIndex) {
|
||||
@@ -202,7 +185,7 @@ static inline void GetRefPic (sMCRefMember* pMCRefMem, PWelsDecoderContext pCtx,
|
||||
#ifndef MC_FLOW_SIMPLE_JUDGE
|
||||
#define MC_FLOW_SIMPLE_JUDGE 1
|
||||
#endif //MC_FLOW_SIMPLE_JUDGE
|
||||
static inline void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
|
||||
void BaseMC (sMCRefMember* pMCRefMem, int32_t iXOffset, int32_t iYOffset, SMcFunc* pMCFunc,
|
||||
int32_t iBlkWidth, int32_t iBlkHeight, int16_t iMVs[2]) {
|
||||
int32_t iFullMVx = (iXOffset << 2) + iMVs[0]; //quarter pixel
|
||||
int32_t iFullMVy = (iYOffset << 2) + iMVs[1];
|
||||
|
||||
@@ -277,7 +277,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_CROSS_IDR_FREEZE_RES_CHANGE);
|
||||
iVal = WELS_CLIP3 (iVal, (int32_t) ERROR_CON_DISABLE, (int32_t) ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE);
|
||||
m_pDecContext->eErrorConMethod = (ERROR_CON_IDC) iVal;
|
||||
InitErrorCon (m_pDecContext);
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
||||
|
||||
Reference in New Issue
Block a user