From 6c3d83a8ac4df68f0df1fd1edd6f96ce49ddca50 Mon Sep 17 00:00:00 2001 From: sijchen Date: Fri, 14 Mar 2014 15:04:35 +0800 Subject: [PATCH] refactor ME for easier adding other search methods --- codec/encoder/core/inc/svc_motion_estimate.h | 10 +-- codec/encoder/core/inc/wels_func_ptr_def.h | 9 ++- codec/encoder/core/src/encoder_ext.cpp | 12 ++-- .../encoder/core/src/svc_motion_estimate.cpp | 72 ++++++++++--------- 4 files changed, 59 insertions(+), 44 deletions(-) diff --git a/codec/encoder/core/inc/svc_motion_estimate.h b/codec/encoder/core/inc/svc_motion_estimate.h index 27138b21..94652cf9 100644 --- a/codec/encoder/core/inc/svc_motion_estimate.h +++ b/codec/encoder/core/inc/svc_motion_estimate.h @@ -83,10 +83,7 @@ SMVUnitXY sMv; * * \return NONE */ -void WelsMotionEstimateSearchSatd (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice); - -void WelsMotionEstimateSearchSad (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice); - +void WelsMotionEstimateSearch (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice); /*! @@ -112,7 +109,7 @@ void WelsMotionEstimateSearchSad (SWelsFuncPtrList* pFuncList, void* pLplayer, v * \return NONE */ -void WelsMotionEstimateInitialPoint (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice, +bool WelsMotionEstimateInitialPoint (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice, const int32_t kiStrideEnc, const int32_t kiStrideRef); /*! @@ -130,6 +127,9 @@ void WelsMotionEstimateIterativeSearch (SWelsFuncPtrList* pFuncList, SWelsME* pM bool WelsMeSadCostSelect (int32_t* pSadCost, const uint16_t* kpMvdCost, int32_t* pBestCost, const int32_t kiDx, const int32_t kiDy, int32_t* pIx, int32_t* pIy); +void CalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride ); +void NotCalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride ); + inline void SetMvWithinMvRange( const int32_t kiMbWidth, const int32_t kiMbHeight, const int32_t kiMbX, const int32_t kiMbY, const int32_t kiMaxMvRange, SMVUnitXY* pMvMin, SMVUnitXY* pMvMax) diff --git a/codec/encoder/core/inc/wels_func_ptr_def.h b/codec/encoder/core/inc/wels_func_ptr_def.h index a946d6a3..824a91ce 100644 --- a/codec/encoder/core/inc/wels_func_ptr_def.h +++ b/codec/encoder/core/inc/wels_func_ptr_def.h @@ -112,8 +112,6 @@ typedef int32_t (*PIntraFineMdFunc) (void* pEncCtx, void* pWelsMd, SMB* pCurMb, typedef void (*PInterFineMdFunc) (void* pEncCtx, void* pWelsMd, SSlice* slice, SMB* pCurMb, int32_t bestCost); typedef bool (*PInterMdFirstIntraModeFunc) (void* pEncCtx, void* pWelsMd, SMB* pCurMb, SMbCache* pMbCache); -typedef void (*PMotionSearchFunc) (SWelsFuncPtrList* pFuncList, void* pCurDqLayer, void* pMe, - void* pSlice); // here after reset all function pointers, will set as right parameter type typedef void (*PFillInterNeighborCacheFunc) (SMbCache* pMbCache, SMB* pCurMb, int32_t iMbWidth, int8_t* pVaaBgMbFlag); typedef void (*PAccumulateSadFunc) (uint32_t* pSumDiff, int32_t* pGomForegroundBlockNum, int32_t* iSad8x8, int8_t* pVaaBgMbFlag);//for RC @@ -134,6 +132,11 @@ typedef int32_t (*PIntraPred4x4Combined3Func) (uint8_t*, int32_t, uint8_t*, int3 typedef int32_t (*PIntraPred16x16Combined3Func) (uint8_t*, int32_t, uint8_t*, int32_t, int32_t*, int32_t, uint8_t*); typedef int32_t (*PIntraPred8x8Combined3Func) (uint8_t*, int32_t, uint8_t*, int32_t, int32_t*, int32_t, uint8_t*, uint8_t*, uint8_t*); + +typedef void (*PMotionSearchFunc) (SWelsFuncPtrList* pFuncList, void* pCurDqLayer, void* pMe, + void* pSlice); // here after reset all function pointers, will set as right parameter type +typedef void (*PCalculateSatdFunc) ( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride ); + #define MAX_BLOCK_TYPE 5 // prev 7 typedef struct TagSampleDealingFunc { PSampleSadSatdCostFunc pfSampleSad[MAX_BLOCK_TYPE]; @@ -181,8 +184,10 @@ struct TagWelsFuncPointerList { PGetIntraPredFunc pfGetLumaI16x16Pred[I16_PRED_DC_A]; PGetIntraPredFunc pfGetLumaI4x4Pred[I4_PRED_A]; PGetIntraPredFunc pfGetChromaPred[C_PRED_A]; + PMotionSearchFunc pfMotionSearch; //svc_encode_slice.c svc_mode_decision.c svc_enhance_layer_md.c svc_base_layer_md.c + PCalculateSatdFunc pfCalculateSatd; PCopyFunc pfCopy16x16Aligned; //svc_encode_slice.c svc_mode_decision.c svc_base_layer_md.c PCopyFunc pfCopy16x16NotAligned; //md.c diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index 665bb4cd..6352cb26 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -2471,7 +2471,8 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) { if (P_SLICE == pCtx->eSliceType) { if (kbBaseAvail) { if (pCtx->pSvcParam->iSpatialLayerNum == (pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId + 1)) { // - pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSad; + pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearch; + pCtx->pFuncList->pfCalculateSatd = NotCalculateSatdCost; pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode; pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa; pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa; @@ -2480,7 +2481,8 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) { pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad; pCtx->pFuncList->sSampleDealingFuncs.pfMdCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSad; } else { - pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSatd; + pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearch; + pCtx->pFuncList->pfCalculateSatd = CalculateSatdCost; pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode; pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartition; pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartition; @@ -2494,7 +2496,8 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) { } else { //case 3: pBase layer MD + encoding if (pCurLayer->sLayerInfo.sNalHeaderExt.uiDependencyId + 1 == pCtx->pSvcParam->iSpatialLayerNum) { - pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSad; + pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearch; + pCtx->pFuncList->pfCalculateSatd = NotCalculateSatdCost; pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode; pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartitionVaa; pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa; @@ -2503,7 +2506,8 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) { pCtx->pFuncList->sSampleDealingFuncs.pfIntra16x16Combined3Sad; pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3 = pCtx->pFuncList->sSampleDealingFuncs.pfIntra8x8Combined3Sad; } else { - pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearchSatd; + pCtx->pFuncList->pfMotionSearch = WelsMotionEstimateSearch; + pCtx->pFuncList->pfCalculateSatd = CalculateSatdCost; pCtx->pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode; pCtx->pFuncList->pfIntraFineMd = WelsMdIntraFinePartition; pCtx->pFuncList->pfInterFineMd = WelsMdInterFinePartition; diff --git a/codec/encoder/core/src/svc_motion_estimate.cpp b/codec/encoder/core/src/svc_motion_estimate.cpp index 7f28c2f5..2b4e6dc8 100644 --- a/codec/encoder/core/src/svc_motion_estimate.cpp +++ b/codec/encoder/core/src/svc_motion_estimate.cpp @@ -43,6 +43,22 @@ #include "svc_motion_estimate.h" namespace WelsSVCEnc { + +inline void UpdateMeResults( const SMVUnitXY ksBestMv, const uint32_t kiBestSadCost, uint8_t* pRef, SWelsME * pMe ) +{ + pMe->sMv = ksBestMv; + pMe->pRefMb = pRef; + pMe->uiSadCost = kiBestSadCost; +} +inline void SvcMeEndSearch( SWelsME * pMe, const uint32_t kuiBestSadCost ) +{ + /* -> qpel mv */ + pMe->sMv.iMvX <<= 2; + pMe->sMv.iMvY <<= 2; + pMe->uiSatdCost = kuiBestSadCost; +} + + /*! * \brief BL mb motion estimate search * @@ -52,7 +68,7 @@ namespace WelsSVCEnc { * \return NONE */ -void WelsMotionEstimateSearchSatd (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice) { +void WelsMotionEstimateSearch (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice) { SDqLayer* pCurDqLayer = (SDqLayer*)pLplayer; SWelsME* pMe = (SWelsME*)pLpme; SSlice* pSlice = (SSlice*)pLpslice; @@ -60,24 +76,11 @@ void WelsMotionEstimateSearchSatd (SWelsFuncPtrList* pFuncList, void* pLplayer, int32_t iStrideRef = pCurDqLayer->pRefPic->iLineSize[0]; // Step 1: Initial point prediction - WelsMotionEstimateInitialPoint (pFuncList, pMe, pSlice, iStrideEnc, iStrideRef); + if ( !WelsMotionEstimateInitialPoint (pFuncList, pMe, pSlice, iStrideEnc, iStrideRef) ) { + WelsMotionEstimateIterativeSearch (pFuncList, pMe, iStrideEnc, iStrideRef, pMe->pRefMb); + } - pMe->uSadPredISatd.uiSatd = pFuncList->sSampleDealingFuncs.pfSampleSatd[pMe->uiPixel] (pMe->pEncMb, iStrideEnc, - pMe->pRefMb, iStrideRef); - pMe->uiSatdCost = pMe->uSadPredISatd.uiSatd + COST_MVD (pMe->pMvdCost, pMe->sMv.iMvX - pMe->sMvp.iMvX, - pMe->sMv.iMvY - pMe->sMvp.iMvY); -} - - -void WelsMotionEstimateSearchSad (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice) { - SDqLayer* pCurDqLayer = (SDqLayer*)pLplayer; - SWelsME* pMe = (SWelsME*)pLpme; - SSlice* slice = (SSlice*)pLpslice; - int32_t iStrideEnc = pCurDqLayer->iEncStride[0]; - int32_t iStrideRef = pCurDqLayer->pRefPic->iLineSize[0]; - - // Step 1: Initial point prediction - WelsMotionEstimateInitialPoint (pFuncList, pMe, slice, iStrideEnc, iStrideRef); + pFuncList->pfCalculateSatd( pFuncList->sSampleDealingFuncs.pfSampleSatd[pMe->uiPixel], pMe, iStrideEnc, iStrideRef ); } /*! @@ -90,7 +93,7 @@ void WelsMotionEstimateSearchSad (SWelsFuncPtrList* pFuncList, void* pLplayer, v * * \return NONE */ -void WelsMotionEstimateInitialPoint (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice, int32_t iStrideEnc, +bool WelsMotionEstimateInitialPoint (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice, int32_t iStrideEnc, int32_t iStrideRef) { PSampleSadSatdCostFunc pSad = pFuncList->sSampleDealingFuncs.pfSampleSad[pMe->uiPixel]; const uint16_t* kpMvdCost = pMe->pMvdCost; @@ -138,21 +141,13 @@ void WelsMotionEstimateInitialPoint (SWelsFuncPtrList* pFuncList, SWelsME* pMe, } } - pMe->sMv = sMv; - pMe->uiSadCost = iBestSadCost; - if (iBestSadCost < pMe->uSadPredISatd.uiSadPred) { - // Step 2: Initial early Stop - /* -> qpel mv */ - pMe->sMv.iMvX <<= 2; - pMe->sMv.iMvY <<= 2; - /* -> pRef */ - pMe->pRefMb = pRefMb; - /* compute the real cost */ - pMe->uiSatdCost = iBestSadCost; - } else { - // Step 3: Fast search pattern - WelsMotionEstimateIterativeSearch (pFuncList, pMe, iStrideEnc, iStrideRef, pRefMb); + UpdateMeResults( sMv, iBestSadCost, pRefMb, pMe ); + if ( iBestSadCost < static_cast(pMe->uSadPredISatd.uiSadPred) ) { + //Initial point early Stop + SvcMeEndSearch(pMe, iBestSadCost); + return true; } + return false; } bool WelsMeSadCostSelect (int32_t* iSadCost, const uint16_t* kpMvdCost, int32_t* pBestCost, const int32_t kiDx, @@ -231,4 +226,15 @@ void WelsMotionEstimateIterativeSearch (SWelsFuncPtrList* pFuncList, SWelsME* pM pMe->pRefMb = pRefMb; } +void CalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride ) +{ + SWelsME* pMe = static_cast(vpMe); + pMe->uSadPredISatd.uiSatd = pSatd(pMe->pEncMb, kiEncStride, pMe->pRefMb, kiRefStride); + pMe->uiSatdCost = pMe->uSadPredISatd.uiSatd + COST_MVD (pMe->pMvdCost, pMe->sMv.iMvX - pMe->sMvp.iMvX, + pMe->sMv.iMvY - pMe->sMvp.iMvY); +} +void NotCalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride ) +{ +} + } // namespace WelsSVCEnc