diff --git a/codec/encoder/core/inc/picture.h b/codec/encoder/core/inc/picture.h index 57b27f14..053bee4a 100644 --- a/codec/encoder/core/inc/picture.h +++ b/codec/encoder/core/inc/picture.h @@ -68,7 +68,6 @@ typedef struct TagFeatureSearchPreparation{ int32_t iHighFreMbCount; }SFeatureSearchPreparation;//maintain only one - /* * Reconstructed Picture definition * It is used to express reference picture, also consequent reconstruction picture for output @@ -108,6 +107,9 @@ typedef struct TagPicture { uint8_t uiTemporalId; uint8_t uiSpatialId; int32_t iFrameAverageQp; + + /*******************************for screen reference frames****************************/ + SScreenBlockFeatureStorage* pScreenBlockFeatureStorage; } SPicture; /* diff --git a/codec/encoder/core/inc/picture_handle.h b/codec/encoder/core/inc/picture_handle.h index 21e4e17c..59126991 100644 --- a/codec/encoder/core/inc/picture_handle.h +++ b/codec/encoder/core/inc/picture_handle.h @@ -46,13 +46,13 @@ namespace WelsSVCEnc { /*! * \brief alloc picture pData with borders for each plane based width and height of picture - * \param cx width of picture in pixels - * \param cy height of picture in pixels - * \param need_data need pData allocation - * \pram need_expand need borders expanding + * \param kiWidth width of picture in pixels + * \param kiHeight height of picture in pixels + * \param bNeedMbInfo need pData allocation + * \pram iNeedFeatureStorage need storage for FME * \return successful if effective picture pointer returned, otherwise failed with NULL */ -SPicture* AllocPicture (CMemoryAlign* pMa, const int32_t kiWidth, const int32_t kiHeight, bool bNeedMbInfo); +SPicture* AllocPicture (CMemoryAlign* pMa, const int32_t kiWidth, const int32_t kiHeight, bool bNeedMbInfo, int32_t iNeedFeatureStorage); /*! * \brief free picture pData planes diff --git a/codec/encoder/core/inc/svc_motion_estimate.h b/codec/encoder/core/inc/svc_motion_estimate.h index 60daf79c..72de9329 100644 --- a/codec/encoder/core/inc/svc_motion_estimate.h +++ b/codec/encoder/core/inc/svc_motion_estimate.h @@ -54,8 +54,7 @@ namespace WelsSVCEnc { #define EXPANDED_MV_RANGE (504) //=512-8 rather than 511 to sacrifice same edge point but save complexity in assemblys #define EXPANDED_MVD_RANGE ((504+1)<<1) -enum -{ +enum { ME_DIA = 0x01, // LITTLE DIAMOND= 0x01 ME_CROSS = 0x02, // CROSS= 0x02 ME_FME = 0x04, // FME = 0x04 @@ -229,6 +228,9 @@ void SumOf8x8BlockOfFrame_c(uint8_t *pRefPicture, const int32_t kiWidth, const i uint16_t* pFeatureOfBlock, uint32_t pTimesOfFeatureValue[]); void SumOf16x16BlockOfFrame_c(uint8_t *pRefPicture, const int32_t kiWidth, const int32_t kiHeight, const int32_t kiRefStride, uint16_t* pFeatureOfBlock, uint32_t pTimesOfFeatureValue[]); +int32_t RequestScreenBlockFeatureStorage( CMemoryAlign *pMa, const int32_t kiFrameWidth, const int32_t kiFrameHeight, const int32_t iNeedFeatureStorage, + SScreenBlockFeatureStorage* pScreenBlockFeatureStorage); +int32_t ReleaseScreenBlockFeatureStorage( CMemoryAlign *pMa, SScreenBlockFeatureStorage* pScreenBlockFeatureStorage ); //inline functions inline void SetMvWithinIntegerMvRange( const int32_t kiMbWidth, const int32_t kiMbHeight, const int32_t kiMbX, const int32_t kiMbY, const int32_t kiMaxMvRange, diff --git a/codec/encoder/core/inc/wels_func_ptr_def.h b/codec/encoder/core/inc/wels_func_ptr_def.h index b77a2174..7cbd528b 100644 --- a/codec/encoder/core/inc/wels_func_ptr_def.h +++ b/codec/encoder/core/inc/wels_func_ptr_def.h @@ -138,14 +138,14 @@ typedef uint32_t (*PSampleSadHor8Func)( uint8_t*, int32_t, uint8_t*, int32_t, ui typedef void (*PMotionSearchFunc) (SWelsFuncPtrList* pFuncList, void* pCurDqLayer, void* pMe, void* pSlice); typedef void (*PSearchMethodFunc) (SWelsFuncPtrList* pFuncList, void* pMe, void* pSlice, const int32_t kiEncStride, const int32_t kiRefStride); -typedef void (*PCalculateSatdFunc) ( PSampleSadSatdCostFunc pSatd, void * vpMe, const int32_t kiEncStride, const int32_t kiRefStride); +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); -typedef void (*PLineFullSearchFunc) ( void *pFunc, void *vpMe, - uint16_t* pMvdTable, const int32_t kiFixedMvd, - const int32_t kiEncStride, const int32_t kiRefStride, - const int32_t kiMinPos, const int32_t kiMaxPos, +typedef void (*PLineFullSearchFunc) ( void *pFunc, void *vpMe, + uint16_t* pMvdTable, const int32_t kiFixedMvd, + const int32_t kiEncStride, const int32_t kiRefStride, + const int32_t kiMinPos, const int32_t kiMaxPos, const bool bVerticalSearch ); typedef void (*PCalculateBlockFeatureOfFrame)(uint8_t *pRef, const int32_t kiWidth, const int32_t kiHeight, const int32_t kiRefStride, uint16_t* pFeatureOfBlock, uint32_t pTimesOfFeatureValue[]); diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index a61583cb..21863925 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -707,7 +707,12 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) { pParam = (*ppCtx)->pSvcParam; iDlayerCount = pParam->iSpatialLayerNum; iNumRef = pParam->iNumRefFrame; -// highest_layers_in_temporal = 1 + WELS_MAX(pParam->iDecompStages, 1); + + const int32_t kiFeatureStrategyIndex = 0; + const int32_t kiMe16x16 = ME_DIA_CROSS; + const int32_t kiMe8x8 = ME_DIA_CROSS_FME; + const int32_t kiNeedFeatureStorage = (pParam->iUsageType != SCREEN_CONTENT_REAL_TIME)?0: + ((kiFeatureStrategyIndex<<16) + ((kiMe16x16 & 0x00FF)<<8) + (kiMe8x8 & 0x00FF)); iDlayerIndex = 0; while (iDlayerIndex < iDlayerCount) { @@ -727,9 +732,8 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) { // pRef list pRefList = (SRefList*)pMa->WelsMallocz (sizeof (SRefList), "pRefList"); WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pRefList), FreeMemorySvc (ppCtx)) - do { - pRefList->pRef[i] = AllocPicture (pMa, kiWidth, kiHeight, true); // to use actual size of current layer + pRefList->pRef[i] = AllocPicture (pMa, kiWidth, kiHeight, true, kiNeedFeatureStorage); // to use actual size of current layer WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pRefList->pRef[i]), FreeMemorySvc (ppCtx)) ++ i; } while (i < 1 + iNumRef); diff --git a/codec/encoder/core/src/picture_handle.cpp b/codec/encoder/core/src/picture_handle.cpp index 29c612a7..7dffc218 100644 --- a/codec/encoder/core/src/picture_handle.cpp +++ b/codec/encoder/core/src/picture_handle.cpp @@ -37,6 +37,7 @@ * *************************************************************************************/ #include "picture_handle.h" +#include "svc_motion_estimate.h" namespace WelsSVCEnc { /*! @@ -47,7 +48,8 @@ namespace WelsSVCEnc { * \pram need_expand need borders expanding * \return successful if effective picture pointer returned, otherwise failed with NULL */ -SPicture* AllocPicture (CMemoryAlign* pMa, const int32_t kiWidth , const int32_t kiHeight, bool bNeedMbInfo) { +SPicture* AllocPicture (CMemoryAlign* pMa, const int32_t kiWidth , const int32_t kiHeight, + bool bNeedMbInfo, int32_t iNeedFeatureStorage) { SPicture* pPic = NULL; int32_t iPicWidth = 0; int32_t iPicHeight = 0; @@ -107,6 +109,15 @@ SPicture* AllocPicture (CMemoryAlign* pMa, const int32_t kiWidth , const int32_t WELS_VERIFY_RETURN_PROC_IF (NULL, NULL == pPic->pMbSkipSad, FreePicture (pMa, &pPic)); } + if (iNeedFeatureStorage) { + pPic->pScreenBlockFeatureStorage = static_cast (pMa->WelsMallocz (sizeof (SScreenBlockFeatureStorage), "pScreenBlockFeatureStorage")); + int32_t iReturn = RequestScreenBlockFeatureStorage(pMa, kiWidth, kiHeight, iNeedFeatureStorage, + pPic->pScreenBlockFeatureStorage ); + + WELS_VERIFY_RETURN_PROC_IF (NULL, ENC_RETURN_SUCCESS != iReturn, FreePicture (pMa, &pPic)); + } else { + pPic->pScreenBlockFeatureStorage = NULL; + } return pPic; } @@ -126,10 +137,10 @@ void FreePicture (CMemoryAlign* pMa, SPicture** ppPic) { pPic->pBuffer = NULL; pPic->pData[0] = pPic->pData[1] = - pPic->pData[2] = NULL; + pPic->pData[2] = NULL; pPic->iLineSize[0] = pPic->iLineSize[1] = - pPic->iLineSize[2] = 0; + pPic->iLineSize[2] = 0; pPic->iWidthInPixel = 0; pPic->iHeightInPixel = 0; @@ -157,6 +168,13 @@ void FreePicture (CMemoryAlign* pMa, SPicture** ppPic) { pMa->WelsFree (pPic->pMbSkipSad, "pPic->pMbSkipSad"); pPic->pMbSkipSad = NULL; } + + if (pPic->pScreenBlockFeatureStorage) { + ReleaseScreenBlockFeatureStorage(pMa, pPic->pScreenBlockFeatureStorage); + pMa->WelsFree (pPic->pScreenBlockFeatureStorage, "pPic->pScreenBlockFeatureStorage"); + pPic->pScreenBlockFeatureStorage = NULL; + } + pMa->WelsFree (*ppPic, "pPic"); *ppPic = NULL; } diff --git a/codec/encoder/core/src/svc_motion_estimate.cpp b/codec/encoder/core/src/svc_motion_estimate.cpp index 72e98273..2cfc526a 100644 --- a/codec/encoder/core/src/svc_motion_estimate.cpp +++ b/codec/encoder/core/src/svc_motion_estimate.cpp @@ -96,9 +96,9 @@ void WelsInitMeFunc( SWelsFuncPtrList* pFuncList, uint32_t uiCpuFlag, bool bScre */ void WelsMotionEstimateSearch (SWelsFuncPtrList* pFuncList, void* pLplayer, void* pLpme, void* pLpslice) { - SDqLayer* pCurDqLayer = (SDqLayer*)pLplayer; - SWelsME* pMe = (SWelsME*)pLpme; - SSlice* pSlice = (SSlice*)pLpslice; + SDqLayer* pCurDqLayer = (SDqLayer*)pLplayer; + SWelsME* pMe = (SWelsME*)pLpme; + SSlice* pSlice = (SSlice*)pLpslice; const int32_t kiStrideEnc = pCurDqLayer->iEncStride[0]; const int32_t kiStrideRef = pCurDqLayer->pRefPic->iLineSize[0]; @@ -237,8 +237,8 @@ bool WelsMeSadCostSelect (int32_t* iSadCost, const uint16_t* kpMvdCost, int32_t* void WelsDiamondSearch (SWelsFuncPtrList* pFuncList, void* pLpme, void* pLpslice, const int32_t kiStrideEnc, const int32_t kiStrideRef) { - SWelsME* pMe = (SWelsME*)pLpme; - PSample4SadCostFunc pSad = pFuncList->sSampleDealingFuncs.pfSample4Sad[pMe->uiBlockSize]; + SWelsME* pMe = (SWelsME*)pLpme; + PSample4SadCostFunc pSad = pFuncList->sSampleDealingFuncs.pfSample4Sad[pMe->uiBlockSize]; uint8_t* pFref = pMe->pRefMb; uint8_t* const kpEncMb = pMe->pEncMb; @@ -542,18 +542,19 @@ int32_t ReleaseFeatureSearchPreparation( CMemoryAlign *pMa, uint16_t*& pFeatureO } return ENC_RETURN_UNEXPECTED; } -int32_t RequestScreenBlockFeatureStorage( CMemoryAlign *pMa, const int32_t kiFeatureStrategyIndex, - const int32_t kiFrameWidth, const int32_t kiFrameHeight, const int32_t kiMe16x16, const int32_t kiMe8x8, - SScreenBlockFeatureStorage* pScreenBlockFeatureStorage) { -#define LIST_SIZE_SUM_16x16 0x0FF01 //(256*255+1) -#define LIST_SIZE_SUM_8x8 0x03FC1 //(64*255+1) - if (((kiMe8x8&ME_FME)==ME_FME) && ((kiMe16x16&ME_FME)==ME_FME)) { +int32_t RequestScreenBlockFeatureStorage( CMemoryAlign *pMa, const int32_t kiFrameWidth, const int32_t kiFrameHeight, const int32_t iNeedFeatureStorage, + SScreenBlockFeatureStorage* pScreenBlockFeatureStorage) { + + const int32_t kiFeatureStrategyIndex = iNeedFeatureStorage>>16; + const int32_t kiMe8x8FME = iNeedFeatureStorage & 0x0000FF & ME_FME; + const int32_t kiMe16x16FME = ((iNeedFeatureStorage & 0x00FF00)>>8) & ME_FME; + if ((kiMe8x8FME==ME_FME) && (kiMe16x16FME==ME_FME)) { return ENC_RETURN_UNSUPPORTED_PARA; //the following memory allocation cannot support when FME at both size } - const bool bIsBlock8x8 = ((kiMe8x8 & ME_FME)==ME_FME); + const bool bIsBlock8x8 = (kiMe8x8FME==ME_FME); const int32_t kiMarginSize = bIsBlock8x8?8:16; const int32_t kiFrameSize = (kiFrameWidth-kiMarginSize) * (kiFrameHeight-kiMarginSize); const int32_t kiListSize = (0==kiFeatureStrategyIndex)?(bIsBlock8x8 ? LIST_SIZE_SUM_8x8 : LIST_SIZE_SUM_16x16):256; @@ -749,6 +750,7 @@ void SaveFeatureSearchOut( const SMVUnitXY sBestMv, const uint32_t uiBestSadCost pFeatureSearchOut->uiBestSadCost = uiBestSadCost; pFeatureSearchOut->pBestRef = pRef; } + bool FeatureSearchOne( SFeatureSearchIn &sFeatureSearchIn, const int32_t iFeatureDifference, const uint32_t kuiExpectedSearchTimes, SFeatureSearchOut* pFeatureSearchOut) { const int32_t iFeatureOfRef = (sFeatureSearchIn.iFeatureOfCurrent + iFeatureDifference); @@ -819,6 +821,7 @@ bool FeatureSearchOne( SFeatureSearchIn &sFeatureSearchIn, const int32_t iFeatur return (i < iSearchTimesx2); } + void MotionEstimateFeatureFullSearch( SFeatureSearchIn &sFeatureSearchIn, const uint32_t kuiMaxSearchPoint, SWelsME* pMe) { @@ -840,8 +843,8 @@ void MotionEstimateFeatureFullSearch( SFeatureSearchIn &sFeatureSearchIn, // Search function options ///////////////////////// void WelsDiamondCrossSearch(SWelsFuncPtrList *pFunc, void* vpMe, void* vpSlice, const int32_t kiEncStride, const int32_t kiRefStride) { - SWelsME* pMe = static_cast(vpMe); - SSlice* pSlice = static_cast(vpSlice); + SWelsME* pMe = static_cast(vpMe); + SSlice* pSlice = static_cast(vpSlice); // Step 1: diamond search WelsDiamondSearch(pFunc, vpMe, vpSlice, kiEncStride, kiRefStride); @@ -854,8 +857,8 @@ void WelsDiamondCrossSearch(SWelsFuncPtrList *pFunc, void* vpMe, void* vpSlice, } } void WelsDiamondCrossFeatureSearch(SWelsFuncPtrList *pFunc, void* vpMe, void* vpSlice, const int32_t kiEncStride, const int32_t kiRefStride) { - SWelsME* pMe = static_cast(vpMe); - SSlice* pSlice = static_cast(vpSlice); + SWelsME* pMe = static_cast(vpMe); + SSlice* pSlice = static_cast(vpSlice); // Step 1: diamond search + cross WelsDiamondCrossSearch(pFunc, pMe, pSlice, kiEncStride, kiRefStride); @@ -875,5 +878,6 @@ void WelsDiamondCrossFeatureSearch(SWelsFuncPtrList *pFunc, void* vpMe, void* vp pSlice->uiSliceFMECostDown -= pMe->uiSadCost; } } + } // namespace WelsSVCEnc diff --git a/codec/encoder/core/src/wels_preprocess.cpp b/codec/encoder/core/src/wels_preprocess.cpp index 62881c6d..c0ef9492 100644 --- a/codec/encoder/core/src/wels_preprocess.cpp +++ b/codec/encoder/core/src/wels_preprocess.cpp @@ -134,7 +134,7 @@ int32_t CWelsPreProcess::AllocSpatialPictures (sWelsEncCtx* pCtx, SWelsSvcCoding uint8_t i = 0; do { - SPicture* pPic = AllocPicture (pMa, kiPicWidth, kiPicHeight, false); + SPicture* pPic = AllocPicture (pMa, kiPicWidth, kiPicHeight, false, 0); WELS_VERIFY_RETURN_IF (1, (NULL == pPic)) m_pSpatialPic[iDlayerIndex][i] = pPic; ++ i; @@ -435,7 +435,7 @@ int32_t WelsInitScaledPic (SWelsSvcCodingParam* pParam, Scaled_Picture* pScal bool bInputPicNeedScaling = JudgeNeedOfScaling (pParam, pScaledPicture); if (bInputPicNeedScaling) { pScaledPicture->pScaledInputPicture = AllocPicture (pMemoryAlign, pParam->SUsedPicRect.iWidth, - pParam->SUsedPicRect.iHeight, false); + pParam->SUsedPicRect.iHeight, false, 0); if (pScaledPicture->pScaledInputPicture == NULL) return -1; }