From 4bd6a3a6e8e779370c6473622446bd6110532335 Mon Sep 17 00:00:00 2001 From: sijchen Date: Mon, 12 May 2014 14:21:40 +0800 Subject: [PATCH] [Encoder MD] Add Inter Psub16 MD for screen content coding --- codec/encoder/core/inc/md.h | 9 +++ codec/encoder/core/inc/svc_base_layer_md.h | 2 + codec/encoder/core/src/encoder_ext.cpp | 3 + codec/encoder/core/src/svc_base_layer_md.cpp | 79 ++++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/codec/encoder/core/inc/md.h b/codec/encoder/core/inc/md.h index e585b020..7654ce58 100644 --- a/codec/encoder/core/inc/md.h +++ b/codec/encoder/core/inc/md.h @@ -66,6 +66,15 @@ namespace WelsSVCEnc { #define NO_BEST_FRAC_PIX 1 // REFINE_ME_NO_BEST_HALF_PIXEL + ME_NO_BEST_QUAR_PIXEL +//for vaa constants +#define MBVAASIGN_FLAT 15 +#define MBVAASIGN_HOR1 3 +#define MBVAASIGN_HOR2 12 +#define MBVAASIGN_VER1 5 +#define MBVAASIGN_VER2 10 +#define MBVAASIGN_CMPX1 6 +#define MBVAASIGN_CMPX2 9 + extern const int32_t g_kiQpCostTable[52]; extern const int8_t g_kiMapModeI16x16[7]; //extern const int8_t g_kiMapModeI4x4[14]; diff --git a/codec/encoder/core/inc/svc_base_layer_md.h b/codec/encoder/core/inc/svc_base_layer_md.h index 7a7bb520..3e725252 100644 --- a/codec/encoder/core/inc/svc_base_layer_md.h +++ b/codec/encoder/core/inc/svc_base_layer_md.h @@ -66,6 +66,8 @@ int32_t WelsMdP8x8 (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SWelsMD* pWe /*static*/ void WelsMdInterInit (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb, const int32_t kiSliceFirstMbXY); /*static*/ void WelsMdInterFinePartition (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb, int32_t bestCost); /*static*/ void WelsMdInterFinePartitionVaa (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb, int32_t bestCost); +/*static*/ void WelsMdInterFinePartitionVaaOnScreen (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb, + int32_t bestCost); void WelsMdInterMbRefinement (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB* pCurMb, SMbCache* pMbCache); bool WelsMdFirstIntraMode (void* pEnc, void* pMd, SMB* pCurMb, SMbCache* pMbCache); //bool svc_md_first_intra_mode_constrained(void* pEnc, void* pMd, SMB* pCurMb, SMbCache *pMbCache); diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index d3f41f5f..f24202a3 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -2457,6 +2457,9 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) { pFeatureSearchPreparation->iHighFreMbCount = 0; if (P_SLICE == pCtx->eSliceType) { + //MD related func pointers + pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaaOnScreen; + //calculate bFMESwitchFlag SVAAFrameInfoExt* pVaaExt = static_cast (pCtx->pVaa); const int32_t kiMbSize = pCurLayer->iMbHeight * pCurLayer->iMbWidth; diff --git a/codec/encoder/core/src/svc_base_layer_md.cpp b/codec/encoder/core/src/svc_base_layer_md.cpp index b4537157..f3d2f94b 100644 --- a/codec/encoder/core/src/svc_base_layer_md.cpp +++ b/codec/encoder/core/src/svc_base_layer_md.cpp @@ -1868,7 +1868,86 @@ void WelsMdIntraSecondaryModesEnc (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB* pCurMb->pSadCost[0] = 0; } +// +//func pointer of inter MD for sub16x16 INTER MD for screen content coding +// +static inline void MergeSub16Me (const SWelsME& sSrcMe0, const SWelsME& sSrcMe1, SWelsME* pTarMe) { + memcpy (pTarMe, &sSrcMe0, sizeof (sSrcMe0)); // confirmed_safe_unsafe_usage + pTarMe->uiSadCost = sSrcMe0.uiSadCost + sSrcMe1.uiSadCost;//not precise cost since MVD cost is not the same + pTarMe->uiSatdCost = sSrcMe0.uiSatdCost + sSrcMe1.uiSatdCost;//not precise cost since MVD cost is not the same +} +static inline bool IsSameMv (const SMVUnitXY& sMv0, const SMVUnitXY& sMv1) { + return ((sMv0.iMvX == sMv1.iMvX) && (sMv0.iMvY == sMv1.iMvY)); +} +static inline int32_t Mvd (const SMVUnitXY& sMv, const SMVUnitXY& sMvp) { + return (WELS_ABS (sMv.iMvX - sMvp.iMvX) + WELS_ABS (sMv.iMvY - sMvp.iMvY)); +} +bool TryModeMerge (SMbCache* pMbCache, SWelsMD* pWelsMd, SMB* pCurMb) { + SWelsME* pMe8x8 = & (pWelsMd->sMe.sMe8x8[0]); + const bool bSameMv16x8_0 = IsSameMv (pMe8x8[0].sMv, pMe8x8[1].sMv); + const bool bSameMv16x8_1 = IsSameMv (pMe8x8[2].sMv, pMe8x8[3].sMv); + + const bool bSameMv8x16_0 = IsSameMv (pMe8x8[0].sMv, pMe8x8[2].sMv); + const bool bSameMv8x16_1 = IsSameMv (pMe8x8[1].sMv, pMe8x8[3].sMv); + //need to consider iRefIdx when multi ref is available + const bool bSameRefIdx16x8_0 = true; //pMe8x8[0].iRefIdx == pMe8x8[1].iRefIdx; + const bool bSameRefIdx16x8_1 = true; //pMe8x8[2].iRefIdx == pMe8x8[3].iRefIdx; + const bool bSameRefIdx8x16_0 = true; //pMe8x8[0].iRefIdx == pMe8x8[2].iRefIdx; + const bool bSameRefIdx8x16_1 = true; //pMe8x8[1].iRefIdx == pMe8x8[3].iRefIdx; + const int32_t iSameMv = (bSameMv16x8_0 << 7) | (bSameRefIdx16x8_0 << 6) | (bSameMv16x8_1 << 5) | + (bSameRefIdx16x8_1 << 4) | + (bSameMv8x16_0 << 3) | (bSameRefIdx8x16_0 << 2) | (bSameMv8x16_1 << 1) | (bSameRefIdx8x16_1); + + switch (iSameMv) { + case 0xF0: + pCurMb->uiMbType = MB_TYPE_16x8; + MergeSub16Me (pMe8x8[0], pMe8x8[1], & (pWelsMd->sMe.sMe16x8[0])); + MergeSub16Me (pMe8x8[2], pMe8x8[3], & (pWelsMd->sMe.sMe16x8[1])); + PredInter16x8Mv (pMbCache, 0, 0, & (pWelsMd->sMe.sMe16x8[0].sMvp)); + PredInter16x8Mv (pMbCache, 8, 0, & (pWelsMd->sMe.sMe16x8[1].sMvp)); + break; + case 0x0F: + pCurMb->uiMbType = MB_TYPE_8x16; + MergeSub16Me (pMe8x8[0], pMe8x8[2], & (pWelsMd->sMe.sMe8x16[0])); + MergeSub16Me (pMe8x8[1], pMe8x8[3], & (pWelsMd->sMe.sMe8x16[1])); + PredInter8x16Mv (pMbCache, 0, 0, & (pWelsMd->sMe.sMe8x16[0].sMvp)); + PredInter8x16Mv (pMbCache, 4, 0, & (pWelsMd->sMe.sMe8x16[1].sMvp)); + break; + case 0xFF: + //MERGE_16x16 + //from test results of multiple sequences show that using the following 0x0F to merge 16x16 + //for some seq there is BR saving some loss + //on the whole the BR will increase little bit + //to save complexity we decided not to merge 16x16 at present (10/12/2012) + default: + break; + } + return (MB_TYPE_8x8 != pCurMb->uiMbType); +} + + +void WelsMdInterFinePartitionVaaOnScreen (void* pEnc, void* pMd, SSlice* pSlice, SMB* pCurMb, int32_t iBestCost) { + sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pEnc; + SWelsMD* pWelsMd = (SWelsMD*)pMd; + SMbCache* pMbCache = &pSlice->sMbCacheInfo; + SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer; + int32_t iCostP8x8; + uint8_t uiMbSign = pEncCtx->pFuncList->pfGetMbSignFromInterVaa (&pEncCtx->pVaa->sVaaCalcInfo.pSad8x8[pCurMb->iMbXY][0]); + + if (MBVAASIGN_FLAT == uiMbSign) { + return; + } + + iCostP8x8 = WelsMdP8x8 (pEncCtx->pFuncList, pCurDqLayer, pWelsMd, pSlice); + if (iCostP8x8 < iBestCost) { + iBestCost = iCostP8x8; + pCurMb->uiMbType = MB_TYPE_8x8; + + TryModeMerge (pMbCache, pWelsMd, pCurMb); + } + pWelsMd->iCostLuma = iBestCost; +} } // namespace WelsSVCEnc