ref: 6c3d83a8ac4df68f0df1fd1edd6f96ce49ddca50
parent: 8492aac917af81807ca7b3c33d27b318e44ee3e7
author: sijchen <sijchen@cisco.com>
date: Fri Mar 14 11:04:35 EDT 2014
refactor ME for easier adding other search methods
--- a/codec/encoder/core/inc/svc_motion_estimate.h
+++ b/codec/encoder/core/inc/svc_motion_estimate.h
@@ -83,12 +83,9 @@
*
* \return NONE
*/
-void WelsMotionEstimateSearchSatd (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice);
+void WelsMotionEstimateSearch (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice);
-void WelsMotionEstimateSearchSad (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice);
-
-
/*!
* \brief BL mb motion estimate initial point testing
*
@@ -112,7 +109,7 @@
* \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);
/*!
@@ -129,6 +126,9 @@
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,
--- 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 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 (*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 @@
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
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -2471,7 +2471,8 @@
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 @@
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 @@
} 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 @@
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;
--- 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 @@
* \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,26 +76,13 @@
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);
+ pFuncList->pfCalculateSatd( pFuncList->sSampleDealingFuncs.pfSampleSatd[pMe->uiPixel], pMe, iStrideEnc, iStrideRef );
}
-
-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);
-}
-
/*!
* \brief EL mb motion estimate initial point testing
*
@@ -90,7 +93,7 @@
*
* \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 @@
}
}
- 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<int32_t>(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,
@@ -229,6 +224,17 @@
pMe->sMv.iMvY = (iMvDy + pMe->sMvp.iMvY) & 0xFFFC;
pMe->uiSatdCost = pMe->uiSadCost = (iBestCost);
pMe->pRefMb = pRefMb;
+}
+
+void CalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride )
+{
+ SWelsME* pMe = static_cast<SWelsME *>(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