ref: 305a2421be82a643b6a8dfa73c179b9d6a5e73f5
parent: f1fb0d6b6980e9705147fcdba2acd80ed6eba5b8
parent: 9425c2ab10acf5c526c96af4c3209c6355c5f756
author: huili2 <[email protected]>
date: Tue Nov 25 07:59:48 EST 2014
Merge pull request #1549 from dongzha/ECMvCopy add EC MV copy
--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -159,7 +159,9 @@
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
--- a/codec/console/dec/src/d3d9_utils.cpp
+++ b/codec/console/dec/src/d3d9_utils.cpp
@@ -336,6 +336,7 @@
|| 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);
}
--- a/codec/console/dec/src/h264dec.cpp
+++ b/codec/console/dec/src/h264dec.cpp
@@ -200,7 +200,7 @@
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
--- a/codec/decoder/core/inc/decode_slice.h
+++ b/codec/decoder/core/inc/decode_slice.h
@@ -53,7 +53,6 @@
int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur);
-
int32_t WelsTargetMbConstruction (PWelsDecoderContext pCtx);
int32_t WelsMbIntraPredictionConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer, bool bOutput);
--- a/codec/decoder/core/inc/decoder_context.h
+++ b/codec/decoder/core/inc/decoder_context.h
@@ -400,6 +400,8 @@
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) {
--- a/codec/decoder/core/inc/error_concealment.h
+++ b/codec/decoder/core/inc/error_concealment.h
@@ -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 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
--- a/codec/decoder/core/inc/picture.h
+++ b/codec/decoder/core/inc/picture.h
@@ -50,6 +50,9 @@
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
--- a/codec/decoder/core/inc/rec_mb.h
+++ b/codec/decoder/core/inc/rec_mb.h
@@ -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);
--- a/codec/decoder/core/inc/slice.h
+++ b/codec/decoder/core/inc/slice.h
@@ -120,6 +120,7 @@
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
--- a/codec/decoder/core/src/decoder_core.cpp
+++ b/codec/decoder/core/src/decoder_core.cpp
@@ -113,7 +113,9 @@
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 @@
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 @@
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 @@
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 @@
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))
--- a/codec/decoder/core/src/error_concealment.cpp
+++ b/codec/decoder/core/src/error_concealment.cpp
@@ -42,6 +42,8 @@
//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,7 +161,264 @@
+ ((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) {
int32_t iRet = WelsMarkAsRef (pCtx);
@@ -200,6 +459,10 @@
|| (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.
--- a/codec/decoder/core/src/manage_dec_ref.cpp
+++ b/codec/decoder/core/src/manage_dec_ref.cpp
@@ -40,6 +40,7 @@
*****************************************************************************/
#include "manage_dec_ref.h"
+#include "error_concealment.h"
#include "error_code.h"
namespace WelsDec {
@@ -67,7 +68,7 @@
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 @@
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))
- && (NULL != pCtx->pPreviousDecodedPictureInDpb);
+ || (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);
--- a/codec/decoder/core/src/pic_queue.cpp
+++ b/codec/decoder/core/src/pic_queue.cpp
@@ -81,6 +81,7 @@
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)));
@@ -93,8 +94,6 @@
pPic->pData[0] = pPic->pBuffer[0] + (1 + pPic->iLinesize[0]) * PADDING_LENGTH;
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;
--- a/codec/decoder/core/src/rec_mb.cpp
+++ b/codec/decoder/core/src/rec_mb.cpp
@@ -164,24 +164,7 @@
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 @@
#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];
--- a/codec/decoder/plus/src/welsDecoderExt.cpp
+++ b/codec/decoder/plus/src/welsDecoderExt.cpp
@@ -277,7 +277,7 @@
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,