From 80ae4cb7d8cbf7503b03dada6161ca79469fa893 Mon Sep 17 00:00:00 2001 From: sijchen Date: Tue, 13 May 2014 16:47:18 +0800 Subject: [PATCH] add me function pointers for screen contents --- codec/encoder/core/inc/svc_motion_estimate.h | 10 ++- codec/encoder/core/src/encoder_ext.cpp | 65 +++++++++++++++---- codec/encoder/core/src/svc_base_layer_md.cpp | 7 ++ .../encoder/core/src/svc_motion_estimate.cpp | 54 +++++++++------ 4 files changed, 101 insertions(+), 35 deletions(-) diff --git a/codec/encoder/core/inc/svc_motion_estimate.h b/codec/encoder/core/inc/svc_motion_estimate.h index f39898e3..680cb5d7 100644 --- a/codec/encoder/core/inc/svc_motion_estimate.h +++ b/codec/encoder/core/inc/svc_motion_estimate.h @@ -90,6 +90,8 @@ typedef struct TagWelsME { SMVUnitXY sMvBase; SMVUnitXY sDirectionalMv; + SScreenBlockFeatureStorage* pRefFeatureStorage; + /* output */ SMVUnitXY sMv; } SWelsME; @@ -220,7 +222,10 @@ void HorizontalFullSearchUsingSSE41 (SWelsFuncPtrList* pFuncList, SWelsME* pMe, 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) @@ -256,6 +261,9 @@ void PerformFMEPreprocess (SWelsFuncPtrList* pFunc, SPicture* pRef, uint16_t* pF 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, const int32_t kiMbY, diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index 82a02f32..bf7508e2 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -2428,6 +2428,36 @@ static inline void SetNormalCodingFunc (SWelsFuncPtrList* pFuncList) { 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) { @@ -2465,13 +2495,19 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) { 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 (pCtx->pVaa); @@ -2491,8 +2527,11 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) { } //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 @@ void PreprocessSliceCoding (sWelsEncCtx* pCtx) { } 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; } } } diff --git a/codec/encoder/core/src/svc_base_layer_md.cpp b/codec/encoder/core/src/svc_base_layer_md.cpp index f3d2f94b..ab298377 100644 --- a/codec/encoder/core/src/svc_base_layer_md.cpp +++ b/codec/encoder/core/src/svc_base_layer_md.cpp @@ -971,6 +971,7 @@ void WelsMdIntraMb (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SMB* pCurMb, SMbCach } 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 @@ static inline void InitMe (const SWelsMD& sWelsMd, const int32_t iBlockSize, uin 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 @@ int32_t WelsMdP16x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWe 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 @@ int32_t WelsMdP16x8 (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SWelsMD* pW 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 @@ int32_t WelsMdP8x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurLayer, SWelsMD* pWel 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 @@ int32_t WelsMdP8x8 (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SWelsMD* pWe 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; diff --git a/codec/encoder/core/src/svc_motion_estimate.cpp b/codec/encoder/core/src/svc_motion_estimate.cpp index d7414c18..c388ddbe 100644 --- a/codec/encoder/core/src/svc_motion_estimate.cpp +++ b/codec/encoder/core/src/svc_motion_estimate.cpp @@ -492,8 +492,8 @@ void LineFullSearch_c (SWelsFuncPtrList* pFuncList, SWelsME* pMe, } } -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,13 +709,18 @@ void FillQpelLocationByFeatureValue_c (uint16_t* pFeatureOfBlock, const int32_t } } -void CalculateFeatureOfBlock (SWelsFuncPtrList* pFunc, SPicture* pRef, +bool CalculateFeatureOfBlock (SWelsFuncPtrList* pFunc, SPicture* pRef, SScreenBlockFeatureStorage* pScreenBlockFeatureStorage) { uint16_t* pFeatureOfBlock = pScreenBlockFeatureStorage->pFeatureOfBlockPointer; uint32_t* pTimesOfFeatureValue = pScreenBlockFeatureStorage->pTimesOfFeatureValue; 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 @@ void CalculateFeatureOfBlock (SWelsFuncPtrList* pFunc, SPicture* pRef, //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 @@ void SetFeatureSearchIn (SWelsFuncPtrList* pFunc, const SWelsME& sMe, 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 @@ void WelsDiamondCrossSearch (SWelsFuncPtrList* pFunc, SWelsME* pMe, SSlice* pSli 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 @@ void WelsDiamondCrossFeatureSearch (SWelsFuncPtrList* pFunc, SWelsME* pMe, SSlic 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; } }