ref: aed919a65aa73331a3c0e4c673f019659a138489
parent: 666e5d1290ff7bf0bdd7e152fadbdfc52e2f41cb
author: ruil2 <ruil2@cisco.com>
date: Mon Mar 31 13:14:00 EDT 2014
add scene change for screen content
--- a/codec/encoder/core/inc/encoder.h
+++ b/codec/encoder/core/inc/encoder.h
@@ -84,6 +84,8 @@
void InitFrameCoding (sWelsEncCtx* pEncCtx, const EVideoFrameType keFrameType);
EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum);
+
+int32_t GetTemporalLevel (SDLayerParam* fDlp, const int32_t kiFrameNum, const int32_t kiGopSize);
/*!
* \brief Dump reconstruction for dependency layer
*/
--- a/codec/encoder/core/inc/encoder_context.h
+++ b/codec/encoder/core/inc/encoder_context.h
@@ -89,7 +89,9 @@
int32_t iLTRMarkMode; // direct mark or delay mark
int32_t iLTRMarkSuccessNum; //successful marked num, for mark mode switch
int32_t iCurLtrIdx;// current int32_t term reference index to mark
- int32_t iLastLtrIdx;
+ int32_t iLastLtrIdx[MAX_TEMPORAL_LAYER_NUM];
+ int32_t iSceneLtrIdx;// related to Scene LTR, used by screen content
+
uint32_t uiLtrMarkInterval;// the interval from the last int32_t term pRef mark
bool bLTRMarkingFlag; //decide whether current frame marked as LTR
@@ -148,7 +150,7 @@
SRefList** ppRefPicListExt; // reference picture list for SVC
SPicture* pRefList0[16];
SLTRState* pLtr;//[MAX_DEPENDENCY_LAYER];
-
+ bool bCurFrameMarkedAsSceneLtr;
// Derived
int32_t iCodingIndex;
int32_t iFrameIndex; // count how many frames elapsed during coding context currently
--- a/codec/encoder/core/inc/picture.h
+++ b/codec/encoder/core/inc/picture.h
@@ -95,9 +95,11 @@
bool bUsedAsRef; //for pRef pic management
bool bIsLongRef; // long term reference frame flag //for pRef pic management
+ bool bIsSceneLTR; //long term reference & large scene change
uint8_t uiRecieveConfirmed;
uint8_t uiTemporalId;
uint8_t uiSpatialId;
+ int32_t iFrameAverageQp;
} SPicture;
/*
--- a/codec/encoder/core/inc/wels_preprocess.h
+++ b/codec/encoder/core/inc/wels_preprocess.h
@@ -62,8 +62,18 @@
typedef struct {- int32_t iBestRefSrcListIdx; //idx in h->spatial_pic[base_did];
- bool bSceneLtrFlag;
+ int32_t iMinFrameComplexity;
+ int32_t iMinFrameComplexity08;
+ int32_t iMinFrameComplexity11;
+
+ int32_t iMinFrameNumGap;
+ int32_t iMinFrameQp;
+}SRefJudgement;
+
+typedef struct {+ SPicture *pRefPicture;
+ int32_t iSrcListIdx; //idx in h->spatial_pic[base_did];
+ bool bSceneLtrFlag;
}SRefInfoParam;
typedef struct {@@ -100,8 +110,8 @@
SRefInfoParam sVaaStrBestRefCandidate[MAX_REF_PIC_COUNT];
int32_t iNumOfAvailableRef;
- int32_t *pVaaBestBlockStaticIdc;//pointer
- int32_t *pVaaBlockStaticIdc[16];//real memory,
+ uint8_t *pVaaBestBlockStaticIdc;//pointer
+ uint8_t *pVaaBlockStaticIdc[16];//real memory,
}SVAAFrameInfoExt;
class CWelsLib {@@ -162,7 +172,16 @@
const int32_t kiWidth, const int32_t kiHeight);
ESceneChangeIdc DetectSceneChangeScreen(sWelsEncCtx* pCtx,SPicture* pCurPicture);
- private:
+ void InitPixMap( const SPicture *pPicture, SPixMap *pPixMap );
+ void GetAvailableRefList(SPicture ** pSrcPicList,uint8_t iCurTid, const int32_t iClosestLtrFrameNum,
+ SRefInfoParam* pAvailableRefList, int32_t& iAvailableRefNum, int32_t& iAvailableSceneRefNum);
+ void InitRefJudgement( SRefJudgement *pRefJudgement );
+ bool JudgeBestRef(SPicture* pRefPic,const SRefJudgement& sRefJudgement, const int32_t iFrameComplexity, const bool bIsClosestLtrFrame);
+ void SaveBestRefToJudgement(const int32_t iRefPictureAvQP, const int32_t iComplexity, SRefJudgement* pRefJudgement);
+ void SaveBestRefToLocal(SRefInfoParam *pRefPicInfo,const SSceneChangeResult& sSceneChangeResult, SRefInfoParam* pRefSaved);
+ void SaveBestRefToVaa(SRefInfoParam& sRefSaved,SRefInfoParam* pVaaBestRef);
+
+private:
Scaled_Picture m_sScaledPicture;
SPicture* m_pLastSpatialPicture[MAX_DEPENDENCY_LAYER][2];
IWelsVP* m_pInterfaceVp;
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -2138,7 +2138,7 @@
/*!
* \brief get temporal level due to configuration and coding context
*/
-static inline int32_t GetTemporalLevel (SDLayerParam* fDlp, const int32_t kiFrameNum, const int32_t kiGopSize) {+int32_t GetTemporalLevel (SDLayerParam* fDlp, const int32_t kiFrameNum, const int32_t kiGopSize) {const int32_t kiCodingIdx = kiFrameNum & (kiGopSize - 1);
return fDlp->uiCodingIdx2TemporalId[kiCodingIdx];
--- a/codec/encoder/core/src/ref_list_mgr_svc.cpp
+++ b/codec/encoder/core/src/ref_list_mgr_svc.cpp
@@ -66,7 +66,7 @@
pLtr->bLTRMarkingFlag = false; //decide whether current frame marked as LTR
pLtr->bLTRMarkEnable = false; //when LTR is confirmed and the interval is no smaller than the marking period
pLtr->iCurLtrIdx = 0;
- pLtr->iLastLtrIdx = 0;
+ memset(&pLtr->iLastLtrIdx , 0 , sizeof(pLtr->iLastLtrIdx)) ;
pLtr->uiLtrMarkInterval = 0;
// LTR mark feedback
@@ -435,7 +435,11 @@
pLtr->bLTRMarkingFlag = true;
pLtr->bLTRMarkEnable = false;
pLtr->uiLtrMarkInterval = 0;
- pLtr->iLastLtrIdx = pLtr->iCurLtrIdx;
+ for(int32_t i = 0 ; i< MAX_TEMPORAL_LAYER_NUM; ++i){
+ if (pCtx->uiTemporalId<i || pCtx->uiTemporalId ==0){
+ pLtr->iLastLtrIdx[i] = pLtr->iCurLtrIdx;
+ }
+ }
} else {pLtr->bLTRMarkingFlag = false;
}
--- a/codec/encoder/core/src/wels_preprocess.cpp
+++ b/codec/encoder/core/src/wels_preprocess.cpp
@@ -44,6 +44,7 @@
#include "picture_handle.h"
#include "encoder_context.h"
#include "utils.h"
+#include "encoder.h"
namespace WelsSVCEnc {@@ -206,9 +207,9 @@
m_bInitDone = false;
m_pEncCtx = pEncCtx;
memset (&m_sScaledPicture, 0, sizeof (m_sScaledPicture));
- memset (m_pSpatialPic, 0, sizeof(m_pSpatialPic));
- memset (m_uiSpatialLayersInTemporal, 0, sizeof(m_uiSpatialLayersInTemporal));
- memset (m_uiSpatialPicNum, 0, sizeof(m_uiSpatialPicNum));
+ memset (m_pSpatialPic, 0, sizeof (m_pSpatialPic));
+ memset (m_uiSpatialLayersInTemporal, 0, sizeof (m_uiSpatialLayersInTemporal));
+ memset (m_uiSpatialPicNum, 0, sizeof (m_uiSpatialPicNum));
}
CWelsPreProcess::~CWelsPreProcess() {@@ -273,7 +274,7 @@
do {SPicture* pPic = AllocPicture (pMa, kiPicWidth, kiPicHeight, false);
- WELS_VERIFY_RETURN_IF(1, (NULL == pPic))
+ WELS_VERIFY_RETURN_IF (1, (NULL == pPic))
m_pSpatialPic[iDlayerIndex][i] = pPic;
++ i;
} while (i < kuiRefNumInTemporal);
@@ -371,17 +372,17 @@
return 0;
}
-int32_t CWelsPreProcess::UpdateSpatialPictures(sWelsEncCtx* pCtx, SWelsSvcCodingParam* pParam,
+int32_t CWelsPreProcess::UpdateSpatialPictures (sWelsEncCtx* pCtx, SWelsSvcCodingParam* pParam,
const int8_t iCurTid, const int32_t d_idx) {- if (iCurTid < m_uiSpatialLayersInTemporal[d_idx] - 1 || pParam->iDecompStages == 0){+ if (iCurTid < m_uiSpatialLayersInTemporal[d_idx] - 1 || pParam->iDecompStages == 0) { if ((iCurTid >= MAX_TEMPORAL_LEVEL) || (m_uiSpatialLayersInTemporal[d_idx] - 1 > MAX_TEMPORAL_LEVEL)) {- InitLastSpatialPictures(pCtx);
+ InitLastSpatialPictures (pCtx);
return 1;
}
if (pParam->bEnableLongTermReference && pCtx->bLongTermRefFlag[d_idx][iCurTid]) {SPicture* tmp = m_pSpatialPic[d_idx][m_uiSpatialLayersInTemporal[d_idx] + pCtx->pVaa->uiMarkLongTermPicIdx];
m_pSpatialPic[d_idx][m_uiSpatialLayersInTemporal[d_idx] + pCtx->pVaa->uiMarkLongTermPicIdx] =
- m_pSpatialPic[d_idx][iCurTid];
+ m_pSpatialPic[d_idx][iCurTid];
m_pSpatialPic[d_idx][iCurTid] = m_pSpatialPic[d_idx][m_uiSpatialLayersInTemporal[d_idx] - 1];
m_pSpatialPic[d_idx][m_uiSpatialLayersInTemporal[d_idx] - 1] = tmp;
pCtx->bLongTermRefFlag[d_idx][iCurTid] = false;
@@ -442,18 +443,16 @@
}
DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight);
- if (pSvcParam->bEnableSceneChangeDetect && !pCtx->pVaa->bIdrPeriodFlag){- if(pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME)
- {- pCtx->pVaa->eSceneChangeIdc = (pCtx->bEncCurFrmAsIdrFlag ? LARGE_CHANGED_SCENE: DetectSceneChangeScreen(pCtx,pDstPic));
- pCtx->pVaa->bSceneChangeFlag = ( LARGE_CHANGED_SCENE == pCtx->pVaa->eSceneChangeIdc);
- }
- else
- {- if((!pCtx->bEncCurFrmAsIdrFlag )&& ! (pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1))) {+ if (pSvcParam->bEnableSceneChangeDetect && !pCtx->pVaa->bIdrPeriodFlag) {+ if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {+ pCtx->pVaa->eSceneChangeIdc = (pCtx->bEncCurFrmAsIdrFlag ? LARGE_CHANGED_SCENE : DetectSceneChangeScreen (pCtx,
+ pDstPic));
+ pCtx->pVaa->bSceneChangeFlag = (LARGE_CHANGED_SCENE == pCtx->pVaa->eSceneChangeIdc);
+ } else {+ if ((!pCtx->bEncCurFrmAsIdrFlag) && ! (pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1))) {SPicture* pRefPic = pCtx->pLtr[iDependencyId].bReceivedT0LostFlag ?
- m_pSpatialPic[iDependencyId][m_uiSpatialLayersInTemporal[iDependencyId] +
- pCtx->pVaa->uiValidLongTermPicIdx] : m_pLastSpatialPicture[iDependencyId][0];
+ m_pSpatialPic[iDependencyId][m_uiSpatialLayersInTemporal[iDependencyId] +
+ pCtx->pVaa->uiValidLongTermPicIdx] : m_pLastSpatialPicture[iDependencyId][0];
pCtx->pVaa->bSceneChangeFlag = DetectSceneChange (pDstPic, pRefPic);
}
@@ -594,7 +593,7 @@
void CWelsPreProcess::BilateralDenoising (SPicture* pSrc, const int32_t kiWidth, const int32_t kiHeight) {int32_t iMethodIdx = METHOD_DENOISE;
SPixMap sSrcPixMap;
- memset (&sSrcPixMap, 0, sizeof(sSrcPixMap));
+ memset (&sSrcPixMap, 0, sizeof (sSrcPixMap));
sSrcPixMap.pPixel[0] = pSrc->pData[0];
sSrcPixMap.pPixel[1] = pSrc->pData[1];
sSrcPixMap.pPixel[2] = pSrc->pData[2];
@@ -615,8 +614,8 @@
SSceneChangeResult sSceneChangeDetectResult = { SIMILAR_SCENE };SPixMap sSrcPixMap;
SPixMap sRefPixMap;
- memset (&sSrcPixMap, 0, sizeof(sSrcPixMap));
- memset (&sRefPixMap, 0, sizeof(sRefPixMap));
+ memset (&sSrcPixMap, 0, sizeof (sSrcPixMap));
+ memset (&sRefPixMap, 0, sizeof (sRefPixMap));
sSrcPixMap.pPixel[0] = pCurPicture->pData[0];
sSrcPixMap.iSizeInBits = g_kiPixMapSizeInBits;
sSrcPixMap.iStride[0] = pCurPicture->iLineSize[0];
@@ -646,8 +645,8 @@
int32_t iRet = 0;
SPixMap sSrcPixMap;
SPixMap sDstPicMap;
- memset (&sSrcPixMap, 0, sizeof(sSrcPixMap));
- memset (&sDstPicMap, 0, sizeof(sDstPicMap));
+ memset (&sSrcPixMap, 0, sizeof (sSrcPixMap));
+ memset (&sDstPicMap, 0, sizeof (sDstPicMap));
sSrcPixMap.pPixel[0] = pSrc->pData[0];
sSrcPixMap.pPixel[1] = pSrc->pData[1];
sSrcPixMap.pPixel[2] = pSrc->pData[2];
@@ -695,8 +694,8 @@
int32_t iMethodIdx = METHOD_VAA_STATISTICS;
SPixMap sCurPixMap;
SPixMap sRefPixMap;
- memset (&sCurPixMap, 0, sizeof(sCurPixMap));
- memset (&sRefPixMap, 0, sizeof(sRefPixMap));
+ memset (&sCurPixMap, 0, sizeof (sCurPixMap));
+ memset (&sRefPixMap, 0, sizeof (sRefPixMap));
SVAACalcParam calc_param = {0};sCurPixMap.pPixel[0] = pCurPicture->pData[0];
@@ -741,8 +740,8 @@
int32_t iMethodIdx = METHOD_BACKGROUND_DETECTION;
SPixMap sSrcPixMap;
SPixMap sRefPixMap;
- memset (&sSrcPixMap, 0, sizeof(sSrcPixMap));
- memset (&sRefPixMap, 0, sizeof(sRefPixMap));
+ memset (&sSrcPixMap, 0, sizeof (sSrcPixMap));
+ memset (&sRefPixMap, 0, sizeof (sRefPixMap));
SBGDInterface BGDParam = {0};sSrcPixMap.pPixel[0] = pCurPicture->pData[0];
@@ -786,8 +785,8 @@
int32_t iMethodIdx = METHOD_ADAPTIVE_QUANT;
SPixMap pSrc;
SPixMap pRef;
- memset (&pSrc, 0, sizeof(pSrc));
- memset (&pRef, 0, sizeof(pRef));
+ memset (&pSrc, 0, sizeof (pSrc));
+ memset (&pRef, 0, sizeof (pRef));
int32_t iRet = 0;
pSrc.pPixel[0] = pCurPicture->pData[0];
@@ -876,8 +875,8 @@
int32_t iMethodIdx = METHOD_COMPLEXITY_ANALYSIS;
SPixMap sSrcPixMap;
SPixMap sRefPixMap;
- memset (&sSrcPixMap, 0, sizeof(SPixMap));
- memset (&sRefPixMap, 0, sizeof(SPixMap));
+ memset (&sSrcPixMap, 0, sizeof (SPixMap));
+ memset (&sRefPixMap, 0, sizeof (SPixMap));
int32_t iRet = 0;
sSrcPixMap.pPixel[0] = pCurPicture->pData[0];
@@ -902,31 +901,227 @@
}
-ESceneChangeIdc CWelsPreProcess::DetectSceneChangeScreen(sWelsEncCtx* pCtx,SPicture* pCurPicture)
-{-#define STATIC_SCENE_MOTION_RATIO 0.01f
- SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
- SVAAFrameInfoExt *pVaaExt = static_cast<SVAAFrameInfoExt *>(pCtx->pVaa);
- if ( NULL==pCtx || NULL == pVaaExt || NULL== pCurPicture)
- {- return LARGE_CHANGED_SCENE;
+void CWelsPreProcess::InitPixMap (const SPicture* pPicture, SPixMap* pPixMap) {+ pPixMap->pPixel[0] = pPicture->pData[0];
+ pPixMap->pPixel[1] = pPicture->pData[1];
+ pPixMap->pPixel[2] = pPicture->pData[2];
+ pPixMap->iSizeInBits = sizeof (uint8_t);
+ pPixMap->iStride[0] = pPicture->iLineSize[0];
+ pPixMap->iStride[1] = pPicture->iLineSize[1];
+ pPixMap->sRect.iRectWidth = pPicture->iWidthInPixel;
+ pPixMap->sRect.iRectHeight = pPicture->iHeightInPixel;
+
+ pPixMap->eFormat = VIDEO_FORMAT_I420;
+}
+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 ;
+ }
+ const bool bCurFrameMarkedAsSceneLtr = m_pEncCtx->bCurFrameMarkedAsSceneLtr;
+ SPicture* pRefPic = NULL;
+ uint8_t uiRefTid = 0;
+ bool bRefRealLtr = false;
+
+ iAvailableRefNum = 1; //zero is left for the closest frame
+ 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 || !pRefPic->bIsLongRef || (bCurFrameMarkedAsSceneLtr
+ && (!pRefPic->bIsSceneLTR))) {+ continue;
}
+ uiRefTid = pRefPic->uiTemporalId;
+ bRefRealLtr = pRefPic->bIsSceneLTR;
- const int32_t iTargetDid = pSvcParam->iSpatialLayerNum-1;
- if ( 0!= iTargetDid )
- {- return LARGE_CHANGED_SCENE;
+ if (bRefRealLtr || (0 == iCurTid && 0 == uiRefTid) || (uiRefTid < iCurTid)) {+ int32_t idx = (pRefPic->iLongTermPicNum == iClosestLtrFrameNum) ? (0) : (iAvailableRefNum++);
+ pAvailableRefList[idx].pRefPicture = pRefPic;
+ pAvailableRefList[idx].iSrcListIdx = i + 1; //in SrcList, the idx 0 is reserved for CurPic
+ iAvailableSceneRefNum += bRefRealLtr;
}
+ }
- ESceneChangeIdc iVaaFrameSceneChangeIdc = LARGE_CHANGED_SCENE;
+ if (pAvailableRefList[0].pRefPicture == NULL) {+ for (int32_t i = 1; i < iAvailableRefNum ; ++i) {+ pAvailableRefList[i - 1].pRefPicture = pAvailableRefList[i].pRefPicture;
+ pAvailableRefList[i - 1].iSrcListIdx = pAvailableRefList[i].iSrcListIdx;
+ }
- SPicture **pSrcPicList = &m_pSpatialPic[iTargetDid][1];
- if ( NULL==pSrcPicList )
- {- return LARGE_CHANGED_SCENE;
+ pAvailableRefList[iAvailableRefNum - 1].pRefPicture = NULL;
+ pAvailableRefList[iAvailableRefNum - 1].iSrcListIdx = 0;
+ --iAvailableRefNum;
+ }
+}
+
+
+void CWelsPreProcess::InitRefJudgement (SRefJudgement* pRefJudgement) {+ pRefJudgement->iMinFrameComplexity = INT_MAX;
+ pRefJudgement->iMinFrameComplexity08 = INT_MAX;
+ pRefJudgement->iMinFrameComplexity11 = INT_MAX;
+
+ pRefJudgement->iMinFrameNumGap = INT_MAX;
+ pRefJudgement->iMinFrameQp = INT_MAX;
+}
+bool CWelsPreProcess::JudgeBestRef (SPicture* pRefPic, const SRefJudgement& sRefJudgement,
+ const int32_t iFrameComplexity, const bool bIsClosestLtrFrame) {+ return (bIsClosestLtrFrame ? (iFrameComplexity < sRefJudgement.iMinFrameComplexity11) :
+ ((iFrameComplexity < sRefJudgement.iMinFrameComplexity08) || ((iFrameComplexity <= sRefJudgement.iMinFrameComplexity11)
+ && (pRefPic->iFrameAverageQp < sRefJudgement.iMinFrameQp))));
+}
+
+void CWelsPreProcess::SaveBestRefToJudgement (const int32_t iRefPictureAvQP, const int32_t iComplexity,
+ SRefJudgement* pRefJudgement) {+ pRefJudgement->iMinFrameQp = iRefPictureAvQP;
+ pRefJudgement->iMinFrameComplexity = iComplexity;
+ pRefJudgement->iMinFrameComplexity08 = static_cast<int32_t> (iComplexity * 0.8);
+ pRefJudgement->iMinFrameComplexity11 = static_cast<int32_t> (iComplexity * 1.1);
+}
+void CWelsPreProcess::SaveBestRefToLocal (SRefInfoParam* pRefPicInfo, const SSceneChangeResult& sSceneChangeResult,
+ SRefInfoParam* pRefSaved) {+ pRefSaved->iSrcListIdx = pRefPicInfo->iSrcListIdx;
+ pRefSaved->bSceneLtrFlag = pRefPicInfo->bSceneLtrFlag;
+}
+
+void CWelsPreProcess::SaveBestRefToVaa (SRefInfoParam& sRefSaved, SRefInfoParam* pVaaBestRef) {+ (*pVaaBestRef) = sRefSaved;
+}
+
+ESceneChangeIdc CWelsPreProcess::DetectSceneChangeScreen (sWelsEncCtx* pCtx, SPicture* pCurPicture) {+#define STATIC_SCENE_MOTION_RATIO 0.01f
+ SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
+ SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
+ if (NULL == pCtx || NULL == pVaaExt || NULL == pCurPicture) {+ return LARGE_CHANGED_SCENE;
+ }
+
+ const int32_t iTargetDid = pSvcParam->iSpatialLayerNum - 1;
+ if (0 != iTargetDid) {+ return LARGE_CHANGED_SCENE;
+ }
+
+ ESceneChangeIdc iVaaFrameSceneChangeIdc = LARGE_CHANGED_SCENE;
+ SPicture** pSrcPicList = &m_pSpatialPic[iTargetDid][1];
+ if (NULL == pSrcPicList) {+ return LARGE_CHANGED_SCENE;
+ }
+
+ SRefInfoParam sAvailableRefList[MAX_REF_PIC_COUNT] = {0};+ int32_t iAvailableRefNum = 0;
+ int32_t iAvailableSceneRefNum = 0;
+
+ int32_t iSceneChangeMethodIdx = METHOD_SCENE_CHANGE_DETECTION_SCREEN;
+ SSceneChangeResult sSceneChangeResult = {SIMILAR_SCENE, 0, 0, NULL};+
+ SPixMap sSrcMap = {0};+ SPixMap sRefMap = {0};+ SRefJudgement sLtrJudgement;
+ SRefJudgement sSceneLtrJudgement;
+ SRefInfoParam sLtrSaved = {0};+ SRefInfoParam sSceneLtrSaved = {0};+
+ int32_t iNumOfLargeChange = 0, iNumOfMediumChangeToLtr = 0;
+
+ bool bBestRefIsLtr = false, bIsClosestLtrFrame = false;
+ int32_t ret = 1, iScdIdx = 0, i = 0;
+
+ SPicture* pRefPic = NULL;
+ SRefInfoParam* pRefPicInfo = NULL;
+ uint8_t* pCurBlockStaticPointer = NULL;
+ uint8_t* pBestStrBlockStaticPointer = NULL;
+ uint8_t* pBestLtrBlockStaticPointer = NULL;
+
+ const int32_t iNegligibleMotionBlocks = (static_cast<int32_t> ((pCurPicture->iWidthInPixel >> 3) *
+ (pCurPicture->iHeightInPixel >> 3) * STATIC_SCENE_MOTION_RATIO));
+ 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);
+ //after this build, pAvailableRefList[idx].iSrcListIdx is the idx of the ref in h->spatial_pic
+ if (0 == iAvailableRefNum) {+ WelsLog (pCtx, WELS_LOG_ERROR, "SceneChangeDetect() iAvailableRefNum=0 but not I.\n");
+ return LARGE_CHANGED_SCENE;
+ }
+
+ InitPixMap (pCurPicture, &sSrcMap);
+ InitRefJudgement (&sLtrJudgement);
+ InitRefJudgement (&sSceneLtrJudgement);
+
+ for (iScdIdx = 0; iScdIdx < iAvailableRefNum; iScdIdx ++) {+ pCurBlockStaticPointer = pVaaExt->pVaaBlockStaticIdc[iScdIdx];
+ sSceneChangeResult.eSceneChangeIdc = SIMILAR_SCENE;
+ sSceneChangeResult.pStaticBlockIdc = pCurBlockStaticPointer;//
+
+ pRefPicInfo = & (sAvailableRefList[iScdIdx]);
+ assert (NULL != pRefPicInfo);
+ pRefPic = pRefPicInfo->pRefPicture;
+ InitPixMap (pRefPic, &sRefMap);
+
+ bIsClosestLtrFrame = (pRefPic->iLongTermPicNum == iClosestLtrFrameNum);
+
+ //TBD scrolling detection
+ m_pInterfaceVp->Set (iSceneChangeMethodIdx, (void*) (&sSceneChangeResult));
+ ret = m_pInterfaceVp->Process (iSceneChangeMethodIdx, &sSrcMap, &sRefMap);
+
+ if (ret == 0) {+ m_pInterfaceVp->Get (iSceneChangeMethodIdx, (void*)&sSceneChangeResult);
+
+ const int32_t iFrameComplexity = sSceneChangeResult.iFrameComplexity;
+ const int32_t iSceneDetectIdc = sSceneChangeResult.eSceneChangeIdc;
+ const int32_t iMotionBlockNum = sSceneChangeResult.iMotionBlockNum;
+
+ const bool bCurRefIsLtr = 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)));
+
+ //for reference selection
+ //this judge can only be saved when iAvailableRefNum==1, which is very limit
+ //when LTR is OFF, it can still judge from all available STR
+ if (JudgeBestRef (pRefPic, sLtrJudgement, iFrameComplexity, bIsClosestLtrFrame)) {+ SaveBestRefToJudgement (iRefPicAvQP, iFrameComplexity, &sLtrJudgement);
+ SaveBestRefToLocal (pRefPicInfo, sSceneChangeResult, &sLtrSaved);
+ bBestRefIsLtr = bCurRefIsLtr;
+ pBestStrBlockStaticPointer = sSceneChangeResult.pStaticBlockIdc;
+ }
+ if (bCurRefIsLtr && JudgeBestRef (pRefPic, sSceneLtrJudgement, iFrameComplexity, bIsClosestLtrFrame)) {+ SaveBestRefToJudgement (iRefPicAvQP, iFrameComplexity, &sSceneLtrJudgement);
+ SaveBestRefToLocal (pRefPicInfo, sSceneChangeResult, &sSceneLtrSaved);
+ pBestLtrBlockStaticPointer = sSceneChangeResult.pStaticBlockIdc;
+ }
+
+ if (iMotionBlockNum <= iNegligibleMotionBlocks) {+ break;
+ }
}
+ }
- return static_cast<ESceneChangeIdc>(iVaaFrameSceneChangeIdc);
+ if (iNumOfLargeChange == iAvailableRefNum) {+ iVaaFrameSceneChangeIdc = LARGE_CHANGED_SCENE;
+ } else if ((iNumOfMediumChangeToLtr == iAvailableSceneRefNum) && (0 != iAvailableSceneRefNum)) {+ iVaaFrameSceneChangeIdc = MEDIUM_CHANGED_SCENE;
+ } else {+ iVaaFrameSceneChangeIdc = SIMILAR_SCENE;
+ }
+
+ SaveBestRefToVaa (sLtrSaved, & (pVaaExt->sVaaStrBestRefCandidate[0]));
+
+ if (0 == iAvailableSceneRefNum) {+ SaveBestRefToVaa (sSceneLtrSaved, & (pVaaExt->sVaaStrBestRefCandidate[1]));
+ }
+
+ pVaaExt->iNumOfAvailableRef = 1;
+ return static_cast<ESceneChangeIdc> (iVaaFrameSceneChangeIdc);
}
void CWelsPreProcess::Padding (uint8_t* pSrcY, uint8_t* pSrcU, uint8_t* pSrcV, int32_t iStrideY, int32_t iStrideUV,
int32_t iActualWidth, int32_t iPaddingWidth, int32_t iActualHeight, int32_t iPaddingHeight) {@@ -1049,7 +1244,7 @@
//in VP Process
if (kiTargetWidth > iSrcWidth || kiTargetHeight > iSrcHeight) {- Padding(pDstY, pDstU, pDstV, kiDstStrideY, kiDstStrideUV, iSrcWidth, kiTargetWidth, iSrcHeight, kiTargetHeight);
+ Padding (pDstY, pDstU, pDstV, kiDstStrideY, kiDstStrideUV, iSrcWidth, kiTargetWidth, iSrcHeight, kiTargetHeight);
}
}
--
⑨