Merge pull request #831 from sijchen/md_merge144

[Encoder ME] Add ME function assignment for Screen Content Coding
This commit is contained in:
huili2 2014-05-17 21:49:07 +08:00
commit 7f3f397706
4 changed files with 101 additions and 35 deletions

View File

@ -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,

View File

@ -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<SVAAFrameInfoExt*> (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;
}
}
}

View File

@ -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;

View File

@ -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;
}
}