ref: 7f3f397706835dfa376ead7b5a5d222507d31a6c
parent: 1e3b015a6f95ae87ce83d28304445770f35fec2e
parent: 80ae4cb7d8cbf7503b03dada6161ca79469fa893
author: huili2 <[email protected]>
date: Sat May 17 17:49:07 EDT 2014
Merge pull request #831 from sijchen/md_merge144 [Encoder ME] Add ME function assignment for Screen Content Coding
--- a/codec/encoder/core/inc/svc_motion_estimate.h
+++ b/codec/encoder/core/inc/svc_motion_estimate.h
@@ -90,6 +90,8 @@
SMVUnitXY sMvBase;
SMVUnitXY sDirectionalMv;
+ SScreenBlockFeatureStorage* pRefFeatureStorage;
+
/* output */
SMVUnitXY sMv;
} SWelsME;
@@ -220,7 +222,10 @@
const int32_t kiMinPos, const int32_t kiMaxPos,
const bool bVerticalSearch);
#endif
-void WelsMotionCrossSearch (SWelsFuncPtrList* pFuncList, SDqLayer* pCurLayer, SWelsME* pMe, const SSlice* pSlice);
+void WelsMotionCrossSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,
+ const int32_t kiEncStride, const int32_t kiRefStride);
+void WelsDiamondCrossSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,
+ const int32_t kiEncStride, const int32_t kiRefStride);
// Feature Search Basics
#define LIST_SIZE_SUM_16x16 0x0FF01 //(256*255+1)
@@ -255,6 +260,9 @@
SScreenBlockFeatureStorage* pScreenBlockFeatureStorage);
void UpdateFMESwitch (SDqLayer* pCurLayer);
void UpdateFMESwitchNull (SDqLayer* pCurLayer);
+
+void WelsDiamondCrossFeatureSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,
+ const int32_t kiEncStride, const int32_t kiRefStride);
//inline functions
inline void SetMvWithinIntegerMvRange (const int32_t kiMbWidth, const int32_t kiMbHeight, const int32_t kiMbX,
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -2428,8 +2428,38 @@
pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3 =
pFuncList->sSampleDealingFuncs.pfIntra4x4Combined3Satd;
}
+bool SetMeMethod (const uint8_t uiMethod, PSearchMethodFunc& pSearchMethodFunc) {
+ switch (uiMethod) {
+ case ME_DIA:
+ pSearchMethodFunc = WelsDiamondSearch;
+ break;
+ case ME_CROSS:
+ pSearchMethodFunc = WelsMotionCrossSearch;
+ break;
+ case ME_DIA_CROSS:
+ pSearchMethodFunc = WelsDiamondCrossSearch;
+ break;
+ case ME_DIA_CROSS_FME:
+ pSearchMethodFunc = WelsDiamondCrossFeatureSearch;
+ break;
+ case ME_FULL:
+#ifdef HAVE_MMX
+ // make sure your cpu can support x86 sse4.1 instruction set if try it
+ //pSearchMethodFunc = WelsFullSearch;
+#else
+ pSearchMethodFunc = WelsDiamondSearch;
+ return false;
+#endif//HAVE_MMX
+ break;
+ default:
+ pSearchMethodFunc = WelsDiamondSearch;
+ return false;
+ }
+ return true;
+}
+
void PreprocessSliceCoding (sWelsEncCtx* pCtx) {
SDqLayer* pCurLayer = pCtx->pCurDqLayer;
//const bool kbBaseAvail = pCurLayer->bBaseLayerAvailableFlag;
@@ -2465,13 +2495,19 @@
return;
//to init at each frame will be needed when dealing with hybrid content (camera+screen)
if (pCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
- SFeatureSearchPreparation* pFeatureSearchPreparation = pCurLayer->pFeatureSearchPreparation;
- if (pFeatureSearchPreparation) {
- pFeatureSearchPreparation->iHighFreMbCount = 0;
+ if (P_SLICE == pCtx->eSliceType) {
+ //MD related func pointers
+ pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaaOnScreen;
- if (P_SLICE == pCtx->eSliceType) {
- //MD related func pointers
- pFuncList->pfInterFineMd = WelsMdInterFinePartitionVaaOnScreen;
+ //ME related func pointers
+ //ME16x16
+ if (!SetMeMethod (ME_DIA_CROSS, pFuncList->pfSearchMethod[BLOCK_16x16])) {
+ WelsLog (pCtx, WELS_LOG_WARNING, "SetMeMethod(BLOCK_16x16) ME_DIA_CROSS unsuccessful, switched to default search\n");
+ }
+ //ME8x8
+ SFeatureSearchPreparation* pFeatureSearchPreparation = pCurLayer->pFeatureSearchPreparation;
+ if (pFeatureSearchPreparation) {
+ pFeatureSearchPreparation->iHighFreMbCount = 0;
//calculate bFMESwitchFlag
SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
@@ -2491,8 +2527,11 @@
}
//assign ME pointer
- if (pScreenBlockFeatureStorage->bRefBlockFeatureCalculated) {
- //TBC int32_t iIs16x16 = pScreenBlockFeatureStorage->iIs16x16;
+ if (pFeatureSearchPreparation->bFMESwitchFlag && pScreenBlockFeatureStorage->bRefBlockFeatureCalculated
+ && (!pScreenBlockFeatureStorage->iIs16x16)) {
+ if (!SetMeMethod (ME_DIA_CROSS_FME, pFuncList->pfSearchMethod[BLOCK_8x8])) {
+ WelsLog (pCtx, WELS_LOG_WARNING, "SetMeMethod(BLOCK_8x8) ME_DIA_CROSS_FME unsuccessful, switched to default search\n");
+ }
}
//assign UpdateFMESwitch pointer
@@ -2501,11 +2540,11 @@
} else {
pFuncList->pfUpdateFMESwitch = UpdateFMESwitchNull;
}
- } else {
- //reset some status when at I_SLICE
- pFeatureSearchPreparation->bFMESwitchFlag = true;
- pFeatureSearchPreparation->uiFMEGoodFrameCount = FMESWITCH_DEFAULT_GOODFRAME_NUM;
- }
+ }//if (pFeatureSearchPreparation)
+ } else {
+ //reset some status when at I_SLICE
+ pCurLayer->pFeatureSearchPreparation->bFMESwitchFlag = true;
+ pCurLayer->pFeatureSearchPreparation->uiFMEGoodFrameCount = FMESWITCH_DEFAULT_GOODFRAME_NUM;
}
}
}
--- a/codec/encoder/core/src/svc_base_layer_md.cpp
+++ b/codec/encoder/core/src/svc_base_layer_md.cpp
@@ -971,6 +971,7 @@
}
static inline void InitMe (const SWelsMD& sWelsMd, const int32_t iBlockSize, uint8_t* pEnc, uint8_t* pRef,
+ SScreenBlockFeatureStorage* pRefFeatureStorage,
SWelsME& sWelsMe) {
sWelsMe.iCurMeBlockPixX = sWelsMd.iMbPixX;
sWelsMe.iCurMeBlockPixY = sWelsMd.iMbPixY;
@@ -979,6 +980,8 @@
sWelsMe.pEncMb = pEnc;
sWelsMe.pRefMb = sWelsMe.pColoRefMb = pRef;
+
+ sWelsMe.pRefFeatureStorage = pRefFeatureStorage;
}
int32_t WelsMdP16x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb) {
@@ -988,6 +991,7 @@
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],
+ pCurLayer->pRefPic->pScreenBlockFeatureStorage,
*pMe16x16);
//not putting the line below into InitMe to avoid judging mode in InitMe
pMe16x16->uSadPredISatd.uiSadPred = pWelsMd->iSadPredMb;
@@ -1038,6 +1042,7 @@
InitMe (*pWelsMd, BLOCK_16x8,
pMbCache->SPicData.pEncMb[0] + (iPixelY * iStrideEnc),
pMbCache->SPicData.pRefMb[0] + (iPixelY * iStrideRef),
+ pCurDqLayer->pRefPic->pScreenBlockFeatureStorage,
*sMe16x8);
//not putting the lines below into InitMe to avoid judging mode in InitMe
sMe16x8->iCurMeBlockPixY = pWelsMd->iMbPixY + iPixelY;
@@ -1065,6 +1070,7 @@
InitMe (*pWelsMd, BLOCK_8x16,
pMbCache->SPicData.pEncMb[0] + iPixelX,
pMbCache->SPicData.pRefMb[0] + iPixelX,
+ pCurLayer->pRefPic->pScreenBlockFeatureStorage,
*sMe8x16);
//not putting the lines below into InitMe to avoid judging mode in InitMe
sMe8x16->iCurMeBlockPixX = pWelsMd->iMbPixX + iPixelX;
@@ -1100,6 +1106,7 @@
InitMe (*pWelsMd, BLOCK_8x8,
pMbCache->SPicData.pEncMb[0] + iStrideEnc,
pMbCache->SPicData.pRefMb[0] + iStrideRef,
+ pCurDqLayer->pRefPic->pScreenBlockFeatureStorage,
*sMe8x8);
//not putting these three lines below into InitMe to avoid judging mode in InitMe
sMe8x8->iCurMeBlockPixX = pWelsMd->iMbPixX + iPixelX;
--- a/codec/encoder/core/src/svc_motion_estimate.cpp
+++ b/codec/encoder/core/src/svc_motion_estimate.cpp
@@ -492,8 +492,8 @@
}
}
-void WelsMotionCrossSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe,
- const SSlice* pSlice, const int32_t kiEncStride, const int32_t kiRefStride) {
+void WelsMotionCrossSearch (SWelsFuncPtrList* pFuncList, SWelsME* pMe, SSlice* pSlice,
+ const int32_t kiEncStride, const int32_t kiRefStride) {
PLineFullSearchFunc pfVerticalFullSearchFunc = pFuncList->pfVerticalFullSearch;
PLineFullSearchFunc pfHorizontalFullSearchFunc = pFuncList->pfHorizontalFullSearch;
@@ -709,7 +709,7 @@
}
}
-void CalculateFeatureOfBlock (SWelsFuncPtrList* pFunc, SPicture* pRef,
+bool CalculateFeatureOfBlock (SWelsFuncPtrList* pFunc, SPicture* pRef,
SScreenBlockFeatureStorage* pScreenBlockFeatureStorage) {
uint16_t* pFeatureOfBlock = pScreenBlockFeatureStorage->pFeatureOfBlockPointer;
uint32_t* pTimesOfFeatureValue = pScreenBlockFeatureStorage->pTimesOfFeatureValue;
@@ -716,6 +716,11 @@
uint16_t** pLocationOfFeature = pScreenBlockFeatureStorage->pLocationOfFeature;
uint16_t* pBuf = pScreenBlockFeatureStorage->pLocationPointer;
+ if (NULL == pFeatureOfBlock || NULL == pTimesOfFeatureValue || NULL == pLocationOfFeature || NULL == pBuf
+ || NULL == pRef->pData[0]) {
+ return false;
+ }
+
uint8_t* pRefData = pRef->pData[0];
const int32_t iRefStride = pRef->iLineSize[0];
int32_t iIs16x16 = pScreenBlockFeatureStorage->iIs16x16;
@@ -735,25 +740,28 @@
//assign each pixel's pLocationOfFeature
FillQpelLocationByFeatureValue_c (pFeatureOfBlock, iWidth, kiHeight, pFeatureValuePointerList);
+ return true;
}
void PerformFMEPreprocess (SWelsFuncPtrList* pFunc, SPicture* pRef, uint16_t* pFeatureOfBlock,
SScreenBlockFeatureStorage* pScreenBlockFeatureStorage) {
pScreenBlockFeatureStorage->pFeatureOfBlockPointer = pFeatureOfBlock;
- CalculateFeatureOfBlock (pFunc, pRef, pScreenBlockFeatureStorage);
- pScreenBlockFeatureStorage->bRefBlockFeatureCalculated = true;
+ pScreenBlockFeatureStorage->bRefBlockFeatureCalculated = CalculateFeatureOfBlock (pFunc, pRef,
+ pScreenBlockFeatureStorage);
- uint32_t uiRefPictureAvgQstepx16 = QStepx16ByQp[WelsMedian (0, pRef->iFrameAverageQp, 51)];
- uint32_t uiSadCostThreshold16x16 = ((30 * (uiRefPictureAvgQstepx16 + 160)) >> 3);
- pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_16x16] = uiSadCostThreshold16x16;
- pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_8x8] = (uiSadCostThreshold16x16 >> 2);
- pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_16x8]
- = pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_8x16]
- = pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_4x4] = UINT_MAX;
+ if (pScreenBlockFeatureStorage->bRefBlockFeatureCalculated) {
+ uint32_t uiRefPictureAvgQstepx16 = QStepx16ByQp[WelsMedian (0, pRef->iFrameAverageQp, 51)];
+ uint32_t uiSadCostThreshold16x16 = ((30 * (uiRefPictureAvgQstepx16 + 160)) >> 3);
+ pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_16x16] = uiSadCostThreshold16x16;
+ pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_8x8] = (uiSadCostThreshold16x16 >> 2);
+ pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_16x8]
+ = pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_8x16]
+ = pScreenBlockFeatureStorage->uiSadCostThreshold[BLOCK_4x4] = UINT_MAX;
+ }
}
//search related
-void SetFeatureSearchIn (SWelsFuncPtrList* pFunc, const SWelsME& sMe,
+bool SetFeatureSearchIn (SWelsFuncPtrList* pFunc, const SWelsME& sMe,
const SSlice* pSlice, SScreenBlockFeatureStorage* pRefFeatureStorage,
const int32_t kiEncStride, const int32_t kiRefStride,
SFeatureSearchIn* pFeatureSearchIn) {
@@ -781,6 +789,12 @@
pFeatureSearchIn->iMinQpelY = pFeatureSearchIn->iCurPixYQpel + ((pSlice->sMvStartMin.iMvY) << 2);
pFeatureSearchIn->iMaxQpelX = pFeatureSearchIn->iCurPixXQpel + ((pSlice->sMvStartMax.iMvX) << 2);
pFeatureSearchIn->iMaxQpelY = pFeatureSearchIn->iCurPixYQpel + ((pSlice->sMvStartMax.iMvY) << 2);
+
+ if (NULL == pFeatureSearchIn->pSad || NULL == pFeatureSearchIn->pTimesOfFeature
+ || NULL == pFeatureSearchIn->pQpelLocationOfFeature) {
+ return false;
+ }
+ return true;
}
void SaveFeatureSearchOut (const SMVUnitXY sBestMv, const uint32_t uiBestSadCost, uint8_t* pRef,
SFeatureSearchOut* pFeatureSearchOut) {
@@ -922,8 +936,7 @@
WelsDiamondSearch (pFunc, pMe, pSlice, kiEncStride, kiRefStride);
// Step 2: CROSS search
- SScreenBlockFeatureStorage pRefBlockFeature; //TODO: use this structure from Ref
- pMe->uiSadCostThreshold = pRefBlockFeature.uiSadCostThreshold[pMe->uiBlockSize];
+ pMe->uiSadCostThreshold = pMe->pRefFeatureStorage->uiSadCostThreshold[pMe->uiBlockSize];
if (pMe->uiSadCost >= pMe->uiSadCostThreshold) {
WelsMotionCrossSearch (pFunc, pMe, pSlice, kiEncStride, kiRefStride);
}
@@ -937,14 +950,13 @@
if (pMe->uiSadCost >= pMe->uiSadCostThreshold) {
pSlice->uiSliceFMECostDown += pMe->uiSadCost;
- SScreenBlockFeatureStorage tmpScreenBlockFeatureStorage; //TODO: use this structure from Ref
uint32_t uiMaxSearchPoint = INT_MAX;//TODO: change it according to computational-complexity setting
SFeatureSearchIn sFeatureSearchIn = {0};
- SetFeatureSearchIn (pFunc, *pMe, pSlice, &tmpScreenBlockFeatureStorage,
- kiEncStride, kiRefStride,
- &sFeatureSearchIn);
- MotionEstimateFeatureFullSearch (sFeatureSearchIn, uiMaxSearchPoint, pMe);
-
+ if (SetFeatureSearchIn (pFunc, *pMe, pSlice, pMe->pRefFeatureStorage,
+ kiEncStride, kiRefStride,
+ &sFeatureSearchIn)) {
+ MotionEstimateFeatureFullSearch (sFeatureSearchIn, uiMaxSearchPoint, pMe);
+ }
pSlice->uiSliceFMECostDown -= pMe->uiSadCost;
}
}