ref: e375a70c0377b69155d689cb2ea04a9b2b6ab044
parent: 8d11b28690d47d0e7a0c70beaadc06d96d3c47a5
parent: 99f3bd69c453ba81ca5be15bd4c77a4cfe590ee4
author: Licai Guo <licaguo@cisco.com>
date: Mon Mar 24 10:30:15 EDT 2014
Merge pull request #564 from sijchen/me_rfr56 [Encoder ME] Add checking directional MV in ME initial point
--- a/codec/encoder/core/inc/svc_motion_estimate.h
+++ b/codec/encoder/core/inc/svc_motion_estimate.h
@@ -140,6 +140,12 @@
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 );
+bool CheckDirectionalMv(PSampleSadSatdCostFunc pSad, void * vpMe,
+ const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+ int32_t& iBestSadCost);
+bool CheckDirectionalMvFalse(PSampleSadSatdCostFunc pSad, void * vpMe,
+ const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+ int32_t& iBestSadCost);
inline void SetMvWithinMvRange( const int32_t kiMbWidth, const int32_t kiMbHeight, const int32_t kiMbX, const int32_t kiMbY,
const int32_t kiMaxMvRange,
@@ -151,6 +157,14 @@
pMvMax->iMvY = WELS_MIN( ((kiMbHeight - kiMbY)<<4) - INTPEL_NEEDED_MARGIN, kiMaxMvRange);
}
-
+inline bool CheckMvInRange( const int16_t kiCurrentMv, const int16_t kiMinMv, const int16_t kiMaxMv )
+{
+ return ((kiCurrentMv >= kiMinMv) && (kiCurrentMv < kiMaxMv));
+}
+inline bool CheckMvInRange( const SMVUnitXY ksCurrentMv, const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv )
+{
+ return (CheckMvInRange(ksCurrentMv.iMvX, ksMinMv.iMvX, ksMaxMv.iMvX)
+ && CheckMvInRange(ksCurrentMv.iMvY, ksMinMv.iMvY, ksMaxMv.iMvY));
+}
}
#endif
--- a/codec/encoder/core/inc/wels_func_ptr_def.h
+++ b/codec/encoder/core/inc/wels_func_ptr_def.h
@@ -136,6 +136,9 @@
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 );
+typedef bool (*PCheckDirectionalMv) (PSampleSadSatdCostFunc pSad, void * vpMe,
+ const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+ int32_t& iBestSadCost);
#define MAX_BLOCK_TYPE 5 // prev 7
typedef struct TagSampleDealingFunc {
@@ -188,6 +191,7 @@
PMotionSearchFunc
pfMotionSearch; //svc_encode_slice.c svc_mode_decision.c svc_enhance_layer_md.c svc_base_layer_md.c
PCalculateSatdFunc pfCalculateSatd;
+ PCheckDirectionalMv pfCheckDirectionalMv;
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
@@ -2515,6 +2515,7 @@
pFuncList->pfMotionSearch = WelsMotionEstimateSearch;
pFuncList->pfFirstIntraMode = WelsMdFirstIntraMode;
pFuncList->sSampleDealingFuncs.pfMeCost = pCtx->pFuncList->sSampleDealingFuncs.pfSampleSatd;
+ pFuncList->pfCheckDirectionalMv = CheckDirectionalMvFalse;
if (kbHighestSpatialLayer) {
pFuncList->pfCalculateSatd = NotCalculateSatdCost;
pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaa;
--- a/codec/encoder/core/src/svc_base_layer_md.cpp
+++ b/codec/encoder/core/src/svc_base_layer_md.cpp
@@ -970,24 +970,31 @@
WelsMdIntraSecondaryModesEnc (pEncCtx, pWelsMd, pCurMb, pMbCache);
}
+static inline void InitMe(const SWelsMD& sWelsMd, const int32_t iBlockSize, uint8_t* pEnc, uint8_t* pRef,
+ SWelsME& sWelsMe )
+{
+ sWelsMe.iCurMeBlockPixX = sWelsMd.iMbPixX;
+ sWelsMe.iCurMeBlockPixY = sWelsMd.iMbPixY;
+ sWelsMe.uiPixel = iBlockSize;
+ sWelsMe.pMvdCost = sWelsMd.pMvdCost;
+
+ sWelsMe.pEncMb = pEnc;
+ sWelsMe.pRefMb = sWelsMe.pColoRefMb = pRef;
+}
+
int32_t WelsMdP16x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb) {
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
- SWelsME* sMe16x16 = &pWelsMd->sMe.sMe16x16;
+ SWelsME* pMe16x16 = &pWelsMd->sMe.sMe16x16;
uint32_t uiNeighborAvail = pCurMb->uiNeighborAvail;
const int32_t kiMbWidth = pCurLayer->iMbWidth; // for assign once
const int32_t kiMbHeight = pCurLayer->iMbHeight;
+ InitMe(*pWelsMd, BLOCK_16x16, pMbCache->SPicData.pEncMb[0], pMbCache->SPicData.pRefMb[0],
+ *pMe16x16 );
+ //not putting the line below into InitMe to avoid judging mode in InitMe
+ pMe16x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb;
- sMe16x16->iCurMeBlockPixX = pWelsMd->iMbPixX;
- sMe16x16->iCurMeBlockPixY = pWelsMd->iMbPixY;
- sMe16x16->uiPixel = BLOCK_16x16;
- sMe16x16->pMvdCost = pWelsMd->pMvdCost;
-
- sMe16x16->pEncMb = pMbCache->SPicData.pEncMb[0];
- sMe16x16->pRefMb = pMbCache->SPicData.pRefMb[0];
- sMe16x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb;
-
pSlice->uiMvcNum = 0;
- pSlice->sMvc[pSlice->uiMvcNum++] = sMe16x16->sMvBase;
+ pSlice->sMvc[pSlice->uiMvcNum++] = pMe16x16->sMvBase;
//spatial motion vector predictors
if (uiNeighborAvail & LEFT_MB_POS) { //left available
pSlice->sMvc[pSlice->uiMvcNum++] = (pCurMb - 1)->sP16x16Mv;
@@ -1011,14 +1018,14 @@
}
}
- PredMv (&pMbCache->sMvComponents, 0, 4, 0, & (sMe16x16->sMvp));
- pFunc->pfMotionSearch (pFunc, pCurLayer, sMe16x16, pSlice);
-// update_p16x16_motion2cache(pMbCache, pWelsMd->uiRef, &(sMe16x16->mv));
+ PredMv (&pMbCache->sMvComponents, 0, 4, 0, & (pMe16x16->sMvp));
+ pFunc->pfMotionSearch (pFunc, pCurLayer, pMe16x16, pSlice);
+// update_p16x16_motion2cache(pMbCache, pWelsMd->uiRef, &(pMe16x16->mv));
- pCurMb->sP16x16Mv = sMe16x16->sMv;
- pCurLayer->pDecPic->sMvList[pCurMb->iMbXY] = sMe16x16->sMv;
+ pCurMb->sP16x16Mv = pMe16x16->sMv;
+ pCurLayer->pDecPic->sMvList[pCurMb->iMbXY] = pMe16x16->sMv;
- return sMe16x16->uiSatdCost;
+ return pMe16x16->uiSatdCost;
}
int32_t WelsMdP16x8 (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SWelsMD* pWelsMd, SSlice* pSlice) {
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
@@ -1025,16 +1032,17 @@
int32_t iStrideEnc = pCurDqLayer->iEncStride[0];
int32_t iStrideRef = pCurDqLayer->pRefPic->iLineSize[0];
SWelsME* sMe16x8;
- int32_t i = 0;
+ int32_t i = 0, iPixelY;
int32_t iCostP16x8 = 0;
do {
sMe16x8 = &pWelsMd->sMe.sMe16x8[i];
-
- sMe16x8->uiPixel = BLOCK_16x8;
- sMe16x8->pMvdCost = pWelsMd->pMvdCost;
-
- sMe16x8->pEncMb = pMbCache->SPicData.pEncMb[0] + ((i << 3) * iStrideEnc);
- sMe16x8->pRefMb = pMbCache->SPicData.pRefMb[0] + ((i << 3) * iStrideRef);
+ iPixelY = (i << 3);
+ InitMe(*pWelsMd, BLOCK_16x8,
+ pMbCache->SPicData.pEncMb[0] + (iPixelY * iStrideEnc),
+ pMbCache->SPicData.pRefMb[0] + (iPixelY * iStrideRef),
+ *sMe16x8 );
+ //not putting the lines below into InitMe to avoid judging mode in InitMe
+ sMe16x8->iCurMeBlockPixY = pWelsMd->iMbPixY + iPixelY;
sMe16x8->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb >> 1;
pSlice->sMvc[0] = sMe16x8->sMvBase;
@@ -1051,16 +1059,17 @@
int32_t WelsMdP8x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWelsMd, SSlice* pSlice) {
SMbCache* pMbCache = &pSlice->sMbCacheInfo;
SWelsME* sMe8x16;
- int32_t i = 0;
+ int32_t i = 0, iPixelX;
int32_t iCostP8x16 = 0;
do {
+ iPixelX = (i << 3);
sMe8x16 = &pWelsMd->sMe.sMe8x16[i];
-
- sMe8x16->uiPixel = BLOCK_8x16;
- sMe8x16->pMvdCost = pWelsMd->pMvdCost;
-
- sMe8x16->pEncMb = pMbCache->SPicData.pEncMb[0] + (i << 3);
- sMe8x16->pRefMb = pMbCache->SPicData.pRefMb[0] + (i << 3);
+ InitMe(*pWelsMd, BLOCK_8x16,
+ pMbCache->SPicData.pEncMb[0] + iPixelX,
+ pMbCache->SPicData.pRefMb[0] + iPixelX,
+ *sMe8x16 );
+ //not putting the lines below into InitMe to avoid judging mode in InitMe
+ sMe8x16->iCurMeBlockPixX = pWelsMd->iMbPixX + iPixelX;
sMe8x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb >> 1;
pSlice->sMvc[0] = sMe8x16->sMvBase;
@@ -1091,16 +1100,16 @@
iStrideRef = iPixelX + ( iPixelY * iLineSizeRef);
sMe8x8 = &pWelsMd->sMe.sMe8x8[i];
-
+ InitMe(*pWelsMd, BLOCK_8x8,
+ pMbCache->SPicData.pEncMb[0] + iStrideEnc,
+ pMbCache->SPicData.pRefMb[0] + iStrideRef,
+ *sMe8x8 );
+ //not putting these three lines below into InitMe to avoid judging mode in InitMe
sMe8x8->iCurMeBlockPixX = pWelsMd->iMbPixX + iPixelX;
sMe8x8->iCurMeBlockPixY = pWelsMd->iMbPixY + iPixelY;
- sMe8x8->uiPixel = BLOCK_8x8;
- sMe8x8->pMvdCost = pWelsMd->pMvdCost;
-
- sMe8x8->pEncMb = pMbCache->SPicData.pEncMb[0] + iStrideEnc;
- sMe8x8->pRefMb = pMbCache->SPicData.pRefMb[0] + iStrideRef;
sMe8x8->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb >> 2;
+
pSlice->sMvc[0] = sMe8x8->sMvBase;
pSlice->uiMvcNum = 1;
@@ -1855,5 +1864,7 @@
WelsIMbChromaEncode (pEncCtx, pCurMb, pMbCache); //add pEnc&rec to MD--2010.3.15
pCurMb->pSadCost[0] = 0;
}
+
+
} // namespace WelsSVCEnc
--- a/codec/encoder/core/src/svc_motion_estimate.cpp
+++ b/codec/encoder/core/src/svc_motion_estimate.cpp
@@ -39,7 +39,7 @@
*/
-
+#include "sample.h"
#include "svc_motion_estimate.h"
namespace WelsSVCEnc {
@@ -141,6 +141,13 @@
}
}
+ if ( pFuncList->pfCheckDirectionalMv
+ (pSad, pMe, ksMvStartMin, ksMvStartMax, iStrideEnc, iStrideRef, iSadCost) ) {
+ sMv = pMe->sDirectionalMv;
+ pRefMb = &pMe->pColoRefMb[sMv.iMvY * iStrideRef + sMv.iMvX];
+ iBestSadCost = iSadCost;
+ }
+
UpdateMeResults( sMv, iBestSadCost, pRefMb, pMe );
if ( iBestSadCost < static_cast<int32_t>(pMe->uSadPredISatd.uiSadPred) ) {
//Initial point early Stop
@@ -235,6 +242,39 @@
}
void NotCalculateSatdCost( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride )
{
+}
+
+
+bool CheckDirectionalMv(PSampleSadSatdCostFunc pSad, void * vpMe,
+ const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+ int32_t& iBestSadCost)
+{
+ SWelsME* pMe = static_cast<SWelsME *>(vpMe);
+ const int16_t kiMvX = pMe->sDirectionalMv.iMvX;
+ const int16_t kiMvY = pMe->sDirectionalMv.iMvY;
+
+ //Check MV from scrolling detection
+ if ( (BLOCK_16x16!=pMe->uiPixel) //scrolled_MV with P16x16 is checked SKIP checking function
+ && ( kiMvX | kiMvY ) //(0,0) checked in ordinary initial point checking
+ && CheckMvInRange( pMe->sDirectionalMv, ksMinMv, ksMaxMv ) )
+ {
+ uint8_t* pRef = &pMe->pColoRefMb[kiMvY * kiRefStride + kiMvX];
+ uint32_t uiCurrentSadCost = pSad( pMe->pEncMb, kiEncStride, pRef, kiRefStride ) +
+ COST_MVD(pMe->pMvdCost, (kiMvX<<2) - pMe->sMvp.iMvX, (kiMvY<<2) - pMe->sMvp.iMvY );
+ if( uiCurrentSadCost < pMe->uiSadCost )
+ {
+ iBestSadCost = uiCurrentSadCost;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CheckDirectionalMvFalse(PSampleSadSatdCostFunc pSad, void * vpMe,
+ const SMVUnitXY ksMinMv, const SMVUnitXY ksMaxMv, const int32_t kiEncStride, const int32_t kiRefStride,
+ int32_t& iBestSadCost)
+{
+ return false;
}
} // namespace WelsSVCEnc