ref: cf2cf9efd9b8fee1a288f41e10961904cb923185
parent: 6ae38da3ab37a3708b5fdc088ff1b3494ac027d3
author: Sijia Chen <[email protected]>
date: Fri Sep 26 12:40:19 EDT 2014
add basic strategy for lossy+no LTR route
--- a/codec/encoder/core/inc/ref_list_mgr_svc.h
+++ b/codec/encoder/core/inc/ref_list_mgr_svc.h
@@ -98,7 +98,7 @@
*/
void WelsMarkPic (void* pCtx);
-void InitRefListMgrFunc (SWelsFuncPtrList* pFuncList, const bool bScreenContent);
+void InitRefListMgrFunc (SWelsFuncPtrList* pFuncList, const bool bEnableLongTermReference, const bool bScreenContent);
#ifdef LONG_TERM_REF_DUMP
void DumpRef (sWelsEncCtx* ctx);
--- a/codec/encoder/core/inc/wels_func_ptr_def.h
+++ b/codec/encoder/core/inc/wels_func_ptr_def.h
@@ -196,6 +196,7 @@
typedef void (*PMarkPicFunc) (void* pCtx);
typedef bool (*PUpdateRefListFunc) (void* pCtx);
typedef void (*PEndofUpdateRefListFunc) (void* pCtx);
+typedef void (*PAfterBuildRefListFunc) (void* pCtx);
typedef int32_t (*PCavlcParamCalFunc) (int16_t* pCoff, uint8_t* pRun, int16_t* pLevel, int32_t* pTotalCoeffs,
int32_t iEndIdx);
@@ -293,6 +294,7 @@
PMarkPicFunc pMarkPic;
PUpdateRefListFunc pUpdateRefList;
PEndofUpdateRefListFunc pEndofUpdateRefList;
+ PAfterBuildRefListFunc pAfterBuildRefList;
PCavlcParamCalFunc pfCavlcParamCal;
};
--- a/codec/encoder/core/inc/wels_preprocess.h
+++ b/codec/encoder/core/inc/wels_preprocess.h
@@ -109,6 +109,7 @@
SRefInfoParam sVaaStrBestRefCandidate[MAX_REF_PIC_COUNT]; //TOP3_BEST_REF_NO_TID
int32_t iNumOfAvailableRef;
+ int32_t iVaaBestRefFrameNum;
uint8_t* pVaaBestBlockStaticIdc;//pointer
uint8_t* pVaaBlockStaticIdc[16];//real memory,
} SVAAFrameInfoExt;
@@ -129,6 +130,7 @@
int32_t GetRefFrameInfo (int32_t iRefIdx, SPicture*& pRefOri);
void AnalyzePictureComplexity (sWelsEncCtx* pCtx, SPicture* pCurPicture, SPicture* pRefPicture,
const int32_t kiDependencyId, const bool kbCalculateBGD);
+ int32_t UpdateBlockIdcForScreen (uint8_t* pCurBlockStaticPointer, const SPicture* kpRefPic, const SPicture* kpSrcPic);
private:
int32_t WelsPreprocessCreate();
@@ -158,6 +160,8 @@
ESceneChangeIdc DetectSceneChangeScreen (sWelsEncCtx* pCtx, SPicture* pCurPicture);
void InitPixMap (const SPicture* pPicture, SPixMap* pPixMap);
+ void GetAvailableRefListLosslessScreenRefSelection (SPicture** pSrcPicList, uint8_t iCurTid, const int32_t iClosestLtrFrameNum,
+ SRefInfoParam* pAvailableRefList, int32_t& iAvailableRefNum, int32_t& iAvailableSceneRefNum);
void GetAvailableRefList (SPicture** pSrcPicList, uint8_t iCurTid, const int32_t iClosestLtrFrameNum,
SRefInfoParam* pAvailableRefList, int32_t& iAvailableRefNum, int32_t& iAvailableSceneRefNum);
void InitRefJudgement (SRefJudgement* pRefJudgement);
--- a/codec/encoder/core/src/encoder.cpp
+++ b/codec/encoder/core/src/encoder.cpp
@@ -218,7 +218,9 @@
WelsBlockFuncInit (&pFuncList->pfSetNZCZero, uiCpuFlag);
InitFillNeighborCacheInterFunc (pFuncList, pParam->bEnableBackgroundDetection);
- InitRefListMgrFunc (pFuncList, bScreenContent);
+
+ InitRefListMgrFunc (pFuncList, pParam->bEnableLongTermReference, bScreenContent);
+
return iReturn;
}
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -196,6 +196,12 @@
WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(),Invalid usage type = %d", pCodingParam->iUsageType);
return ENC_RETURN_UNSUPPORTED_PARA;
}
+ if ((pCodingParam->iUsageType == SCREEN_CONTENT_REAL_TIME) && (!pCodingParam->bIsLosslessLink
+ && pCodingParam->bEnableLongTermReference)) {
+ WelsLog (pLogCtx, WELS_LOG_WARNING,
+ "ParamValidationExt(), setting lossy link for LTR under screen, which is not supported yet! Auto disabled LTR!");
+ pCodingParam->bEnableLongTermReference = false;
+ }
if (pCodingParam->iSpatialLayerNum < 1 || pCodingParam->iSpatialLayerNum > MAX_DEPENDENCY_LAYER) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "ParamValidationExt(), monitor invalid pCodingParam->iSpatialLayerNum: %d!",
pCodingParam->iSpatialLayerNum);
@@ -2593,7 +2599,8 @@
pFeatureSearchPreparation->pRefBlockFeature = pScreenBlockFeatureStorage;
if (pFeatureSearchPreparation->bFMESwitchFlag
&& !pScreenBlockFeatureStorage->bRefBlockFeatureCalculated) {
- PerformFMEPreprocess (pFuncList, pCurLayer->pRefOri[0], pFeatureSearchPreparation->pFeatureOfBlock,
+ SPicture* pRef = (pCtx->pSvcParam->bEnableLongTermReference ? pCurLayer->pRefOri[0] : pCurLayer->pRefPic);
+ PerformFMEPreprocess (pFuncList, pRef, pFeatureSearchPreparation->pFeatureOfBlock,
pScreenBlockFeatureStorage);
}
@@ -3163,6 +3170,9 @@
pFbi->eFrameType = videoFrameTypeIDR;
pCtx->iEncoderError = ENC_RETURN_CORRECTED;
return ENC_RETURN_CORRECTED;
+ }
+ if (pCtx->eSliceType != I_SLICE) {
+ pCtx->pFuncList->pAfterBuildRefList (pCtx);
}
#ifdef LONG_TERM_REF_DUMP
DumpRef (pCtx);
--- a/codec/encoder/core/src/ref_list_mgr_svc.cpp
+++ b/codec/encoder/core/src/ref_list_mgr_svc.cpp
@@ -624,6 +624,21 @@
return (pCtx->iNumRef0 > 0 || pCtx->eSliceType == I_SLICE) ? (true) : (false);
}
+static void UpdateBlockStatic (void* pEncCtx) {
+ sWelsEncCtx* pCtx = (sWelsEncCtx*)pEncCtx;
+ SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
+ assert (pCtx->iNumRef0 == 1); //multi-ref is not support yet?
+ for (int32_t idx = 0; idx < pCtx->iNumRef0; idx++) {
+ //TODO: we need to re-factor the source picture storage first,
+ //and then use original frame of the ref to do this calculation for better vaa algo implementation
+ SPicture* pRef = pCtx->pRefList0[idx];
+ if (pVaaExt->iVaaBestRefFrameNum != pRef->iFrameNum) {
+ //re-do the calculation
+ pCtx->pVpp->UpdateBlockIdcForScreen (pVaaExt->pVaaBestBlockStaticIdc, pRef, pCtx->pEncPic);
+ }
+ }
+}
+
/*
* update syntax for reference base related
*/
@@ -680,7 +695,7 @@
}
}
-static inline void UpdareOriginalPicInfo(SPicture* pOrigPic, SPicture* pReconPic) {
+static inline void UpdateOriginalPicInfo (SPicture* pOrigPic, SPicture* pReconPic) {
if (!pOrigPic)
return;
@@ -696,7 +711,7 @@
pOrigPic->iFrameAverageQp = pReconPic->iFrameAverageQp;
}
-static void UpdateSrcListLosslessScreenRefSelectionWithLtr(sWelsEncCtx* pCtx) {
+static void UpdateSrcListLosslessScreenRefSelectionWithLtr (sWelsEncCtx* pCtx) {
int32_t iDIdx = pCtx->uiDependencyId;
SPicture** pLongRefList = pCtx->ppRefPicListExt[iDIdx]->pLongRefList;
SPicture** pLongRefSrcList = &pCtx->pVpp->m_pSpatialPic[iDIdx][0];
@@ -711,16 +726,47 @@
WelsExchangeSpatialPictures (&pCtx->pVpp->m_pSpatialPic[iDIdx][0],
&pCtx->pVpp->m_pSpatialPic[iDIdx][1 + pCtx->pVaa->uiMarkLongTermPicIdx]);
}
-static void UpdateSrcPicList (void* pEncCtx) {
+
+static void UpdateSrcList (sWelsEncCtx* pCtx) {
+ int32_t iDIdx = pCtx->uiDependencyId;
+ SPicture** pShortRefList = pCtx->ppRefPicListExt[iDIdx]->pShortRefList;
+ const uint32_t kuiShortRefCount = pCtx->ppRefPicListExt[iDIdx]->uiShortRefCount;
+ SPicture** pRefSrcList = &pCtx->pVpp->m_pSpatialPic[iDIdx][0];
+
+ //pRefSrcList[0] is for current frame
+ if (pCtx->eSliceType == P_SLICE && pCtx->uiTemporalId != 0) {
+ for (int iRefIdx = kuiShortRefCount - 1; iRefIdx >= 0; --iRefIdx) {
+ WelsExchangeSpatialPictures (&pRefSrcList[iRefIdx + 1],
+ &pRefSrcList[iRefIdx]);
+ }
+ } else {
+ WelsExchangeSpatialPictures (&pRefSrcList[0], &pRefSrcList[1]);
+ for (int32_t i = MAX_SHORT_REF_COUNT - 1; i > 0 ; --i) {
+ if (pRefSrcList[i + 1] != NULL) {
+ SetUnref (pRefSrcList[i + 1]);
+ }
+ }
+ }
+}
+static void UpdateSrcPicListLosslessScreenRefSelectionWithLtr (void* pEncCtx) {
sWelsEncCtx* pCtx = (sWelsEncCtx*)pEncCtx;
int32_t iDIdx = pCtx->uiDependencyId;
//update info in src list
- UpdareOriginalPicInfo(pCtx->pEncPic, pCtx->pDecPic);
+ UpdateOriginalPicInfo (pCtx->pEncPic, pCtx->pDecPic);
PrefetchNextBuffer (pCtx);
UpdateSrcListLosslessScreenRefSelectionWithLtr (pCtx);
SetUnref (pCtx->pVpp->m_pSpatialPic[iDIdx][0]);
}
-
+
+static void UpdateSrcPicList (void* pEncCtx) {
+ sWelsEncCtx* pCtx = (sWelsEncCtx*)pEncCtx;
+ int32_t iDIdx = pCtx->uiDependencyId;
+ //update info in src list
+ UpdateOriginalPicInfo (pCtx->pEncPic, pCtx->pDecPic);
+ PrefetchNextBuffer (pCtx);
+ UpdateSrcList (pCtx);
+ SetUnref (pCtx->pVpp->m_pSpatialPic[iDIdx][0]);
+}
bool WelsUpdateRefListScreen (void* pEncCtx) {
sWelsEncCtx* pCtx = (sWelsEncCtx*)pEncCtx;
SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
@@ -908,13 +954,17 @@
pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount].iLongTermFrameIdx = pLtr->iCurLtrIdx;
pRefPicMark->SMmcoRef[pRefPicMark->uiMmcoCount++].iMmcoType = MMCO_LONG;
-
}
}
return;
}
-void InitRefListMgrFunc (SWelsFuncPtrList* pFuncList, const bool bScreenContent) {
- if (bScreenContent) {
+
+void DoNothing (void* pointer) {
+}
+
+void InitRefListMgrFunc (SWelsFuncPtrList* pFuncList, const bool bWithLtr, const bool bScreenContent) {
+ bool bLosslessScreenRefSelectionWithLtr = bWithLtr && bScreenContent;
+ if (bLosslessScreenRefSelectionWithLtr) {
pFuncList->pBuildRefList = WelsBuildRefListScreen;
pFuncList->pMarkPic = WelsMarkPicScreen;
pFuncList->pUpdateRefList = WelsUpdateRefListScreen;
@@ -924,6 +974,18 @@
pFuncList->pMarkPic = WelsMarkPic;
pFuncList->pUpdateRefList = WelsUpdateRefList;
pFuncList->pEndofUpdateRefList = PrefetchNextBuffer;
+ }
+
+ pFuncList->pAfterBuildRefList = DoNothing;
+ if (bScreenContent) {
+ if (bLosslessScreenRefSelectionWithLtr) {
+ pFuncList->pEndofUpdateRefList = UpdateSrcPicListLosslessScreenRefSelectionWithLtr;
+ } else {
+ pFuncList->pEndofUpdateRefList = UpdateSrcPicList;
+ pFuncList->pAfterBuildRefList = UpdateBlockStatic;
+ }
+ } else {
+ pFuncList->pEndofUpdateRefList = PrefetchNextBuffer;
}
}
} // namespace WelsEnc
--- a/codec/encoder/core/src/wels_preprocess.cpp
+++ b/codec/encoder/core/src/wels_preprocess.cpp
@@ -858,7 +858,8 @@
pPixMap->eFormat = VIDEO_FORMAT_I420;
}
-void CWelsPreProcess::GetAvailableRefList (SPicture** pSrcPicList, uint8_t iCurTid, const int32_t iClosestLtrFrameNum,
+void CWelsPreProcess::GetAvailableRefListLosslessScreenRefSelection (SPicture** pSrcPicList, uint8_t iCurTid,
+ const int32_t iClosestLtrFrameNum,
SRefInfoParam* pAvailableRefList, int32_t& iAvailableRefNum, int32_t& iAvailableSceneRefNum) {
SWelsSvcCodingParam* pSvcParam = m_pEncCtx->pSvcParam;
const int32_t iSourcePicNum = pSvcParam->iNumRefFrame;
@@ -907,6 +908,39 @@
}
+
+void CWelsPreProcess::GetAvailableRefList (SPicture** pSrcPicList, uint8_t iCurTid, const int32_t iClosestLtrFrameNum,
+ SRefInfoParam* pAvailableRefList, int32_t& iAvailableRefNum, int32_t& iAvailableSceneRefNum) {
+ SWelsSvcCodingParam* pSvcParam = m_pEncCtx->pSvcParam;
+ const int32_t iSourcePicNum = pSvcParam->iNumRefFrame;
+ if (0 >= iSourcePicNum) {
+ iAvailableRefNum = 0;
+ iAvailableSceneRefNum = 0;
+ return ;
+ }
+ SPicture* pRefPic = NULL;
+ uint8_t uiRefTid = 0;
+ iAvailableRefNum = 0;
+ iAvailableSceneRefNum = 0;
+
+ //the saving order will be depend on pSrcPicList
+ //TODO: use a frame_idx to find the closer ref in time distance, and correctly sort the ref list
+ for (int32_t i = iSourcePicNum - 1; i >= 0; --i) {
+ pRefPic = pSrcPicList[i];
+ if (NULL == pRefPic || !pRefPic->bUsedAsRef) {
+ continue;
+ }
+ uiRefTid = pRefPic->uiTemporalId;
+
+ if (uiRefTid <= iCurTid) {
+ pAvailableRefList[iAvailableRefNum].pRefPicture = pRefPic;
+ pAvailableRefList[iAvailableRefNum].iSrcListIdx = i + 1; //in SrcList, the idx 0 is reserved for CurPic
+ iAvailableRefNum ++;
+ }
+ }
+}
+
+
void CWelsPreProcess::InitRefJudgement (SRefJudgement* pRefJudgement) {
pRefJudgement->iMinFrameComplexity = INT_MAX;
pRefJudgement->iMinFrameComplexity08 = INT_MAX;
@@ -931,8 +965,7 @@
}
void CWelsPreProcess::SaveBestRefToLocal (SRefInfoParam* pRefPicInfo, const SSceneChangeResult& sSceneChangeResult,
SRefInfoParam* pRefSaved) {
- pRefSaved->iSrcListIdx = pRefPicInfo->iSrcListIdx;
- pRefSaved->bSceneLtrFlag = pRefPicInfo->bSceneLtrFlag;
+ memcpy (pRefSaved, pRefPicInfo, sizeof (SRefInfoParam));
pRefSaved->pBestBlockStaticIdc = sSceneChangeResult.pStaticBlockIdc;
}
@@ -987,8 +1020,14 @@
const uint8_t iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[m_pEncCtx->sSpatialIndexMap[0].iDid],
m_pEncCtx->iCodingIndex, pSvcParam->uiGopSize);
const int32_t iClosestLtrFrameNum = pCtx->pLtr[iTargetDid].iLastLtrIdx[iCurTid];//TBD
- GetAvailableRefList (pSrcPicList, iCurTid, iClosestLtrFrameNum, &sAvailableRefList[0], iAvailableRefNum,
- iAvailableSceneRefNum);
+ if (pSvcParam->bEnableLongTermReference) {
+ GetAvailableRefListLosslessScreenRefSelection (pSrcPicList, iCurTid, iClosestLtrFrameNum, &sAvailableRefList[0],
+ iAvailableRefNum,
+ iAvailableSceneRefNum);
+ } else {
+ GetAvailableRefList (pSrcPicList, iCurTid, iClosestLtrFrameNum, &sAvailableRefList[0], iAvailableRefNum,
+ iAvailableSceneRefNum);
+ }
//after this build, pAvailableRefList[idx].iSrcListIdx is the idx of the ref in h->spatial_pic
if (0 == iAvailableRefNum) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "SceneChangeDetect() iAvailableRefNum=0 but not I.");
@@ -1037,12 +1076,12 @@
const int32_t iSceneDetectIdc = sSceneChangeResult.eSceneChangeIdc;
const int32_t iMotionBlockNum = sSceneChangeResult.iMotionBlockNum;
- const bool bCurRefIsLtr = pRefPic->bIsSceneLTR;
+ const bool bCurRefIsSceneLtr = pRefPic->bIsSceneLTR;
const int32_t iRefPicAvQP = pRefPic->iFrameAverageQp;
//for scene change detection
iNumOfLargeChange += (static_cast<int32_t> (LARGE_CHANGED_SCENE == iSceneDetectIdc));
- iNumOfMediumChangeToLtr += (static_cast<int32_t> ((bCurRefIsLtr) && (iSceneDetectIdc != SIMILAR_SCENE)));
+ iNumOfMediumChangeToLtr += (static_cast<int32_t> ((bCurRefIsSceneLtr) && (iSceneDetectIdc != SIMILAR_SCENE)));
//for reference selection
//this judge can only be saved when iAvailableRefNum==1, which is very limit
@@ -1051,7 +1090,7 @@
SaveBestRefToJudgement (iRefPicAvQP, iFrameComplexity, &sLtrJudgement);
SaveBestRefToLocal (pRefPicInfo, sSceneChangeResult, &sLtrSaved);
}
- if (bCurRefIsLtr && JudgeBestRef (pRefPic, sSceneLtrJudgement, iFrameComplexity, bIsClosestLtrFrame)) {
+ if (bCurRefIsSceneLtr && JudgeBestRef (pRefPic, sSceneLtrJudgement, iFrameComplexity, bIsClosestLtrFrame)) {
SaveBestRefToJudgement (iRefPicAvQP, iFrameComplexity, &sSceneLtrJudgement);
SaveBestRefToLocal (pRefPicInfo, sSceneChangeResult, &sSceneLtrSaved);
}
@@ -1074,6 +1113,7 @@
pCtx->iCodingIndex);
SaveBestRefToVaa (sLtrSaved, & (pVaaExt->sVaaStrBestRefCandidate[0]));
+ pVaaExt->iVaaBestRefFrameNum = sLtrSaved.pRefPicture->iFrameNum;
pVaaExt->pVaaBestBlockStaticIdc = sLtrSaved.pBestBlockStaticIdc;
if (0 == iAvailableSceneRefNum) {
@@ -1118,6 +1158,27 @@
}
}
+
+int32_t CWelsPreProcess::UpdateBlockIdcForScreen (uint8_t* pCurBlockStaticPointer, const SPicture* kpRefPic,
+ const SPicture* kpSrcPic) {
+ int32_t iSceneChangeMethodIdx = METHOD_SCENE_CHANGE_DETECTION_SCREEN;
+ SSceneChangeResult sSceneChangeResult = {SIMILAR_SCENE, 0, 0, NULL};
+ sSceneChangeResult.pStaticBlockIdc = pCurBlockStaticPointer;
+ sSceneChangeResult.sScrollResult.bScrollDetectFlag = false;
+
+ SPixMap sSrcMap = { { 0 } };
+ SPixMap sRefMap = { { 0 } };
+ InitPixMap (kpSrcPic, &sSrcMap);
+ InitPixMap (kpRefPic, &sRefMap);
+
+ m_pInterfaceVp->Set (iSceneChangeMethodIdx, (void*) (&sSceneChangeResult));
+ int32_t iRet = m_pInterfaceVp->Process (iSceneChangeMethodIdx, &sSrcMap, &sRefMap);
+ if (iRet == 0) {
+ m_pInterfaceVp->Get (iSceneChangeMethodIdx, (void*)&sSceneChangeResult);
+ return 0;
+ }
+ return iRet;
+}
//TODO: may opti later
//TODO: not use this func?
--- a/test/api/encoder_test.cpp
+++ b/test/api/encoder_test.cpp
@@ -106,21 +106,22 @@
"res/Cisco_Absolute_Power_1280x720_30fps.yuv",
"68c3220e49b7a57d563faf7c99a870ab34a23400", CAMERA_VIDEO_REAL_TIME, 1280, 720, 30.0f, SM_SINGLE_SLICE, false, 4, false, false
},
+ // the following values may be adjusted for times since we start tuning the strategy
{
"res/CiscoVT2people_320x192_12fps.yuv",
- "030d0e2d742ac039c2ab6333fe7cb18623c0d283", SCREEN_CONTENT_REAL_TIME, 320, 192, 12.0f, SM_SINGLE_SLICE, false, 1, false, false
+ "3ce65d9c326657b845cd00b22ce76128c29f8347", SCREEN_CONTENT_REAL_TIME, 320, 192, 12.0f, SM_SINGLE_SLICE, false, 1, false, false
},
{
"res/CiscoVT2people_160x96_6fps.yuv",
- "40aa19d4b2684a59e689860d2a793876f33904f7", SCREEN_CONTENT_REAL_TIME, 160, 96, 6.0f, SM_SINGLE_SLICE, false, 1, false, false
+ "2b57e1cc7a4db6258116c302eada3bf870ee94a1", SCREEN_CONTENT_REAL_TIME, 160, 96, 6.0f, SM_SINGLE_SLICE, false, 1, false, false
},
{
"res/Static_152_100.yuv",
- "494068b59aa9ed9118a9f33174b732024effc870", SCREEN_CONTENT_REAL_TIME, 152, 100, 6.0f, SM_SINGLE_SLICE, false, 1, false, false
+ "bad065da4564d0580a1722d91463fa0f9fd947c8", SCREEN_CONTENT_REAL_TIME, 152, 100, 6.0f, SM_SINGLE_SLICE, false, 1, false, false
},
{
"res/Cisco_Absolute_Power_1280x720_30fps.yuv",
- "7a0be680c2c89cda208fb5890e64867f3787491e", SCREEN_CONTENT_REAL_TIME, 1280, 720, 30.0f, SM_DYN_SLICE, false, 1, false, false
+ "8ee6cd375b58e9877f6145fb72da844e65162b14", SCREEN_CONTENT_REAL_TIME, 1280, 720, 30.0f, SM_DYN_SLICE, false, 1, false, false
},
//for different strategy
{