using independent encoder control logic for SAVC case

This commit is contained in:
Karina 2016-01-14 09:16:12 +08:00
parent 7bfb96b2b6
commit 0f0d54ef51
13 changed files with 405 additions and 313 deletions

View File

@ -82,11 +82,11 @@ int32_t InitFunctionPointers (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* _param,
/*! /*!
* \brief initialize frame coding * \brief initialize frame coding
*/ */
void InitFrameCoding (sWelsEncCtx* pEncCtx, const EVideoFrameType keFrameType); void InitFrameCoding (sWelsEncCtx* pEncCtx, const EVideoFrameType keFrameType,const int32_t kiDidx);
void LoadBackFrameNum(sWelsEncCtx* pEncCtx); void LoadBackFrameNum(sWelsEncCtx* pEncCtx,const int32_t kiDidx);
EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum);
EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum,const int32_t kiDidx);
void InitBitStream(sWelsEncCtx* pEncCtx);
int32_t GetTemporalLevel (SSpatialLayerInternal* fDlp, const int32_t kiFrameNum, const int32_t kiGopSize); int32_t GetTemporalLevel (SSpatialLayerInternal* fDlp, const int32_t kiFrameNum, const int32_t kiGopSize);
/*! /*!
* \brief Dump reconstruction for dependency layer * \brief Dump reconstruction for dependency layer

View File

@ -149,10 +149,7 @@ typedef struct TagWelsEncCtx {
SLTRState* pLtr;//[MAX_DEPENDENCY_LAYER]; SLTRState* pLtr;//[MAX_DEPENDENCY_LAYER];
bool bCurFrameMarkedAsSceneLtr; bool bCurFrameMarkedAsSceneLtr;
// Derived // Derived
int32_t iCodingIndex;
int32_t iFrameIndex; // count how many frames elapsed during coding context currently
int32_t iFrameNum; // current frame number coding
int32_t iPOC; // frame iPOC
EWelsSliceType eSliceType; // currently coding slice type EWelsSliceType eSliceType; // currently coding slice type
EWelsNalUnitType eNalType; // NAL type EWelsNalUnitType eNalType; // NAL type
EWelsNalRefIdc eNalPriority; // NAL_Reference_Idc currently EWelsNalRefIdc eNalPriority; // NAL_Reference_Idc currently
@ -162,7 +159,6 @@ typedef struct TagWelsEncCtx {
uint8_t uiDependencyId; // Idc of dependecy layer to be coded uint8_t uiDependencyId; // Idc of dependecy layer to be coded
uint8_t uiTemporalId; // Idc of temporal layer to be coded uint8_t uiTemporalId; // Idc of temporal layer to be coded
bool bNeedPrefixNalFlag; // whether add prefix nal bool bNeedPrefixNalFlag; // whether add prefix nal
bool bEncCurFrmAsIdrFlag;
// Rate control routine // Rate control routine
SWelsSvcRc* pWelsSvcRc; SWelsSvcRc* pWelsSvcRc;
@ -202,7 +198,6 @@ typedef struct TagWelsEncCtx {
bool bRefOfCurTidIsLtr[MAX_DEPENDENCY_LAYER][MAX_TEMPORAL_LEVEL]; bool bRefOfCurTidIsLtr[MAX_DEPENDENCY_LAYER][MAX_TEMPORAL_LEVEL];
uint16_t uiIdrPicId; // IDR picture id: [0, 65535], this one is used for LTR uint16_t uiIdrPicId; // IDR picture id: [0, 65535], this one is used for LTR
int32_t iMaxSliceCount;// maximal count number of slices for all layers observation int32_t iMaxSliceCount;// maximal count number of slices for all layers observation
int16_t iActiveThreadsNum; // number of threads active so far int16_t iActiveThreadsNum; // number of threads active so far

View File

@ -86,7 +86,13 @@ typedef struct TagDLayerParam {
int8_t iHighestTemporalId; int8_t iHighestTemporalId;
float fInputFrameRate; // input frame rate float fInputFrameRate; // input frame rate
float fOutputFrameRate; // output frame rate float fOutputFrameRate; // output frame rate
// uint16_t uiIdrPicId; // IDR picture id: [0, 65535], this one is used for LTR
int32_t iSkipFrameFlag; //_GOM_RC_
int32_t iCodingIndex;
int32_t iFrameIndex; // count how many frames elapsed during coding context currently
bool bEncCurFrmAsIdrFlag;
int32_t iFrameNum; // current frame number coding
int32_t iPOC; // frame iPOC
#ifdef ENABLE_FRAME_DUMP #ifdef ENABLE_FRAME_DUMP
char sRecFileName[MAX_FNAME_LEN]; // file to be constructed char sRecFileName[MAX_FNAME_LEN]; // file to be constructed
#endif//ENABLE_FRAME_DUMP #endif//ENABLE_FRAME_DUMP

View File

@ -140,7 +140,7 @@ class CWelsPreProcess {
const uint32_t kuiShortRefCount); const uint32_t kuiShortRefCount);
void UpdateSrcListLosslessScreenRefSelectionWithLtr (SPicture* pCurPicture, const int32_t kiCurDid, void UpdateSrcListLosslessScreenRefSelectionWithLtr (SPicture* pCurPicture, const int32_t kiCurDid,
const int32_t kuiMarkLongTermPicIdx, SPicture** pLongRefList); const int32_t kuiMarkLongTermPicIdx, SPicture** pLongRefList);
bool BuildSpatialLayer(sWelsEncCtx* pCtx, const SSourcePicture* kpSrc,int32_t iSpatialLayer);
private: private:
int32_t WelsPreprocessCreate(); int32_t WelsPreprocessCreate();
int32_t WelsPreprocessDestroy(); int32_t WelsPreprocessDestroy();

View File

@ -211,7 +211,7 @@ int32_t InitFunctionPointers (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* pParam,
/*init pixel average function*/ /*init pixel average function*/
/*get one column or row pixel when refinement*/ /*get one column or row pixel when refinement*/
InitMcFunc (&pFuncList->sMcFuncs, uiCpuFlag); InitMcFunc (&pFuncList->sMcFuncs, uiCpuFlag);
InitCoeffFunc (pFuncList,uiCpuFlag,pParam->iEntropyCodingModeFlag); InitCoeffFunc (pFuncList, uiCpuFlag, pParam->iEntropyCodingModeFlag);
WelsInitEncodingFuncs (pFuncList, uiCpuFlag); WelsInitEncodingFuncs (pFuncList, uiCpuFlag);
WelsInitReconstructionFuncs (pFuncList, uiCpuFlag); WelsInitReconstructionFuncs (pFuncList, uiCpuFlag);
@ -226,87 +226,97 @@ int32_t InitFunctionPointers (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* pParam,
return iReturn; return iReturn;
} }
void UpdateFrameNum(sWelsEncCtx* pEncCtx) { void UpdateFrameNum (sWelsEncCtx* pEncCtx, const int32_t kiDidx) {
SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDidx];
bool bNeedFrameNumIncreasing = false; bool bNeedFrameNumIncreasing = false;
for (int32_t i=0; i<MAX_DEPENDENCY_LAYER; i++) {
if (NRI_PRI_LOWEST != pEncCtx->eLastNalPriority[i]) { if (NRI_PRI_LOWEST != pEncCtx->eLastNalPriority[kiDidx]) {
bNeedFrameNumIncreasing = true; bNeedFrameNumIncreasing = true;
}
} }
if (bNeedFrameNumIncreasing) { if (bNeedFrameNumIncreasing) {
if (pEncCtx->iFrameNum < (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1) if (pParamInternal->iFrameNum < (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1)
++ pEncCtx->iFrameNum; ++ pParamInternal->iFrameNum;
else else
pEncCtx->iFrameNum = 0; // if iFrameNum overflow pParamInternal->iFrameNum = 0; // if iFrameNum overflow
}
for (int32_t i=0; i<MAX_DEPENDENCY_LAYER; i++) {
pEncCtx->eLastNalPriority[i] = NRI_PRI_LOWEST;
} }
pEncCtx->eLastNalPriority[kiDidx] = NRI_PRI_LOWEST;
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO, "UpdateFrameNum,bNeedFrameNumIncreasing = %d,iFrameNum = %d,kiDidx = %d",
bNeedFrameNumIncreasing, pParamInternal->iFrameNum, kiDidx);
} }
void LoadBackFrameNum(sWelsEncCtx* pEncCtx) { void LoadBackFrameNum (sWelsEncCtx* pEncCtx, const int32_t kiDidx) {
bool bNeedFrameNumIncreasing = false; SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDidx];
for (int32_t i=0; i<MAX_DEPENDENCY_LAYER; i++) { bool bNeedFrameNumIncreasing = false;
if (NRI_PRI_LOWEST != pEncCtx->eLastNalPriority[i]) {
bNeedFrameNumIncreasing = true; if (NRI_PRI_LOWEST != pEncCtx->eLastNalPriority[kiDidx]) {
} bNeedFrameNumIncreasing = true;
} }
if (bNeedFrameNumIncreasing) {
if (pEncCtx->iFrameNum != 0) { if (bNeedFrameNumIncreasing) {
pEncCtx->iFrameNum --; if (pParamInternal->iFrameNum != 0) {
} else { pParamInternal->iFrameNum --;
pEncCtx->iFrameNum = (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1; } else {
} pParamInternal->iFrameNum = (1 << pEncCtx->pSps->uiLog2MaxFrameNum) - 1;
} }
}
WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_INFO,
"LoadBackFrameNum,bNeedFrameNumIncreasing = %d,iFrameNum = %d,kiDidx = %d", bNeedFrameNumIncreasing,
pParamInternal->iFrameNum, kiDidx);
} }
/*! void InitBitStream (sWelsEncCtx* pEncCtx) {
* \brief initialize frame coding
*/
void InitFrameCoding (sWelsEncCtx* pEncCtx, const EVideoFrameType keFrameType) {
// for bitstream writing // for bitstream writing
pEncCtx->iPosBsBuffer = 0; // reset bs pBuffer position pEncCtx->iPosBsBuffer = 0; // reset bs pBuffer position
pEncCtx->pOut->iNalIndex = 0; // reset NAL index pEncCtx->pOut->iNalIndex = 0; // reset NAL index
pEncCtx->pOut->iLayerBsIndex = 0; // reset index of Layer Bs pEncCtx->pOut->iLayerBsIndex = 0; // reset index of Layer Bs
InitBits (&pEncCtx->pOut->sBsWrite, pEncCtx->pOut->pBsBuffer, pEncCtx->pOut->uiSize); InitBits (&pEncCtx->pOut->sBsWrite, pEncCtx->pOut->pBsBuffer, pEncCtx->pOut->uiSize);
}
/*!
* \brief initialize frame coding
*/
void InitFrameCoding (sWelsEncCtx* pEncCtx, const EVideoFrameType keFrameType, const int32_t kiDidx) {
SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDidx];
if (keFrameType == videoFrameTypeP) { if (keFrameType == videoFrameTypeP) {
++pEncCtx->iFrameIndex; ++pParamInternal->iFrameIndex;
if (pEncCtx->iPOC < (1 << pEncCtx->pSps->iLog2MaxPocLsb) - 2) // if iPOC type is no 0, this need be modification if (pParamInternal->iPOC < (1 << pEncCtx->pSps->iLog2MaxPocLsb) -
pEncCtx->iPOC += 2; // for POC type 0 2) // if iPOC type is no 0, this need be modification
pParamInternal->iPOC += 2; // for POC type 0
else else
pEncCtx->iPOC = 0; pParamInternal->iPOC = 0;
UpdateFrameNum(pEncCtx); UpdateFrameNum (pEncCtx, kiDidx);
pEncCtx->eNalType = NAL_UNIT_CODED_SLICE; pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
pEncCtx->eSliceType = P_SLICE; pEncCtx->eSliceType = P_SLICE;
pEncCtx->eNalPriority = NRI_PRI_HIGH; pEncCtx->eNalPriority = NRI_PRI_HIGH;
} else if (keFrameType == videoFrameTypeIDR) { } else if (keFrameType == videoFrameTypeIDR) {
pEncCtx->iFrameNum = 0; pParamInternal->iFrameNum = 0;
pEncCtx->iPOC = 0; pParamInternal->iPOC = 0;
pEncCtx->bEncCurFrmAsIdrFlag = false; pParamInternal->bEncCurFrmAsIdrFlag = false;
pEncCtx->iFrameIndex = 0; pParamInternal->iFrameIndex = 0;
pEncCtx->eNalType = NAL_UNIT_CODED_SLICE_IDR; pEncCtx->eNalType = NAL_UNIT_CODED_SLICE_IDR;
pEncCtx->eSliceType = I_SLICE; pEncCtx->eSliceType = I_SLICE;
pEncCtx->eNalPriority = NRI_PRI_HIGHEST; pEncCtx->eNalPriority = NRI_PRI_HIGHEST;
pEncCtx->iCodingIndex = 0; pParamInternal->iCodingIndex = 0;
// reset_ref_list // reset_ref_list
// rc_init_gop // rc_init_gop
} else if (keFrameType == videoFrameTypeI) { } else if (keFrameType == videoFrameTypeI) {
if (pEncCtx->iPOC < (1 << pEncCtx->pSps->iLog2MaxPocLsb) - 2) // if iPOC type is no 0, this need be modification if (pParamInternal->iPOC < (1 << pEncCtx->pSps->iLog2MaxPocLsb) -
pEncCtx->iPOC += 2; // for POC type 0 2) // if iPOC type is no 0, this need be modification
pParamInternal->iPOC += 2; // for POC type 0
else else
pEncCtx->iPOC = 0; pParamInternal->iPOC = 0;
UpdateFrameNum(pEncCtx); UpdateFrameNum (pEncCtx, kiDidx);
pEncCtx->eNalType = NAL_UNIT_CODED_SLICE; pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
pEncCtx->eSliceType = I_SLICE; pEncCtx->eSliceType = I_SLICE;
@ -322,11 +332,12 @@ void InitFrameCoding (sWelsEncCtx* pEncCtx, const EVideoFrameType keFrameType) {
#endif//FRAME_INFO_OUTPUT #endif//FRAME_INFO_OUTPUT
} }
EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum) { EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum, const int32_t kiDidx) {
SWelsSvcCodingParam* pSvcParam = pEncCtx->pSvcParam; SWelsSvcCodingParam* pSvcParam = pEncCtx->pSvcParam;
SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[kiDidx];
EVideoFrameType iFrameType = videoFrameTypeInvalid; EVideoFrameType iFrameType = videoFrameTypeInvalid;
bool bSceneChangeFlag = false; bool bSceneChangeFlag = false;
int32_t iSkipFrameFlag = pSvcParam->bSimulcastAVC?pParamInternal->iSkipFrameFlag:pEncCtx->iSkipFrameFlag;
if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) { if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
if ((!pSvcParam->bEnableSceneChangeDetect) || pEncCtx->pVaa->bIdrPeriodFlag || if ((!pSvcParam->bEnableSceneChangeDetect) || pEncCtx->pVaa->bIdrPeriodFlag ||
(kiSpatialNum < pSvcParam->iSpatialLayerNum)) { (kiSpatialNum < pSvcParam->iSpatialLayerNum)) {
@ -334,7 +345,7 @@ EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum
} else { } else {
bSceneChangeFlag = pEncCtx->pVaa->bSceneChangeFlag; bSceneChangeFlag = pEncCtx->pVaa->bSceneChangeFlag;
} }
if (pEncCtx->pVaa->bIdrPeriodFlag || pEncCtx->bEncCurFrmAsIdrFlag || (!pSvcParam->bEnableLongTermReference if (pEncCtx->pVaa->bIdrPeriodFlag || pParamInternal->bEncCurFrmAsIdrFlag || (!pSvcParam->bEnableLongTermReference
&& bSceneChangeFlag)) { && bSceneChangeFlag)) {
iFrameType = videoFrameTypeIDR; iFrameType = videoFrameTypeIDR;
} else if (pSvcParam->bEnableLongTermReference && (bSceneChangeFlag } else if (pSvcParam->bEnableLongTermReference && (bSceneChangeFlag
@ -356,11 +367,11 @@ EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum
} else { } else {
iFrameType = videoFrameTypeP; iFrameType = videoFrameTypeP;
} }
if (videoFrameTypeP == iFrameType && pEncCtx->iSkipFrameFlag > 0) { if (videoFrameTypeP == iFrameType && iSkipFrameFlag > 0) {
-- pEncCtx->iSkipFrameFlag; pParamInternal->iSkipFrameFlag = 0;
iFrameType = videoFrameTypeSkip; iFrameType = videoFrameTypeSkip;
} else if (videoFrameTypeIDR == iFrameType) { } else if (videoFrameTypeIDR == iFrameType) {
pEncCtx->iCodingIndex = 0; pParamInternal->iCodingIndex = 0;
pEncCtx->bCurFrameMarkedAsSceneLtr = true; pEncCtx->bCurFrameMarkedAsSceneLtr = true;
} }
@ -368,7 +379,7 @@ EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum
// perform scene change detection // perform scene change detection
if ((!pSvcParam->bEnableSceneChangeDetect) || pEncCtx->pVaa->bIdrPeriodFlag || if ((!pSvcParam->bEnableSceneChangeDetect) || pEncCtx->pVaa->bIdrPeriodFlag ||
(kiSpatialNum < pSvcParam->iSpatialLayerNum) (kiSpatialNum < pSvcParam->iSpatialLayerNum)
|| (pEncCtx->iFrameIndex < (VGOP_SIZE << 1))) { // avoid too frequent I frame coding, rc control || (pParamInternal->iFrameIndex < (VGOP_SIZE << 1))) { // avoid too frequent I frame coding, rc control
bSceneChangeFlag = false; bSceneChangeFlag = false;
} else { } else {
bSceneChangeFlag = pEncCtx->pVaa->bSceneChangeFlag; bSceneChangeFlag = pEncCtx->pVaa->bSceneChangeFlag;
@ -378,13 +389,13 @@ EVideoFrameType DecideFrameType (sWelsEncCtx* pEncCtx, const int8_t kiSpatialNum
//bIdrPeriodFlag: RC disable || iSpatialNum != pSvcParam->iSpatialLayerNum //bIdrPeriodFlag: RC disable || iSpatialNum != pSvcParam->iSpatialLayerNum
//pEncCtx->bEncCurFrmAsIdrFlag: 1. first frame should be IDR; 2. idr pause; 3. idr request //pEncCtx->bEncCurFrmAsIdrFlag: 1. first frame should be IDR; 2. idr pause; 3. idr request
iFrameType = (pEncCtx->pVaa->bIdrPeriodFlag || bSceneChangeFlag iFrameType = (pEncCtx->pVaa->bIdrPeriodFlag || bSceneChangeFlag
|| pEncCtx->bEncCurFrmAsIdrFlag) ? videoFrameTypeIDR : videoFrameTypeP; || pParamInternal->bEncCurFrmAsIdrFlag) ? videoFrameTypeIDR : videoFrameTypeP;
if (videoFrameTypeP == iFrameType && pEncCtx->iSkipFrameFlag > 0) { // for frame skip, 1/5/2010 if (videoFrameTypeP == iFrameType && iSkipFrameFlag > 0) { // for frame skip, 1/5/2010
-- pEncCtx->iSkipFrameFlag; pParamInternal->iSkipFrameFlag = 0;
iFrameType = videoFrameTypeSkip; iFrameType = videoFrameTypeSkip;
} else if (videoFrameTypeIDR == iFrameType) { } else if (videoFrameTypeIDR == iFrameType) {
pEncCtx->iCodingIndex = 0; pParamInternal->iCodingIndex = 0;
} }
} }
return iFrameType; return iFrameType;

View File

@ -1206,6 +1206,7 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
while (iDlayerIndex < iDlayerCount) { while (iDlayerIndex < iDlayerCount) {
SDqLayer* pDqLayer = NULL; SDqLayer* pDqLayer = NULL;
SSpatialLayerConfig* pDlayer = &pParam->sSpatialLayers[iDlayerIndex]; SSpatialLayerConfig* pDlayer = &pParam->sSpatialLayers[iDlayerIndex];
SSpatialLayerInternal* pParamInternal = &pParam->sDependencyLayers[iDlayerIndex];
const int32_t kiMbW = (pDlayer->iVideoWidth + 0x0f) >> 4; const int32_t kiMbW = (pDlayer->iVideoWidth + 0x0f) >> 4;
const int32_t kiMbH = (pDlayer->iVideoHeight + 0x0f) >> 4; const int32_t kiMbH = (pDlayer->iVideoHeight + 0x0f) >> 4;
int32_t iMaxSliceNum = 1; int32_t iMaxSliceNum = 1;
@ -1213,6 +1214,12 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
if (iMaxSliceNum < kiSliceNum) if (iMaxSliceNum < kiSliceNum)
iMaxSliceNum = kiSliceNum; iMaxSliceNum = kiSliceNum;
pParamInternal->iSkipFrameFlag = 0;
pParamInternal->iCodingIndex = 0;
pParamInternal->iFrameIndex = 0;
pParamInternal->iFrameNum = 0;
pParamInternal->iPOC = 0;
pParamInternal->bEncCurFrmAsIdrFlag = true; // make sure first frame is IDR
// pDq layers list // pDq layers list
pDqLayer = (SDqLayer*)pMa->WelsMallocz (sizeof (SDqLayer), "pDqLayer"); pDqLayer = (SDqLayer*)pMa->WelsMallocz (sizeof (SDqLayer), "pDqLayer");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pDqLayer), FreeMemorySvc (ppCtx)) WELS_VERIFY_RETURN_PROC_IF (1, (NULL == pDqLayer), FreeMemorySvc (ppCtx))
@ -1900,7 +1907,6 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingPa
(pMa->WelsMallocz (iCountMaxMbNum * sizeof (int32_t), "pSadCostMb")); (pMa->WelsMallocz (iCountMaxMbNum * sizeof (int32_t), "pSadCostMb"));
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSadCostMb), FreeMemorySvc (ppCtx)) WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSadCostMb), FreeMemorySvc (ppCtx))
(*ppCtx)->bEncCurFrmAsIdrFlag = true; // make sure first frame is IDR
(*ppCtx)->iGlobalQp = 26; // global qp in default (*ppCtx)->iGlobalQp = 26; // global qp in default
(*ppCtx)->pLtr = (SLTRState*)pMa->WelsMalloc (kiNumDependencyLayers * sizeof (SLTRState), "SLTRState"); (*ppCtx)->pLtr = (SLTRState*)pMa->WelsMalloc (kiNumDependencyLayers * sizeof (SLTRState), "SLTRState");
@ -2802,7 +2808,7 @@ void WelsInitCurrentLayer (sWelsEncCtx* pCtx,
SDqIdc* pDqIdc = &pCtx->pDqIdcMap[kiCurDid]; SDqIdc* pDqIdc = &pCtx->pDqIdcMap[kiCurDid];
int32_t iIdx = 0; int32_t iIdx = 0;
int32_t iSliceCount = 0; int32_t iSliceCount = 0;
SSpatialLayerInternal* pParamInternal = &pParam->sDependencyLayers[kiCurDid];
if (NULL == pCurDq) if (NULL == pCurDq)
return; return;
@ -2856,8 +2862,9 @@ void WelsInitCurrentLayer (sWelsEncCtx* pCtx,
pNalHdExt->uiDependencyId = kiCurDid; pNalHdExt->uiDependencyId = kiCurDid;
pNalHdExt->bDiscardableFlag = (pCtx->bNeedPrefixNalFlag) ? (pNalHd->uiNalRefIdc == NRI_PRI_LOWEST) : false; pNalHdExt->bDiscardableFlag = (pCtx->bNeedPrefixNalFlag) ? (pNalHd->uiNalRefIdc == NRI_PRI_LOWEST) : false;
pNalHdExt->bIdrFlag = (pCtx->iFrameNum == 0) && ((pCtx->eNalType == NAL_UNIT_CODED_SLICE_IDR) pNalHdExt->bIdrFlag = (pParamInternal->iFrameNum == 0)
|| (pCtx->eSliceType == I_SLICE)); && ((pCtx->eNalType == NAL_UNIT_CODED_SLICE_IDR)
|| (pCtx->eSliceType == I_SLICE));
pNalHdExt->uiTemporalId = pCtx->uiTemporalId; pNalHdExt->uiTemporalId = pCtx->uiTemporalId;
// pEncPic pData // pEncPic pData
@ -3398,9 +3405,16 @@ int32_t WritePadding (sWelsEncCtx* pCtx, int32_t iLen, int32_t& iSize) {
int32_t ForceCodingIDR (sWelsEncCtx* pCtx) { int32_t ForceCodingIDR (sWelsEncCtx* pCtx) {
if (NULL == pCtx) if (NULL == pCtx)
return 1; return 1;
for (int32_t iDid = 0; iDid < pCtx->pSvcParam->iSpatialLayerNum; iDid++) {
SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[iDid];
pParamInternal->iCodingIndex = 0;
pParamInternal->iSkipFrameFlag = 0;
pParamInternal->iFrameIndex = 0;
pParamInternal->iFrameNum = 0;
pParamInternal->iPOC = 0;
pParamInternal->bEncCurFrmAsIdrFlag = true;
}
pCtx->bEncCurFrmAsIdrFlag = true;
pCtx->iCodingIndex = 0;
pCtx->bCheckWindowStatusRefreshFlag = false; pCtx->bCheckWindowStatusRefreshFlag = false;
WelsLog (&pCtx->sLogCtx, WELS_LOG_INFO, "ForceCodingIDR at InputFrameCount=%d\n", WelsLog (&pCtx->sLogCtx, WELS_LOG_INFO, "ForceCodingIDR at InputFrameCount=%d\n",
@ -3427,11 +3441,10 @@ int32_t WelsEncoderEncodeParameterSets (sWelsEncCtx* pCtx, void* pDst) {
pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiQualityId = 0;
pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
pLayerBsInfo->iNalCount = iCountNal; pLayerBsInfo->iNalCount = iCountNal;
pLayerBsInfo->eFrameType = videoFrameTypeIDR; pLayerBsInfo->eFrameType = videoFrameTypeInvalid;
//pCtx->eLastNalPriority = NRI_PRI_HIGHEST; //pCtx->eLastNalPriority = NRI_PRI_HIGHEST;
pFbi->iLayerNum = 1; pFbi->iLayerNum = 1;
pFbi->eFrameType = videoFrameTypeInvalid; pFbi->eFrameType = videoFrameTypeInvalid;
WelsEmms(); WelsEmms();
return ENC_RETURN_SUCCESS; return ENC_RETURN_SUCCESS;
@ -3479,75 +3492,69 @@ int32_t WriteSsvcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
} }
// writing parasets for simulcast avc // writing parasets for simulcast avc
int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t kiSpatialNum, int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t iIdx,
SLayerBSInfo*& pLayerBsInfo, int32_t& iLayerNum, int32_t& iFrameSize) { SLayerBSInfo*& pLayerBsInfo, int32_t& iLayerNum, int32_t& iFrameSize) {
int32_t iNonVclSize = 0, iCountNal = 0, iReturn = ENC_RETURN_SUCCESS; int32_t iNonVclSize = 0, iCountNal = 0, iReturn = ENC_RETURN_SUCCESS;
// write SPS // write SPS
iNonVclSize = 0; iNonVclSize = 0;
assert ((kiSpatialNum == pCtx->iSpsNum) || (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)); //writing one NAL
int32_t iNalSize = 0;
iCountNal = 0;
for (int32_t iIdx = 0; iIdx < pCtx->iSpsNum; iIdx++) { iReturn = WelsWriteOneSPS (pCtx, iIdx, iNalSize);
//writing one NAL WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
int32_t iNalSize = 0;
iCountNal = 0;
iReturn = WelsWriteOneSPS (pCtx, iIdx, iNalSize); pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize;
WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS) iNonVclSize += iNalSize;
iCountNal = 1;
pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize; //finish writing one NAL
iNonVclSize += iNalSize;
iCountNal = 1;
//finish writing one NAL
pLayerBsInfo->uiSpatialId = iIdx; pLayerBsInfo->uiSpatialId = iIdx;
pLayerBsInfo->uiTemporalId = 0; pLayerBsInfo->uiTemporalId = 0;
pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiQualityId = 0;
pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
pLayerBsInfo->iNalCount = iCountNal; pLayerBsInfo->iNalCount = iCountNal;
pLayerBsInfo->eFrameType = videoFrameTypeIDR; pLayerBsInfo->eFrameType = videoFrameTypeIDR;
//point to next pLayerBsInfo //point to next pLayerBsInfo
++ pLayerBsInfo; ++ pLayerBsInfo;
++ pCtx->pOut->iLayerBsIndex; ++ pCtx->pOut->iLayerBsIndex;
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal; pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
//update for external countings //update for external countings
++ iLayerNum; ++ iLayerNum;
}
// write PPS // write PPS
//TODO: under new strategy, will PPS be correctly updated? //TODO: under new strategy, will PPS be correctly updated?
for (int32_t iIdx = 0; iIdx < pCtx->iPpsNum; iIdx++) { //writing one NAL
//writing one NAL iNalSize = 0;
int32_t iNalSize = 0; iCountNal = 0;
iCountNal = 0;
iReturn = WelsWriteOnePPS (pCtx, iIdx, iNalSize); iReturn = WelsWriteOnePPS (pCtx, iIdx, iNalSize);
WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS) WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize; pLayerBsInfo->pNalLengthInByte[iCountNal] = iNalSize;
iNonVclSize += iNalSize; iNonVclSize += iNalSize;
iCountNal = 1; iCountNal = 1;
//finish writing one NAL //finish writing one NAL
pLayerBsInfo->uiSpatialId = iIdx; pLayerBsInfo->uiSpatialId = iIdx;
pLayerBsInfo->uiTemporalId = 0; pLayerBsInfo->uiTemporalId = 0;
pLayerBsInfo->uiQualityId = 0; pLayerBsInfo->uiQualityId = 0;
pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER; pLayerBsInfo->uiLayerType = NON_VIDEO_CODING_LAYER;
pLayerBsInfo->iNalCount = iCountNal; pLayerBsInfo->iNalCount = iCountNal;
pLayerBsInfo->eFrameType = videoFrameTypeIDR; pLayerBsInfo->eFrameType = videoFrameTypeIDR;
//point to next pLayerBsInfo //point to next pLayerBsInfo
++ pLayerBsInfo; ++ pLayerBsInfo;
++ pCtx->pOut->iLayerBsIndex; ++ pCtx->pOut->iLayerBsIndex;
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal; pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
//update for external countings //update for external countings
++ iLayerNum; ++ iLayerNum;
}
// to check number of layers / nals / slices dependencies // to check number of layers / nals / slices dependencies
if (iLayerNum > MAX_LAYER_NUM_OF_FRAME) { if (iLayerNum > MAX_LAYER_NUM_OF_FRAME) {
@ -3645,6 +3652,7 @@ int32_t WriteSavcParaset_Listing (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
void StackBackEncoderStatus (sWelsEncCtx* pEncCtx, void StackBackEncoderStatus (sWelsEncCtx* pEncCtx,
EVideoFrameType keFrameType) { EVideoFrameType keFrameType) {
SSpatialLayerInternal* pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
// for bitstream writing // for bitstream writing
pEncCtx->iPosBsBuffer = 0; // reset bs pBuffer position pEncCtx->iPosBsBuffer = 0; // reset bs pBuffer position
pEncCtx->pOut->iNalIndex = 0; // reset NAL index pEncCtx->pOut->iNalIndex = 0; // reset NAL index
@ -3652,14 +3660,15 @@ void StackBackEncoderStatus (sWelsEncCtx* pEncCtx,
InitBits (&pEncCtx->pOut->sBsWrite, pEncCtx->pOut->pBsBuffer, pEncCtx->pOut->uiSize); InitBits (&pEncCtx->pOut->sBsWrite, pEncCtx->pOut->pBsBuffer, pEncCtx->pOut->uiSize);
if ((keFrameType == videoFrameTypeP) || (keFrameType == videoFrameTypeI)) { if ((keFrameType == videoFrameTypeP) || (keFrameType == videoFrameTypeI)) {
pEncCtx->iFrameIndex --; pParamInternal->iFrameIndex --;
if (pEncCtx->iPOC != 0) { if (pParamInternal->iPOC != 0) {
pEncCtx->iPOC -= 2; pParamInternal->iPOC -= 2;
} else { } else {
pEncCtx->iPOC = (1 << pEncCtx->pSps->iLog2MaxPocLsb) - 2; pParamInternal->iPOC = (1 << pEncCtx->pSps->iLog2MaxPocLsb) - 2;
} }
LoadBackFrameNum (pEncCtx); LoadBackFrameNum (pEncCtx, pEncCtx->uiDependencyId);
pEncCtx->eNalType = NAL_UNIT_CODED_SLICE; pEncCtx->eNalType = NAL_UNIT_CODED_SLICE;
pEncCtx->eSliceType = P_SLICE; pEncCtx->eSliceType = P_SLICE;
//pEncCtx->eNalPriority = pEncCtx->eLastNalPriority; //not need this since eNalPriority will be updated at the beginning of coding a frame //pEncCtx->eNalPriority = pEncCtx->eLastNalPriority; //not need this since eNalPriority will be updated at the beginning of coding a frame
@ -3682,10 +3691,10 @@ void ClearFrameBsInfo (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi) {
for (int i = 0; i < pFbi->iLayerNum; i++) { for (int i = 0; i < pFbi->iLayerNum; i++) {
pFbi->sLayerInfo[i].iNalCount = 0; pFbi->sLayerInfo[i].iNalCount = 0;
pFbi->sLayerInfo[i].eFrameType = videoFrameTypeSkip;
} }
pFbi->iLayerNum = 0; pFbi->iLayerNum = 0;
pFbi->iFrameSizeInBytes = 0; pFbi->iFrameSizeInBytes = 0;
pFbi->eFrameType = videoFrameTypeSkip;
} }
/*! /*!
@ -3725,6 +3734,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
int8_t iCurTid = 0; int8_t iCurTid = 0;
bool bAvcBased = false; bool bAvcBased = false;
SLogContext* pLogCtx = & (pCtx->sLogCtx); SLogContext* pLogCtx = & (pCtx->sLogCtx);
bool bFinishedWriteHeader = false;
#if defined(ENABLE_PSNR_CALC) #if defined(ENABLE_PSNR_CALC)
float fSnrY = .0f, fSnrU = .0f, fSnrV = .0f; float fSnrY = .0f, fSnrU = .0f, fSnrV = .0f;
#endif//ENABLE_PSNR_CALC #endif//ENABLE_PSNR_CALC
@ -3732,7 +3742,6 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
#if defined(_DEBUG) #if defined(_DEBUG)
int32_t i = 0, j = 0, k = 0; int32_t i = 0, j = 0, k = 0;
#endif//_DEBUG #endif//_DEBUG
pCtx->iEncoderError = ENC_RETURN_SUCCESS; pCtx->iEncoderError = ENC_RETURN_SUCCESS;
pCtx->bCurFrameMarkedAsSceneLtr = false; pCtx->bCurFrameMarkedAsSceneLtr = false;
pFbi->iLayerNum = 0; // for initialization pFbi->iLayerNum = 0; // for initialization
@ -3746,76 +3755,116 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pCtx->pFuncList->pfRc.pfWelsUpdateMaxBrWindowStatus (pCtx, iSpatialNum, pSrcPic->uiTimeStamp); pCtx->pFuncList->pfRc.pfWelsUpdateMaxBrWindowStatus (pCtx, iSpatialNum, pSrcPic->uiTimeStamp);
} }
if (iSpatialNum < 1) { // skip due to temporal layer settings (different frame rate) if (iSpatialNum < 1) {
++ pCtx->iCodingIndex; // ++ pCtx->iCodingIndex;
pLayerBsInfo->eFrameType = videoFrameTypeSkip;
pFbi->eFrameType = videoFrameTypeSkip; pFbi->eFrameType = videoFrameTypeSkip;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"[Rc] Frame timestamp = %lld, skip one frame due to preprocessing return (temporal layer settings or else), continual skipped %d frames", "[Rc] Frame timestamp = %lld, skip one frame due to preprocessing return (temporal layer settings or else), continual skipped %d frames",
pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames); pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
return ENC_RETURN_SUCCESS; return ENC_RETURN_SUCCESS;
} }
if (!pSvcParam->bSimulcastAVC) {
eFrameType = DecideFrameType (pCtx, iSpatialNum); pCtx->iSkipFrameFlag = false;
if (eFrameType == videoFrameTypeSkip) { for (int32_t iDid = 0; iDid < iSpatialNum; iDid++) {
if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip) if (pCtx->pSvcParam->sDependencyLayers[iDid].iSkipFrameFlag)
pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, iSpatialNum); pCtx->iSkipFrameFlag = 1;
pFbi->eFrameType = eFrameType;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"[Rc] Frame timestamp = %lld, skip one frame due to target_br, continual skipped %d frames",
pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
return ENC_RETURN_SUCCESS;
}
//loop each layer to check if have skip frame when RC and frame skip enable
if (pCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr) {
bool bSkip = pCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType,
(uint32_t)pSrcPic->uiTimeStamp);
if (bSkip) {
pFbi->eFrameType = videoFrameTypeSkip;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"[Rc] Frame timestamp = %lld, skip one frame due to max_br, continual skipped %d frames",
pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
return ENC_RETURN_SUCCESS;
} }
} }
pCtx->iContinualSkipFrames = 0; InitBitStream (pCtx);
InitFrameCoding (pCtx, eFrameType);
iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[pSpatialIndexMap->iDid], pCtx->iCodingIndex,
pSvcParam->uiGopSize);
pCtx->uiTemporalId = iCurTid;
pLayerBsInfo->pBsBuf = pCtx->pFrameBs ; pLayerBsInfo->pBsBuf = pCtx->pFrameBs ;
pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen; pLayerBsInfo->pNalLengthInByte = pCtx->pOut->pNalLen;
if (eFrameType == videoFrameTypeIDR) {
++ pCtx->uiIdrPicId;
// write parameter sets bitstream or SEI/SSEI (if any) here
// TODO: use function pointer instead
if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
pCtx->iEncoderError = ((!pSvcParam->bSimulcastAVC)
? (WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize))
: (WriteSavcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize)));
} else {
pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
}
WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
}
pCtx->pCurDqLayer = pCtx->ppDqLayerList[pSpatialIndexMap->iDid]; pCtx->pCurDqLayer = pCtx->ppDqLayerList[pSpatialIndexMap->iDid];
pCtx->pCurDqLayer->pRefLayer = NULL; pCtx->pCurDqLayer->pRefLayer = NULL;
while (iSpatialIdx < iSpatialNum) { while (iSpatialIdx < iSpatialNum) {
const int32_t iDidIdx = (pSpatialIndexMap + iSpatialIdx)->iDid; // get iDid bool bEncoding = pCtx->pVpp->BuildSpatialLayer (pCtx, pSrcPic, iSpatialIdx);
if (!bEncoding) {
++iSpatialIdx;
continue;
}
const int32_t iDidIdx = (pSpatialIndexMap + iSpatialIdx)->iDid;
SSpatialLayerConfig* pParam = &pSvcParam->sSpatialLayers[iDidIdx]; SSpatialLayerConfig* pParam = &pSvcParam->sSpatialLayers[iDidIdx];
SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[iDidIdx];
int32_t iDecompositionStages = pSvcParam->sDependencyLayers[iDidIdx].iDecompositionStages; int32_t iDecompositionStages = pSvcParam->sDependencyLayers[iDidIdx].iDecompositionStages;
pCtx->pCurDqLayer = pCtx->ppDqLayerList[iDidIdx];
pCtx->uiDependencyId = iCurDid = (int8_t)iDidIdx; pCtx->uiDependencyId = iCurDid = (int8_t)iDidIdx;
eFrameType = DecideFrameType (pCtx, iSpatialNum, iDidIdx);
if (eFrameType == videoFrameTypeSkip) {
eFrameType = videoFrameTypeSkip;
pLayerBsInfo->eFrameType = eFrameType;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"[Rc] Frame timestamp = %lld, skip one frame due to target_br, continual skipped %d frames",
pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
++ iSpatialIdx;
if (pSvcParam->bSimulcastAVC) {
if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip)
pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, iDidIdx);
continue;
}
else {
if (pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip) {
for (int32_t i = 0; i < iSpatialNum; i++) {
pCtx->pSvcParam->sDependencyLayers[i].iSkipFrameFlag = false;
pCtx->pFuncList->pfRc.pfWelsUpdateBufferWhenSkip (pCtx, (pSpatialIndexMap + i)->iDid);
}
}
return ENC_RETURN_SUCCESS;
}
}
//loop each layer to check if have skip frame when RC and frame skip enable
if (pCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr) {
bool bSkip = pCtx->pFuncList->pfRc.pfWelsCheckSkipBasedMaxbr (pCtx, iSpatialNum, eFrameType,
(uint32_t)pSrcPic->uiTimeStamp);
if (bSkip) {
eFrameType = videoFrameTypeSkip;
pLayerBsInfo->eFrameType = videoFrameTypeSkip;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"[Rc] Frame timestamp = %lld, skip one frame due to max_br, continual skipped %d frames",
pSrcPic->uiTimeStamp, pCtx->iContinualSkipFrames);
++ iSpatialIdx;
if (pSvcParam->bSimulcastAVC)
continue;
else
return ENC_RETURN_SUCCESS;
}
}
pCtx->iContinualSkipFrames = 0;
InitFrameCoding (pCtx, eFrameType, iDidIdx);
iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[iSpatialIdx], pParamInternal->iCodingIndex,
pSvcParam->uiGopSize);
pCtx->uiTemporalId = iCurTid;
if (eFrameType == videoFrameTypeIDR) {
// write parameter sets bitstream or SEI/SSEI (if any) here
// TODO: use function pointer instead
if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
if (pSvcParam->bSimulcastAVC) {
pCtx->iEncoderError = WriteSavcParaset (pCtx, iCurDid, pLayerBsInfo, iLayerNum, iFrameSize);
++ pCtx->uiIdrPicId;
} else if (!bFinishedWriteHeader) {
pCtx->iEncoderError = WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
++ pCtx->uiIdrPicId;
bFinishedWriteHeader = true;
}
} else if (!bFinishedWriteHeader) {
pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
bFinishedWriteHeader = true;
++ pCtx->uiIdrPicId;
}
WELS_VERIFY_RETURN_IFNEQ (pCtx->iEncoderError, ENC_RETURN_SUCCESS)
}
pCtx->pVpp->AnalyzeSpatialPic (pCtx, iDidIdx); pCtx->pVpp->AnalyzeSpatialPic (pCtx, iDidIdx);
pCtx->pEncPic = pEncPic = (pSpatialIndexMap + iSpatialIdx)->pSrc; pCtx->pEncPic = pEncPic = (pSpatialIndexMap + iSpatialIdx)->pSrc;
pCtx->pEncPic->iPictureType = pCtx->eSliceType; pCtx->pEncPic->iPictureType = pCtx->eSliceType;
pCtx->pEncPic->iFramePoc = pCtx->iPOC; pCtx->pEncPic->iFramePoc = pParamInternal->iPOC;
iCurWidth = pParam->iVideoWidth; iCurWidth = pParam->iVideoWidth;
iCurHeight = pParam->iVideoHeight; iCurHeight = pParam->iVideoHeight;
@ -3880,12 +3929,12 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
fsnr = pCtx->pDecPic; fsnr = pCtx->pDecPic;
#endif//#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC) #endif//#if defined(ENABLE_FRAME_DUMP) || defined(ENABLE_PSNR_CALC)
pCtx->pDecPic->iPictureType = pCtx->eSliceType; pCtx->pDecPic->iPictureType = pCtx->eSliceType;
pCtx->pDecPic->iFramePoc = pCtx->iPOC; pCtx->pDecPic->iFramePoc = pParamInternal->iPOC;
WelsInitCurrentLayer (pCtx, iCurWidth, iCurHeight); WelsInitCurrentLayer (pCtx, iCurWidth, iCurHeight);
pCtx->pFuncList->pMarkPic (pCtx); pCtx->pFuncList->pMarkPic (pCtx);
if (!pCtx->pFuncList->pBuildRefList (pCtx, pCtx->iPOC, 0)) { if (!pCtx->pFuncList->pBuildRefList (pCtx, pParamInternal->iPOC, 0)) {
WelsLog (pLogCtx, WELS_LOG_WARNING, WelsLog (pLogCtx, WELS_LOG_WARNING,
"WelsEncoderEncodeExt(), WelsBuildRefList failed for P frames, pCtx->iNumRef0= %d. ForceCodingIDR!", "WelsEncoderEncodeExt(), WelsBuildRefList failed for P frames, pCtx->iNumRef0= %d. ForceCodingIDR!",
pCtx->iNumRef0); pCtx->iNumRef0);
@ -3904,7 +3953,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pCtx->pVpp->AnalyzePictureComplexity (pCtx, pCtx->pEncPic, ((pCtx->eSliceType == P_SLICE) pCtx->pVpp->AnalyzePictureComplexity (pCtx, pCtx->pEncPic, ((pCtx->eSliceType == P_SLICE)
&& (pCtx->iNumRef0 > 0)) ? pCtx->pRefList0[0] : NULL, && (pCtx->iNumRef0 > 0)) ? pCtx->pRefList0[0] : NULL,
iCurDid, (pCtx->eSliceType == P_SLICE) && pSvcParam->bEnableBackgroundDetection); iCurDid, (pCtx->eSliceType == P_SLICE) && pSvcParam->bEnableBackgroundDetection);
WelsUpdateRefSyntax (pCtx, pCtx->iPOC, WelsUpdateRefSyntax (pCtx, pParamInternal->iPOC,
eFrameType); //get reordering syntax used for writing slice header and transmit to encoder. eFrameType); //get reordering syntax used for writing slice header and transmit to encoder.
PrefetchReferencePicture (pCtx, eFrameType); // update reference picture for current pDq layer PrefetchReferencePicture (pCtx, eFrameType); // update reference picture for current pDq layer
@ -4033,6 +4082,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pLbi->uiQualityId = 0; pLbi->uiQualityId = 0;
pLbi->iNalCount = 0; pLbi->iNalCount = 0;
pLbi->eFrameType = eFrameType; pLbi->eFrameType = eFrameType;
int32_t iIdx = 0; int32_t iIdx = 0;
while (iIdx < kiPartitionCnt) { while (iIdx < kiPartitionCnt) {
pCtx->pSliceThreading->pThreadPEncCtx[iIdx].pFrameBsInfo = pFbi; pCtx->pSliceThreading->pThreadPEncCtx[iIdx].pFrameBsInfo = pFbi;
@ -4252,7 +4302,8 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
++ iLayerNum; ++ iLayerNum;
++ pLayerBsInfo; ++ pLayerBsInfo;
++ pCtx->pOut->iLayerBsIndex; ++ pCtx->pOut->iLayerBsIndex;
WelsLog (pLogCtx, WELS_LOG_DEBUG,
"WelsEncoderEncodeExt() test iLayerNum = %d,iCountNal = %d,iLayerSize = %d", iLayerNum, iCountNal, iLayerSize);
pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer; pLayerBsInfo->pBsBuf = pCtx->pFrameBs + pCtx->iPosBsBuffer;
pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal; pLayerBsInfo->pNalLengthInByte = (pLayerBsInfo - 1)->pNalLengthInByte + iCountNal;
@ -4321,6 +4372,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
&& (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DIRECT_MARK)) || eFrameType == videoFrameTypeIDR)) { && (pCtx->pLtr[pCtx->uiDependencyId].iLTRMarkMode == LTR_DIRECT_MARK)) || eFrameType == videoFrameTypeIDR)) {
pCtx->bRefOfCurTidIsLtr[iDidIdx][iCurTid] = true; pCtx->bRefOfCurTidIsLtr[iDidIdx][iCurTid] = true;
} }
++ pParamInternal->iCodingIndex;
}//end of (iSpatialIdx/iSpatialNum) }//end of (iSpatialIdx/iSpatialNum)
if (ENC_RETURN_CORRECTED == pCtx->iEncoderError) { if (ENC_RETURN_CORRECTED == pCtx->iEncoderError) {
@ -4361,7 +4413,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
return 1; return 1;
} }
++ pCtx->iCodingIndex;
pFbi->iLayerNum = iLayerNum; pFbi->iLayerNum = iLayerNum;
pFbi->iSubSeqId = GetSubSequenceId (pCtx, eFrameType); pFbi->iSubSeqId = GetSubSequenceId (pCtx, eFrameType);
@ -4370,13 +4422,19 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
pFbi->iSubSeqId, iFrameSize); pFbi->iSubSeqId, iFrameSize);
for (int32_t i = 0; i < iLayerNum; i++) for (int32_t i = 0; i < iLayerNum; i++)
WelsLog (pLogCtx, WELS_LOG_DEBUG, WelsLog (pLogCtx, WELS_LOG_DEBUG,
"WelsEncoderEncodeExt() OutputInfo iLayerId = %d,iNalType = %d,iNalCount = %d, first Nal Length=%d", i, "WelsEncoderEncodeExt() OutputInfo iLayerId = %d,iNalType = %d,iNalCount = %d, first Nal Length=%d,uiSpatialId = %d", i,
pFbi->sLayerInfo[i].uiLayerType, pFbi->sLayerInfo[i].iNalCount, pFbi->sLayerInfo[i].pNalLengthInByte[0]); pFbi->sLayerInfo[i].uiLayerType, pFbi->sLayerInfo[i].iNalCount, pFbi->sLayerInfo[i].pNalLengthInByte[0],
pFbi->sLayerInfo[i].uiSpatialId);
WelsEmms(); WelsEmms();
pFbi->eFrameType = eFrameType; pLayerBsInfo->eFrameType = eFrameType;
pFbi->iFrameSizeInBytes = iFrameSize; pFbi->iFrameSizeInBytes = iFrameSize;
pFbi->eFrameType = eFrameType;
for (int32_t k = 0; k < pFbi->iLayerNum; k++) {
if (pFbi->eFrameType != pFbi->sLayerInfo[k].eFrameType) {
pFbi->eFrameType = videoFrameTypeIPMixed;
}
}
#ifdef _DEBUG #ifdef _DEBUG
if (pFbi->iLayerNum > MAX_LAYER_NUM_OF_FRAME) { if (pFbi->iLayerNum > MAX_LAYER_NUM_OF_FRAME) {
WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!", WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR, "WelsEncoderEncodeExt(), iLayerNum(%d) > MAX_LAYER_NUM_OF_FRAME(%d)!",
@ -4402,7 +4460,7 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
return ENC_RETURN_UNEXPECTED; return ENC_RETURN_UNEXPECTED;
} }
#endif #endif
WelsLog (& pCtx->sLogCtx, WELS_LOG_INFO, "return ENC_RETURN_SUCCESS");
return ENC_RETURN_SUCCESS; return ENC_RETURN_SUCCESS;
} }
@ -4565,9 +4623,8 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
// reset the scaled spatial picture size // reset the scaled spatial picture size
(*ppCtx)->pVpp->WelsPreprocessReset (*ppCtx); (*ppCtx)->pVpp->WelsPreprocessReset (*ppCtx);
//if WelsInitEncoderExt succeed //if WelsInitEncoderExt succeed
//for LTR //for LTR
(*ppCtx)->uiIdrPicId = uiTmpIdrPicId; (*ppCtx)->uiIdrPicId = uiTmpIdrPicId ;//this is for LTR!; //this is for LTR!
//for sEncoderStatistics //for sEncoderStatistics
memcpy ((*ppCtx)->sEncoderStatistics, sTempEncoderStatistics, sizeof (sTempEncoderStatistics)); memcpy ((*ppCtx)->sEncoderStatistics, sTempEncoderStatistics, sizeof (sTempEncoderStatistics));
@ -4601,7 +4658,8 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
pOldParam->uiGopSize = pNewParam->uiGopSize; pOldParam->uiGopSize = pNewParam->uiGopSize;
if (pOldParam->iTemporalLayerNum != pNewParam->iTemporalLayerNum) { if (pOldParam->iTemporalLayerNum != pNewParam->iTemporalLayerNum) {
pOldParam->iTemporalLayerNum = pNewParam->iTemporalLayerNum; pOldParam->iTemporalLayerNum = pNewParam->iTemporalLayerNum;
(*ppCtx)->iCodingIndex = 0; for (int32_t iIndexD = 0; iIndexD < MAX_DEPENDENCY_LAYER; iIndexD++)
pOldParam->sDependencyLayers[iIndexD].iCodingIndex = 0;
} }
pOldParam->iDecompStages = pNewParam->iDecompStages; pOldParam->iDecompStages = pNewParam->iDecompStages;
/* denoise control */ /* denoise control */
@ -4663,7 +4721,6 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
memcpy (pOldDlpInternal->uiCodingIdx2TemporalId, pNewDlpInternal->uiCodingIdx2TemporalId, memcpy (pOldDlpInternal->uiCodingIdx2TemporalId, pNewDlpInternal->uiCodingIdx2TemporalId,
sizeof (pOldDlpInternal->uiCodingIdx2TemporalId)); // confirmed_safe_unsafe_usage sizeof (pOldDlpInternal->uiCodingIdx2TemporalId)); // confirmed_safe_unsafe_usage
++ iIndexD; ++ iIndexD;
} while (iIndexD < pOldParam->iSpatialLayerNum); } while (iIndexD < pOldParam->iSpatialLayerNum);
} }

View File

@ -685,6 +685,7 @@ void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) {
SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc; SRCTemporal* pTOverRc = pWelsSvcRc->pTemporalOverRc;
const int32_t kiOutputBits = pWelsSvcRc->iBitsPerFrame; const int32_t kiOutputBits = pWelsSvcRc->iBitsPerFrame;
const int32_t kiOutputMaxBits = pWelsSvcRc->iMaxBitsPerFrame; const int32_t kiOutputMaxBits = pWelsSvcRc->iMaxBitsPerFrame;
SSpatialLayerInternal* pDLayerParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
//condition 1: whole pBuffer fullness //condition 1: whole pBuffer fullness
pWelsSvcRc->iBufferFullnessSkip += (pWelsSvcRc->iFrameDqBits - kiOutputBits); pWelsSvcRc->iBufferFullnessSkip += (pWelsSvcRc->iFrameDqBits - kiOutputBits);
pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] += (pWelsSvcRc->iFrameDqBits - kiOutputMaxBits); pWelsSvcRc->iBufferMaxBRFullness[EVEN_TIME_WINDOW] += (pWelsSvcRc->iFrameDqBits - kiOutputMaxBits);
@ -704,7 +705,7 @@ void RcVBufferCalculationSkip (sWelsEncCtx* pEncCtx) {
if ((pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip if ((pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip
&& pWelsSvcRc->iAverageFrameQp > pWelsSvcRc->iSkipQpValue) && pWelsSvcRc->iAverageFrameQp > pWelsSvcRc->iSkipQpValue)
|| (dIncPercent > pWelsSvcRc->iRcVaryPercentage)) { || (dIncPercent > pWelsSvcRc->iRcVaryPercentage)) {
pEncCtx->iSkipFrameFlag = 1; pDLayerParamInternal->iSkipFrameFlag = 1;
} }
} }
void WelsRcFrameDelayJudge (sWelsEncCtx* pEncCtx, EVideoFrameType eFrameType, long long uiTimeStamp) { void WelsRcFrameDelayJudge (sWelsEncCtx* pEncCtx, EVideoFrameType eFrameType, long long uiTimeStamp) {
@ -772,35 +773,38 @@ void WelsRcFrameDelayJudge (sWelsEncCtx* pEncCtx, EVideoFrameType eFrameType, lo
//loop each layer to check if have skip frame when RC and frame skip enable (maxbr>0) //loop each layer to check if have skip frame when RC and frame skip enable (maxbr>0)
bool CheckFrameSkipBasedMaxbr (sWelsEncCtx* pEncCtx, int32_t iSpatialNum, EVideoFrameType eFrameType, bool CheckFrameSkipBasedMaxbr (sWelsEncCtx* pEncCtx, int32_t iSpatialNum, EVideoFrameType eFrameType,
const uint32_t uiTimeStamp) { const uint32_t uiTimeStamp) {
SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0];
bool bSkipMustFlag = false; bool bSkipMustFlag = false;
if (!pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge) if (!pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge)
return false; return false;
for (int32_t i = 0; i < iSpatialNum; i++) { if( pEncCtx->pSvcParam->bSimulcastAVC){
if (UNSPECIFIED_BIT_RATE == pEncCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate) { int32_t iDidIdx = pEncCtx->uiDependencyId;
break; if (UNSPECIFIED_BIT_RATE == pEncCtx->pSvcParam->sSpatialLayers[iDidIdx].iMaxSpatialBitrate)
} return false;
pEncCtx->uiDependencyId = (uint8_t) (pSpatialIndexMap + i)->iDid;
pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp); pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp);
if (true == pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId].bSkipFlag) { if (true == pEncCtx->pWelsSvcRc[iDidIdx].bSkipFlag) {
bSkipMustFlag = true; bSkipMustFlag = true;
pEncCtx->iContinualSkipFrames++; pEncCtx->pWelsSvcRc[iDidIdx].uiLastTimeStamp = uiTimeStamp;
break; pEncCtx->iContinualSkipFrames++;
}
}else{
for(int32_t i = 0;i<iSpatialNum;i++){
if (UNSPECIFIED_BIT_RATE == pEncCtx->pSvcParam->sSpatialLayers[i].iMaxSpatialBitrate)
break;
pEncCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge (pEncCtx, eFrameType, uiTimeStamp);
if (true == pEncCtx->pWelsSvcRc[i].bSkipFlag) {
bSkipMustFlag = true;
pEncCtx->pWelsSvcRc[i].uiLastTimeStamp = uiTimeStamp;
pEncCtx->iContinualSkipFrames++;
break;
}
} }
}
if (bSkipMustFlag) {
for (int32_t i = 0; i < iSpatialNum; i++)
pEncCtx->pWelsSvcRc[i].uiLastTimeStamp = uiTimeStamp;
} }
return bSkipMustFlag; return bSkipMustFlag;
} }
void UpdateBufferWhenFrameSkipped (sWelsEncCtx* pEncCtx, int32_t iSpatialNum) { void UpdateBufferWhenFrameSkipped (sWelsEncCtx* pEncCtx, int32_t iCurDid) {
SSpatialPicIndex* pSpatialIndexMap = &pEncCtx->sSpatialIndexMap[0];
for (int32_t i = 0; i < iSpatialNum; i++) {
int32_t iCurDid = (pSpatialIndexMap + i)->iDid;
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[iCurDid]; SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[iCurDid];
const int32_t kiOutputBits = pWelsSvcRc->iBitsPerFrame; const int32_t kiOutputBits = pWelsSvcRc->iBitsPerFrame;
const int32_t kiOutputMaxBits = pWelsSvcRc->iMaxBitsPerFrame; const int32_t kiOutputMaxBits = pWelsSvcRc->iMaxBitsPerFrame;
@ -817,7 +821,6 @@ void UpdateBufferWhenFrameSkipped (sWelsEncCtx* pEncCtx, int32_t iSpatialNum) {
pWelsSvcRc->iSkipFrameNum++; pWelsSvcRc->iSkipFrameNum++;
pWelsSvcRc->iSkipFrameInVGop++; pWelsSvcRc->iSkipFrameInVGop++;
}
pEncCtx->iContinualSkipFrames++; pEncCtx->iContinualSkipFrames++;
if ((pEncCtx->iContinualSkipFrames % 3) == 0) { if ((pEncCtx->iContinualSkipFrames % 3) == 0) {
//output a warning when iContinualSkipFrames is large enough, which may indicate subjective quality problem //output a warning when iContinualSkipFrames is large enough, which may indicate subjective quality problem
@ -906,7 +909,7 @@ void RcVBufferCalculationPadding (sWelsEncCtx* pEncCtx) {
void RcTraceFrameBits (sWelsEncCtx* pEncCtx, long long uiTimeStamp) { void RcTraceFrameBits (sWelsEncCtx* pEncCtx, long long uiTimeStamp) {
SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
SSpatialLayerInternal *pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
if (pWelsSvcRc->iPredFrameBit != 0) if (pWelsSvcRc->iPredFrameBit != 0)
pWelsSvcRc->iPredFrameBit = (int32_t) (LAST_FRAME_PREDICT_WEIGHT * pWelsSvcRc->iFrameDqBits + pWelsSvcRc->iPredFrameBit = (int32_t) (LAST_FRAME_PREDICT_WEIGHT * pWelsSvcRc->iFrameDqBits +
(1 - LAST_FRAME_PREDICT_WEIGHT) * pWelsSvcRc->iPredFrameBit); (1 - LAST_FRAME_PREDICT_WEIGHT) * pWelsSvcRc->iPredFrameBit);
@ -919,7 +922,7 @@ void RcTraceFrameBits (sWelsEncCtx* pEncCtx, long long uiTimeStamp) {
pEncCtx->uiDependencyId, uiTimeStamp, pEncCtx->eSliceType, pEncCtx->iGlobalQp, pWelsSvcRc->iAverageFrameQp, pEncCtx->uiDependencyId, uiTimeStamp, pEncCtx->eSliceType, pEncCtx->iGlobalQp, pWelsSvcRc->iAverageFrameQp,
pWelsSvcRc->iMaxFrameQp, pWelsSvcRc->iMaxFrameQp,
pWelsSvcRc->iMinFrameQp, pWelsSvcRc->iMinFrameQp,
pEncCtx->iFrameIndex, pEncCtx->uiTemporalId, pWelsSvcRc->iFrameDqBits, pWelsSvcRc->iBitsPerFrame, pParamInternal->iFrameIndex, pEncCtx->uiTemporalId, pWelsSvcRc->iFrameDqBits, pWelsSvcRc->iBitsPerFrame,
pWelsSvcRc->iTargetBits, pWelsSvcRc->iRemainingBits, pWelsSvcRc->iBufferSizeSkip); pWelsSvcRc->iTargetBits, pWelsSvcRc->iRemainingBits, pWelsSvcRc->iBufferSizeSkip);
} }

View File

@ -155,6 +155,7 @@ static inline void DeleteInvalidLTR (sWelsEncCtx* pCtx) {
SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId]; SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum); int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
int32_t i; int32_t i;
SSpatialLayerInternal *pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
SLogContext* pLogCtx = & (pCtx->sLogCtx); SLogContext* pLogCtx = & (pCtx->sLogCtx);
for (i = 0; i < LONG_TERM_REF_NUM; i++) { for (i = 0; i < LONG_TERM_REF_NUM; i++) {
@ -168,7 +169,7 @@ static inline void DeleteInvalidLTR (sWelsEncCtx* pCtx) {
DeleteLTRFromLongList (pCtx, i); DeleteLTRFromLongList (pCtx, i);
pLtr->bLTRMarkEnable = true; pLtr->bLTRMarkEnable = true;
if (pRefList->uiLongRefCount == 0) { if (pRefList->uiLongRefCount == 0) {
pCtx->bEncCurFrmAsIdrFlag = true; pParamInternal->bEncCurFrmAsIdrFlag = true;
} }
} else if (CompareFrameNum (pLongRefList[i]->iMarkFrameNum , pLtr->iLastCorFrameNumDec , } else if (CompareFrameNum (pLongRefList[i]->iMarkFrameNum , pLtr->iLastCorFrameNumDec ,
iMaxFrameNumPlus1) == FRAME_NUM_BIGGER iMaxFrameNumPlus1) == FRAME_NUM_BIGGER
@ -181,7 +182,7 @@ static inline void DeleteInvalidLTR (sWelsEncCtx* pCtx) {
DeleteLTRFromLongList (pCtx, i); DeleteLTRFromLongList (pCtx, i);
pLtr->bLTRMarkEnable = true; pLtr->bLTRMarkEnable = true;
if (pRefList->uiLongRefCount == 0) { if (pRefList->uiLongRefCount == 0) {
pCtx->bEncCurFrmAsIdrFlag = true; pParamInternal->bEncCurFrmAsIdrFlag = true;
} }
} }
} }
@ -195,12 +196,13 @@ static inline void HandleLTRMarkFeedback (sWelsEncCtx* pCtx) {
SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId]; SRefList* pRefList = pCtx->ppRefPicListExt[pCtx->uiDependencyId];
SPicture** pLongRefList = pRefList->pLongRefList; SPicture** pLongRefList = pRefList->pLongRefList;
SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId]; SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
SSpatialLayerInternal *pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
int32_t i, j; int32_t i, j;
if (pLtr->uiLtrMarkState == LTR_MARKING_SUCCESS) { if (pLtr->uiLtrMarkState == LTR_MARKING_SUCCESS) {
WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,
"pLtr->uiLtrMarkState = %d, pLtr.iCurLtrIdx = %d , pLtr->iLtrMarkFbFrameNum = %d ,pCtx->iFrameNum = %d ", "pLtr->uiLtrMarkState = %d, pLtr.iCurLtrIdx = %d , pLtr->iLtrMarkFbFrameNum = %d ,pCtx->iFrameNum = %d ",
pLtr->uiLtrMarkState, pLtr->iCurLtrIdx, pLtr->iLtrMarkFbFrameNum, pCtx->iFrameNum); pLtr->uiLtrMarkState, pLtr->iCurLtrIdx, pLtr->iLtrMarkFbFrameNum, pParamInternal->iFrameNum);
for (i = 0; i < pRefList->uiLongRefCount; i++) { for (i = 0; i < pRefList->uiLongRefCount; i++) {
if (pLongRefList[i]->iFrameNum == pLtr->iLtrMarkFbFrameNum && pLongRefList[i]->uiRecieveConfirmed != RECIEVE_SUCCESS) { if (pLongRefList[i]->iFrameNum == pLtr->iLtrMarkFbFrameNum && pLongRefList[i]->uiRecieveConfirmed != RECIEVE_SUCCESS) {
@ -239,7 +241,7 @@ static inline void HandleLTRMarkFeedback (sWelsEncCtx* pCtx) {
pLtr->bLTRMarkEnable = true; pLtr->bLTRMarkEnable = true;
if (pLtr->iLTRMarkSuccessNum == 0) { if (pLtr->iLTRMarkSuccessNum == 0) {
pCtx->bEncCurFrmAsIdrFlag = true; // no LTR , means IDR recieve failed, force next frame IDR pParamInternal->bEncCurFrmAsIdrFlag = true; // no LTR , means IDR recieve failed, force next frame IDR
} }
} }
} }
@ -256,6 +258,7 @@ static inline void LTRMarkProcess (sWelsEncCtx* pCtx) {
int32_t i = 0; int32_t i = 0;
int32_t j = 0; int32_t j = 0;
bool bMoveLtrFromShortToLong = false; bool bMoveLtrFromShortToLong = false;
SSpatialLayerInternal *pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
if (pCtx->eSliceType == I_SLICE) { if (pCtx->eSliceType == I_SLICE) {
i = 0; i = 0;
@ -265,7 +268,7 @@ static inline void LTRMarkProcess (sWelsEncCtx* pCtx) {
if (pLtr->iLTRMarkMode == LTR_DELAY_MARK) { if (pLtr->iLTRMarkMode == LTR_DELAY_MARK) {
for (i = 0; i < pRefList->uiShortRefCount; i++) { for (i = 0; i < pRefList->uiShortRefCount; i++) {
if (CompareFrameNum (pCtx->iFrameNum, pShortRefList[i]->iFrameNum + iGoPFrameNumInterval, if (CompareFrameNum (pParamInternal->iFrameNum, pShortRefList[i]->iFrameNum + iGoPFrameNumInterval,
iMaxFrameNumPlus1) == FRAME_NUM_EQUAL) { iMaxFrameNumPlus1) == FRAME_NUM_EQUAL) {
break; break;
} }
@ -276,7 +279,7 @@ static inline void LTRMarkProcess (sWelsEncCtx* pCtx) {
if (pCtx->eSliceType == I_SLICE || pLtr->bLTRMarkingFlag) { if (pCtx->eSliceType == I_SLICE || pLtr->bLTRMarkingFlag) {
pShortRefList[i]->bIsLongRef = true; pShortRefList[i]->bIsLongRef = true;
pShortRefList[i]->iLongTermPicNum = pLtr->iCurLtrIdx; pShortRefList[i]->iLongTermPicNum = pLtr->iCurLtrIdx;
pShortRefList[i]->iMarkFrameNum = pCtx->iFrameNum; pShortRefList[i]->iMarkFrameNum = pParamInternal->iFrameNum;
} }
// delay one gop to move LTR from int16_t list to int32_t list // delay one gop to move LTR from int16_t list to int32_t list
@ -376,8 +379,8 @@ bool WelsUpdateRefList (sWelsEncCtx* pCtx) {
// move picture in list // move picture in list
pCtx->pDecPic->uiTemporalId = kuiTid; pCtx->pDecPic->uiTemporalId = kuiTid;
pCtx->pDecPic->uiSpatialId = kuiDid; pCtx->pDecPic->uiSpatialId = kuiDid;
pCtx->pDecPic->iFrameNum = pCtx->iFrameNum; pCtx->pDecPic->iFrameNum = pParamD->iFrameNum;
pCtx->pDecPic->iFramePoc = pCtx->iPOC; pCtx->pDecPic->iFramePoc = pParamD->iPOC;
pCtx->pDecPic->uiRecieveConfirmed = RECIEVE_UNKOWN; pCtx->pDecPic->uiRecieveConfirmed = RECIEVE_UNKOWN;
pCtx->pDecPic->bUsedAsRef = true; pCtx->pDecPic->bUsedAsRef = true;
@ -405,7 +408,7 @@ bool WelsUpdateRefList (sWelsEncCtx* pCtx) {
DeleteSTRFromShortList (pCtx, i); DeleteSTRFromShortList (pCtx, i);
} }
if (pRefList->uiShortRefCount > 0 && (pRefList->pShortRefList[0]->uiTemporalId > 0 if (pRefList->uiShortRefCount > 0 && (pRefList->pShortRefList[0]->uiTemporalId > 0
|| pRefList->pShortRefList[0]->iFrameNum != pCtx->iFrameNum)) { || pRefList->pShortRefList[0]->iFrameNum != pParamD->iFrameNum)) {
pRefList->pShortRefList[0]->SetUnref(); pRefList->pShortRefList[0]->SetUnref();
DeleteSTRFromShortList (pCtx, 0); DeleteSTRFromShortList (pCtx, 0);
} }
@ -433,11 +436,12 @@ bool CheckCurMarkFrameNumUsed (sWelsEncCtx* pCtx) {
SPicture** pLongRefList = pRefList->pLongRefList; SPicture** pLongRefList = pRefList->pLongRefList;
int32_t iGoPFrameNumInterval = ((pCtx->pSvcParam->uiGopSize >> 1) > 1) ? (pCtx->pSvcParam->uiGopSize >> 1) : (1); int32_t iGoPFrameNumInterval = ((pCtx->pSvcParam->uiGopSize >> 1) > 1) ? (pCtx->pSvcParam->uiGopSize >> 1) : (1);
int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum); int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
SSpatialLayerInternal *pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
int32_t i; int32_t i;
for (i = 0; i < pRefList->uiLongRefCount; i++) { for (i = 0; i < pRefList->uiLongRefCount; i++) {
if ((pCtx->iFrameNum == pLongRefList[i]->iFrameNum && pLtr->iLTRMarkMode == LTR_DIRECT_MARK) || if ((pParamInternal->iFrameNum == pLongRefList[i]->iFrameNum && pLtr->iLTRMarkMode == LTR_DIRECT_MARK) ||
(CompareFrameNum (pCtx->iFrameNum + iGoPFrameNumInterval, pLongRefList[i]->iFrameNum, (CompareFrameNum (pParamInternal->iFrameNum + iGoPFrameNumInterval, pLongRefList[i]->iFrameNum,
iMaxFrameNumPlus1) == FRAME_NUM_EQUAL && pLtr->iLTRMarkMode == LTR_DELAY_MARK)) { iMaxFrameNumPlus1) == FRAME_NUM_EQUAL && pLtr->iLTRMarkMode == LTR_DELAY_MARK)) {
return false; return false;
} }
@ -513,10 +517,11 @@ int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRec
SLTRRecoverRequest* pRequest = pLTRRecoverRequest; SLTRRecoverRequest* pRequest = pLTRRecoverRequest;
SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId]; SLTRState* pLtr = &pCtx->pLtr[pCtx->uiDependencyId];
int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum); int32_t iMaxFrameNumPlus1 = (1 << pCtx->pSps->uiLog2MaxFrameNum);
SSpatialLayerInternal* pParamInternal = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
if (pCtx->pSvcParam->bEnableLongTermReference) { if (pCtx->pSvcParam->bEnableLongTermReference) {
if (pRequest->uiFeedbackType == LTR_RECOVERY_REQUEST && pRequest->uiIDRPicId == pCtx->uiIdrPicId) { if (pRequest->uiFeedbackType == LTR_RECOVERY_REQUEST && pRequest->uiIDRPicId == pCtx->uiIdrPicId) {
if (pRequest->iLastCorrectFrameNum == -1) { if (pRequest->iLastCorrectFrameNum == -1) {
pCtx->bEncCurFrmAsIdrFlag = true; pParamInternal->bEncCurFrmAsIdrFlag = true;
return true; return true;
} else if (pRequest->iCurrentFrameNum == -1) { } else if (pRequest->iCurrentFrameNum == -1) {
pLtr->bReceivedT0LostFlag = true; pLtr->bReceivedT0LostFlag = true;
@ -541,7 +546,7 @@ int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRec
, pRequest->uiFeedbackType, pRequest->uiIDRPicId, pRequest->iCurrentFrameNum, pRequest->iLastCorrectFrameNum); , pRequest->uiFeedbackType, pRequest->uiIDRPicId, pRequest->iCurrentFrameNum, pRequest->iLastCorrectFrameNum);
} }
} else if (!pCtx->pSvcParam->bEnableLongTermReference) { } else if (!pCtx->pSvcParam->bEnableLongTermReference) {
pCtx->bEncCurFrmAsIdrFlag = true; pParamInternal->bEncCurFrmAsIdrFlag = true;
} }
return true; return true;
} }
@ -577,7 +582,7 @@ bool WelsBuildRefList (sWelsEncCtx* pCtx, const int32_t iPOC, int32_t iBestLtrRe
const int32_t kiNumRef = pCtx->pSvcParam->iNumRefFrame; const int32_t kiNumRef = pCtx->pSvcParam->iNumRefFrame;
const uint8_t kuiTid = pCtx->uiTemporalId; const uint8_t kuiTid = pCtx->uiTemporalId;
uint32_t i = 0; uint32_t i = 0;
SSpatialLayerInternal* pParamD = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
// to support any type of cur_dq->mgs_control // to support any type of cur_dq->mgs_control
// [ 0: using current layer to do ME/MC; // [ 0: using current layer to do ME/MC;
// -1: using store base layer to do ME/MC; // -1: using store base layer to do ME/MC;
@ -586,13 +591,12 @@ bool WelsBuildRefList (sWelsEncCtx* pCtx, const int32_t iPOC, int32_t iBestLtrRe
// build reference list 0/1 if applicable // build reference list 0/1 if applicable
pCtx->iNumRef0 = 0; pCtx->iNumRef0 = 0;
if (pCtx->eSliceType != I_SLICE) { if (pCtx->eSliceType != I_SLICE) {
if (pCtx->pSvcParam->bEnableLongTermReference && pLtr->bReceivedT0LostFlag && pCtx->uiTemporalId == 0) { if (pCtx->pSvcParam->bEnableLongTermReference && pLtr->bReceivedT0LostFlag && pCtx->uiTemporalId == 0) {
for (i = 0; i < pRefList->uiLongRefCount; i++) { for (i = 0; i < pRefList->uiLongRefCount; i++) {
if (pRefList->pLongRefList[i]->uiRecieveConfirmed == RECIEVE_SUCCESS) { if (pRefList->pLongRefList[i]->uiRecieveConfirmed == RECIEVE_SUCCESS) {
pCtx->pRefList0[pCtx->iNumRef0++] = pRefList->pLongRefList[i]; pCtx->pRefList0[pCtx->iNumRef0++] = pRefList->pLongRefList[i];
pLtr->iLastRecoverFrameNum = pCtx->iFrameNum; pLtr->iLastRecoverFrameNum = pParamD->iFrameNum;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
"pRef is int32_t !iLastRecoverFrameNum = %d, pRef iFrameNum = %d,LTR number = %d,", "pRef is int32_t !iLastRecoverFrameNum = %d, pRef iFrameNum = %d,LTR number = %d,",
pLtr->iLastRecoverFrameNum, pCtx->pRefList0[0]->iFrameNum, pRefList->uiLongRefCount); pLtr->iLastRecoverFrameNum, pCtx->pRefList0[0]->iFrameNum, pRefList->uiLongRefCount);
@ -690,18 +694,18 @@ void WelsUpdateRefSyntax (sWelsEncCtx* pCtx, const int32_t iPOC, const int32_t u
int32_t iAbsDiffPicNumMinus1 = -1; int32_t iAbsDiffPicNumMinus1 = -1;
SSlice* pSliceList = NULL; SSlice* pSliceList = NULL;
SSpatialLayerInternal* pParamD = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
/*syntax for ref_pic_list_reordering()*/ /*syntax for ref_pic_list_reordering()*/
if (pCtx->iNumRef0 > 0) { if (pCtx->iNumRef0 > 0){
iAbsDiffPicNumMinus1 = pCtx->iFrameNum - (pCtx->pRefList0[0]->iFrameNum) - 1; iAbsDiffPicNumMinus1 = pParamD->iFrameNum - (pCtx->pRefList0[0]->iFrameNum) - 1;
if (iAbsDiffPicNumMinus1 < 0) { if (iAbsDiffPicNumMinus1 < 0) {
WelsLog(&(pCtx->sLogCtx), WELS_LOG_INFO, "WelsUpdateRefSyntax():::uiAbsDiffPicNumMinus1:%d", iAbsDiffPicNumMinus1); WelsLog(&(pCtx->sLogCtx), WELS_LOG_INFO, "WelsUpdateRefSyntax():::uiAbsDiffPicNumMinus1:%d", iAbsDiffPicNumMinus1);
iAbsDiffPicNumMinus1 += (1 << (pCtx->pSps->uiLog2MaxFrameNum)); iAbsDiffPicNumMinus1 += (1 << (pCtx->pSps->uiLog2MaxFrameNum));
WelsLog(&(pCtx->sLogCtx), WELS_LOG_INFO, "WelsUpdateRefSyntax():::uiAbsDiffPicNumMinus1< 0, update as:%d", WelsLog(&(pCtx->sLogCtx), WELS_LOG_INFO, "WelsUpdateRefSyntax():::uiAbsDiffPicNumMinus1< 0, update as:%d",
iAbsDiffPicNumMinus1); iAbsDiffPicNumMinus1);
}
} }
}
if (pCtx->iActiveThreadsNum >0) { if (pCtx->iActiveThreadsNum >0) {
// to do: will replace with thread based buffer later // to do: will replace with thread based buffer later
@ -772,8 +776,8 @@ bool WelsUpdateRefListScreen (sWelsEncCtx* pCtx) {
// move picture in list // move picture in list
pCtx->pDecPic->uiTemporalId = pCtx->uiTemporalId; pCtx->pDecPic->uiTemporalId = pCtx->uiTemporalId;
pCtx->pDecPic->uiSpatialId = pCtx->uiDependencyId; pCtx->pDecPic->uiSpatialId = pCtx->uiDependencyId;
pCtx->pDecPic->iFrameNum = pCtx->iFrameNum; pCtx->pDecPic->iFrameNum = pParamD->iFrameNum;
pCtx->pDecPic->iFramePoc = pCtx->iPOC; pCtx->pDecPic->iFramePoc = pParamD->iPOC;
pCtx->pDecPic->bUsedAsRef = true; pCtx->pDecPic->bUsedAsRef = true;
pCtx->pDecPic->bIsLongRef = true; pCtx->pDecPic->bIsLongRef = true;
pCtx->pDecPic->bIsSceneLTR = pLtr->bLTRMarkingFlag || (pCtx->pSvcParam->bEnableLongTermReference pCtx->pDecPic->bIsSceneLTR = pLtr->bLTRMarkingFlag || (pCtx->pSvcParam->bEnableLongTermReference
@ -801,6 +805,7 @@ bool WelsBuildRefListScreen (sWelsEncCtx* pCtx, const int32_t iPOC, int32_t iBes
SWelsSvcCodingParam* pParam = pCtx->pSvcParam; SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa); SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
const int32_t iNumRef = pParam->iNumRefFrame; const int32_t iNumRef = pParam->iNumRefFrame;
SSpatialLayerInternal* pParamD = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
pCtx->iNumRef0 = 0; pCtx->iNumRef0 = 0;
if (pCtx->eSliceType != I_SLICE) { if (pCtx->eSliceType != I_SLICE) {
@ -816,7 +821,7 @@ bool WelsBuildRefListScreen (sWelsEncCtx* pCtx, const int32_t iPOC, int32_t iBes
pCtx->pRefList0[pCtx->iNumRef0++] = pRefPic; pCtx->pRefList0[pCtx->iNumRef0++] = pRefPic;
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"WelsBuildRefListScreen(), current iFrameNum = %d, current Tid = %d, ref iFrameNum = %d, ref uiTemporalId = %d, ref is Scene LTR = %d, LTR count = %d,iNumRef = %d", "WelsBuildRefListScreen(), current iFrameNum = %d, current Tid = %d, ref iFrameNum = %d, ref uiTemporalId = %d, ref is Scene LTR = %d, LTR count = %d,iNumRef = %d",
pCtx->iFrameNum, pCtx->uiTemporalId, pParamD->iFrameNum, pCtx->uiTemporalId,
pRefPic->iFrameNum, pRefPic->uiTemporalId, pRefPic->bIsSceneLTR, pRefPic->iFrameNum, pRefPic->uiTemporalId, pRefPic->bIsSceneLTR,
pRefList->uiLongRefCount, iNumRef); pRefList->uiLongRefCount, iNumRef);
} }
@ -831,7 +836,7 @@ bool WelsBuildRefListScreen (sWelsEncCtx* pCtx, const int32_t iPOC, int32_t iBes
pCtx->pRefList0[pCtx->iNumRef0++] = pRefList->pLongRefList[i]; pCtx->pRefList0[pCtx->iNumRef0++] = pRefList->pLongRefList[i];
WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG, WelsLog (& (pCtx->sLogCtx), WELS_LOG_DEBUG,
"WelsBuildRefListScreen(), ref !current iFrameNum = %d, ref iFrameNum = %d,LTR number = %d", "WelsBuildRefListScreen(), ref !current iFrameNum = %d, ref iFrameNum = %d,LTR number = %d",
pCtx->iFrameNum, pCtx->pRefList0[pCtx->iNumRef0 - 1]->iFrameNum, pRefList->uiLongRefCount); pParamD->iFrameNum, pCtx->pRefList0[pCtx->iNumRef0 - 1]->iFrameNum, pRefList->uiLongRefCount);
break; break;
} }
} }
@ -902,7 +907,7 @@ void WelsMarkPicScreen (sWelsEncCtx* pCtx) {
int32_t iMaxTid = WELS_LOG2 (pCtx->pSvcParam->uiGopSize); int32_t iMaxTid = WELS_LOG2 (pCtx->pSvcParam->uiGopSize);
int32_t iMaxActualLtrIdx = -1; int32_t iMaxActualLtrIdx = -1;
SSlice* pSliceList = NULL; SSlice* pSliceList = NULL;
SSpatialLayerInternal* pParamD = &pCtx->pSvcParam->sDependencyLayers[pCtx->uiDependencyId];
if (pCtx->pSvcParam->bEnableLongTermReference) if (pCtx->pSvcParam->bEnableLongTermReference)
iMaxActualLtrIdx = pCtx->pSvcParam->iNumRefFrame - STR_ROOM - 1 - WELS_MAX (iMaxTid , 1); iMaxActualLtrIdx = pCtx->pSvcParam->iNumRefFrame - STR_ROOM - 1 - WELS_MAX (iMaxTid , 1);
@ -953,9 +958,9 @@ void WelsMarkPicScreen (sWelsEncCtx* pCtx) {
if (ppLongRefList[i]->bUsedAsRef && ppLongRefList[i]->bIsLongRef && (!ppLongRefList[i]->bIsSceneLTR) if (ppLongRefList[i]->bUsedAsRef && ppLongRefList[i]->bIsLongRef && (!ppLongRefList[i]->bIsSceneLTR)
&& iMaxMultiRefTid == ppLongRefList[i]->uiTemporalId) { && iMaxMultiRefTid == ppLongRefList[i]->uiTemporalId) {
assert (IsValidFrameNum (ppLongRefList[i]->iFrameNum)); // pLtr->iCurLtrIdx must have a value assert (IsValidFrameNum (ppLongRefList[i]->iFrameNum)); // pLtr->iCurLtrIdx must have a value
int32_t iDeltaFrameNum = (pCtx->iFrameNum >= ppLongRefList[i]->iFrameNum) int32_t iDeltaFrameNum = (pParamD->iFrameNum >= ppLongRefList[i]->iFrameNum)
? (pCtx->iFrameNum - ppLongRefList[i]->iFrameNum) ? (pParamD->iFrameNum - ppLongRefList[i]->iFrameNum)
: (pCtx->iFrameNum + iMaxFrameNum - ppLongRefList[i]->iFrameNum); : (pParamD->iFrameNum + iMaxFrameNum - ppLongRefList[i]->iFrameNum);
if (iDeltaFrameNum > iLongestDeltaFrameNum) { if (iDeltaFrameNum > iLongestDeltaFrameNum) {
pLtr->iCurLtrIdx = ppLongRefList[i]->iLongTermPicNum; pLtr->iCurLtrIdx = ppLongRefList[i]->iLongTermPicNum;

View File

@ -679,7 +679,7 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
const int32_t kiFirstMbInPartition = pPrivateData->iStartMbIndex; // inclusive const int32_t kiFirstMbInPartition = pPrivateData->iStartMbIndex; // inclusive
const int32_t kiEndMbInPartition = pPrivateData->iEndMbIndex; // exclusive const int32_t kiEndMbInPartition = pPrivateData->iEndMbIndex; // exclusive
int32_t iAnyMbLeftInPartition = kiEndMbInPartition - kiFirstMbInPartition; int32_t iAnyMbLeftInPartition = kiEndMbInPartition - kiFirstMbInPartition;
SSpatialLayerInternal *pParamInternal = &pCodingParam->sDependencyLayers[kiCurDid];
iSliceIdx = pPrivateData->iSliceIndex; iSliceIdx = pPrivateData->iSliceIndex;
SSliceHeaderExt* pStartSliceHeaderExt = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx].sSliceHeaderExt; SSliceHeaderExt* pStartSliceHeaderExt = &pCurDq->sLayerInfo.pSliceInLayer[iSliceIdx].sSliceHeaderExt;
pStartSliceHeaderExt->sSliceHeader.iFirstMbInSlice = kiFirstMbInPartition; pStartSliceHeaderExt->sSliceHeader.iFirstMbInSlice = kiFirstMbInPartition;
@ -695,7 +695,7 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
uiThrdRet = 1; uiThrdRet = 1;
WelsLog (&pEncPEncCtx->sLogCtx, WELS_LOG_WARNING, WelsLog (&pEncPEncCtx->sLogCtx, WELS_LOG_WARNING,
"[MT] CodingSliceThreadProc Too many slices: coding_idx %d, iSliceIdx %d, pSliceCtx->iMaxSliceNumConstraint %d", "[MT] CodingSliceThreadProc Too many slices: coding_idx %d, iSliceIdx %d, pSliceCtx->iMaxSliceNumConstraint %d",
pEncPEncCtx->iCodingIndex, pParamInternal->iCodingIndex,
iSliceIdx, pSliceCtx->iMaxSliceNumConstraint); iSliceIdx, pSliceCtx->iMaxSliceNumConstraint);
WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent, WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,
pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent, pEncPEncCtx->pSliceThreading->pSliceCodedMasterEvent,
@ -740,7 +740,7 @@ WELS_THREAD_ROUTINE_TYPE CodingSliceThreadProc (void* arg) {
uiThrdRet = iReturn; uiThrdRet = iReturn;
WelsLog (&pEncPEncCtx->sLogCtx, WELS_LOG_WARNING, WelsLog (&pEncPEncCtx->sLogCtx, WELS_LOG_WARNING,
"[MT] CodingSliceThreadProc, WriteSliceBs not successful: coding_idx %d, iSliceIdx %d, BufferSize %d, m_iSliceSize %d, iPayloadSize %d", "[MT] CodingSliceThreadProc, WriteSliceBs not successful: coding_idx %d, iSliceIdx %d, BufferSize %d, m_iSliceSize %d, iPayloadSize %d",
pEncPEncCtx->iCodingIndex, pParamInternal->iCodingIndex,
iSliceIdx, pSliceBs->uiSize, iSliceSize, pSliceBs->sNalList[0].iPayloadSize); iSliceIdx, pSliceBs->uiSize, iSliceSize, pSliceBs->sNalList[0].iPayloadSize);
WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent, WELS_THREAD_SIGNAL_AND_BREAK (pEncPEncCtx->pSliceThreading->pSliceCodedEvent,

View File

@ -89,14 +89,14 @@ void WelsSliceHeaderScalExtInit (SDqLayer* pCurLayer, SSlice* pSlice) {
void WelsSliceHeaderExtInit (sWelsEncCtx* pEncCtx, SDqLayer* pCurLayer, SSlice* pSlice) { void WelsSliceHeaderExtInit (sWelsEncCtx* pEncCtx, SDqLayer* pCurLayer, SSlice* pSlice) {
SSliceHeaderExt* pCurSliceExt = &pSlice->sSliceHeaderExt; SSliceHeaderExt* pCurSliceExt = &pSlice->sSliceHeaderExt;
SSliceHeader* pCurSliceHeader = &pCurSliceExt->sSliceHeader; SSliceHeader* pCurSliceHeader = &pCurSliceExt->sSliceHeader;
SSpatialLayerInternal *pParamInternal = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
pCurSliceHeader->eSliceType = pEncCtx->eSliceType; pCurSliceHeader->eSliceType = pEncCtx->eSliceType;
pCurSliceExt->bStoreRefBasePicFlag = false; pCurSliceExt->bStoreRefBasePicFlag = false;
pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice (pCurLayer->sLayerInfo.pSliceInLayer, pSlice->uiSliceIdx); pCurSliceHeader->iFirstMbInSlice = WelsGetFirstMbOfSlice (pCurLayer->sLayerInfo.pSliceInLayer, pSlice->uiSliceIdx);
pCurSliceHeader->iFrameNum = pEncCtx->iFrameNum; pCurSliceHeader->iFrameNum = pParamInternal->iFrameNum;
pCurSliceHeader->uiIdrPicId = pEncCtx->uiIdrPicId; pCurSliceHeader->uiIdrPicId = pEncCtx->uiIdrPicId;
pCurSliceHeader->iPicOrderCntLsb = pEncCtx->pEncPic->iFramePoc; // 0 pCurSliceHeader->iPicOrderCntLsb = pEncCtx->pEncPic->iFramePoc; // 0

View File

@ -185,8 +185,9 @@ int32_t CWelsPreProcess::BuildSpatialPicList (sWelsEncCtx* pCtx, const SSourcePi
pSvcParam->SUsedPicRect.iTop = 0; pSvcParam->SUsedPicRect.iTop = 0;
pSvcParam->SUsedPicRect.iWidth = ((kpSrcPic->iPicWidth >> 1) << 1); pSvcParam->SUsedPicRect.iWidth = ((kpSrcPic->iPicWidth >> 1) << 1);
pSvcParam->SUsedPicRect.iHeight = ((kpSrcPic->iPicHeight >> 1) << 1); pSvcParam->SUsedPicRect.iHeight = ((kpSrcPic->iPicHeight >> 1) << 1);
if((pSvcParam->SUsedPicRect.iWidth<16)||((pSvcParam->SUsedPicRect.iHeight<16))){ if ((pSvcParam->SUsedPicRect.iWidth < 16) || ((pSvcParam->SUsedPicRect.iHeight < 16))) {
WelsLog ( & (pCtx->sLogCtx), WELS_LOG_ERROR, "Don't support width(%d) or height(%d) which is less than 16 ",pSvcParam->SUsedPicRect.iWidth,pSvcParam->SUsedPicRect.iHeight); WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "Don't support width(%d) or height(%d) which is less than 16 ",
pSvcParam->SUsedPicRect.iWidth, pSvcParam->SUsedPicRect.iHeight);
return -1; return -1;
} }
if (WelsPreprocessReset (pCtx) != 0) if (WelsPreprocessReset (pCtx) != 0)
@ -201,8 +202,6 @@ int32_t CWelsPreProcess::BuildSpatialPicList (sWelsEncCtx* pCtx, const SSourcePi
return -1; return -1;
pCtx->pVaa->bSceneChangeFlag = pCtx->pVaa->bIdrPeriodFlag = false; pCtx->pVaa->bSceneChangeFlag = pCtx->pVaa->bIdrPeriodFlag = false;
if (pSvcParam->uiIntraPeriod)
pCtx->pVaa->bIdrPeriodFlag = (1 + pCtx->iFrameIndex >= (int32_t)pSvcParam->uiIntraPeriod) ? true : false;
iSpatialNum = SingleLayerPreprocess (pCtx, kpSrcPic, &m_sScaledPicture); iSpatialNum = SingleLayerPreprocess (pCtx, kpSrcPic, &m_sScaledPicture);
@ -213,10 +212,10 @@ int32_t CWelsPreProcess::AnalyzeSpatialPic (sWelsEncCtx* pCtx, const int32_t kiD
SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam; SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
bool bNeededMbAq = (pSvcParam->bEnableAdaptiveQuant && (pCtx->eSliceType == P_SLICE)); bool bNeededMbAq = (pSvcParam->bEnableAdaptiveQuant && (pCtx->eSliceType == P_SLICE));
bool bCalculateBGD = (pCtx->eSliceType == P_SLICE && pSvcParam->bEnableBackgroundDetection); bool bCalculateBGD = (pCtx->eSliceType == P_SLICE && pSvcParam->bEnableBackgroundDetection);
SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[kiDidx];
int32_t iCurTemporalIdx = m_uiSpatialLayersInTemporal[kiDidx] - 1; int32_t iCurTemporalIdx = m_uiSpatialLayersInTemporal[kiDidx] - 1;
int32_t iRefTemporalIdx = (int32_t)g_kuiRefTemporalIdx[pSvcParam->iDecompStages][pCtx->iCodingIndex & int32_t iRefTemporalIdx = (int32_t)g_kuiRefTemporalIdx[pSvcParam->iDecompStages][pParamInternal->iCodingIndex &
(pSvcParam->uiGopSize - 1)]; (pSvcParam->uiGopSize - 1)];
if (pCtx->uiTemporalId == 0 && pCtx->pLtr[pCtx->uiDependencyId].bReceivedT0LostFlag) if (pCtx->uiTemporalId == 0 && pCtx->pLtr[pCtx->uiDependencyId].bReceivedT0LostFlag)
iRefTemporalIdx = m_uiSpatialLayersInTemporal[kiDidx] + pCtx->pVaa->uiValidLongTermPicIdx; iRefTemporalIdx = m_uiSpatialLayersInTemporal[kiDidx] + pCtx->pVaa->uiValidLongTermPicIdx;
@ -253,6 +252,9 @@ int32_t CWelsPreProcess::AnalyzeSpatialPic (sWelsEncCtx* pCtx, const int32_t kiD
if (bNeededMbAq) { if (bNeededMbAq) {
SPicture* pCurPic = m_pLastSpatialPicture[kiDidx][1]; SPicture* pCurPic = m_pLastSpatialPicture[kiDidx][1];
SPicture* pRefPic = m_pLastSpatialPicture[kiDidx][0]; SPicture* pRefPic = m_pLastSpatialPicture[kiDidx][0];
//printf("pCurPicDid = %d,pCurPicTid = %d,pRefPicDid = %d,pRefPicTid = %d,kiDidx = %d,pCurPic = %x,pRefPic = %x,bbCurPic = %x\n",
// pCurPic->uiSpatialId,pCurPic->uiTemporalId,pCurPic->uiSpatialId,pCurPic->uiTemporalId,kiDidx,pCurPic,pRefPic,m_pSpatialPic[kiDidx][iCurTemporalIdx]);
AdaptiveQuantCalculation (pCtx->pVaa, pCurPic, pRefPic); AdaptiveQuantCalculation (pCtx->pVaa, pCurPic, pRefPic);
} }
@ -285,6 +287,8 @@ int32_t CWelsPreProcess::UpdateSpatialPictures (sWelsEncCtx* pCtx, SWelsSvcCodin
} }
WelsExchangeSpatialPictures (&m_pSpatialPic[kiDidx][kiCurPos], WelsExchangeSpatialPictures (&m_pSpatialPic[kiDidx][kiCurPos],
&m_pSpatialPic[kiDidx][iCurTid]); &m_pSpatialPic[kiDidx][iCurTid]);
} }
return 0; return 0;
} }
@ -294,6 +298,43 @@ int32_t CWelsPreProcess::UpdateSpatialPictures (sWelsEncCtx* pCtx, SWelsSvcCodin
* SingleLayerPreprocess: down sampling if applicable * SingleLayerPreprocess: down sampling if applicable
* @return: exact number of spatial layers need to encoder indeed * @return: exact number of spatial layers need to encoder indeed
*/ */
bool CWelsPreProcess::BuildSpatialLayer (sWelsEncCtx* pCtx, const SSourcePicture* kpSrc, int32_t iDependencyId) {
SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
int32_t iMaxDid = pSvcParam->iSpatialLayerNum - 1;
SSpatialPicIndex* pSpatialIndexMap = &pCtx->sSpatialIndexMap[0];
SSpatialLayerConfig* pDlayerParam = &pSvcParam->sSpatialLayers[iDependencyId];
SSpatialLayerInternal* pDlayerParamInternal = &pSvcParam->sDependencyLayers[iDependencyId];
int32_t iTemporalId = pDlayerParamInternal->uiCodingIdx2TemporalId[pDlayerParamInternal->iCodingIndex &
(pSvcParam->uiGopSize - 1)];
if (iTemporalId != INVALID_TEMPORAL_ID) {
if (iDependencyId == iMaxDid) {
return true;
} else {
int32_t iPicturePos = m_uiSpatialLayersInTemporal[iDependencyId] - 1;
Scaled_Picture* pScaledPicture = &m_sScaledPicture;
int32_t iSrcWidth = pSvcParam->SUsedPicRect.iWidth;
int32_t iSrcHeight = pSvcParam->SUsedPicRect.iHeight;
int32_t iTargetWidth = pDlayerParam->iVideoWidth;
int32_t iTargetHeight = pDlayerParam->iVideoHeight;
SPicture* pSrcPic = (pSpatialIndexMap + iMaxDid)->pSrc;; // large
SPicture* pDstPic = m_pSpatialPic[iDependencyId][iPicturePos]; // small
int32_t iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId];
int32_t iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId];
DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight,
true);
WelsUpdateSpatialIdxMap (pCtx, iDependencyId, pDstPic, iDependencyId);
m_pLastSpatialPicture[iDependencyId][1] = m_pSpatialPic[iDependencyId][iPicturePos];
return true;
}
}
return false;
}
int32_t CWelsPreProcess::SingleLayerPreprocess (sWelsEncCtx* pCtx, const SSourcePicture* kpSrc, int32_t CWelsPreProcess::SingleLayerPreprocess (sWelsEncCtx* pCtx, const SSourcePicture* kpSrc,
Scaled_Picture* pScaledPicture) { Scaled_Picture* pScaledPicture) {
SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam; SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
@ -310,19 +351,22 @@ int32_t CWelsPreProcess::SingleLayerPreprocess (sWelsEncCtx* pCtx, const SSource
int32_t iTargetWidth = 0; int32_t iTargetWidth = 0;
int32_t iTargetHeight = 0; int32_t iTargetHeight = 0;
int32_t iTemporalId = 0; int32_t iTemporalId = 0;
int32_t iActualSpatialLayerNum = 0;
pDlayerParamInternal = &pSvcParam->sDependencyLayers[iDependencyId]; pDlayerParamInternal = &pSvcParam->sDependencyLayers[iDependencyId];
pDlayerParam = &pSvcParam->sSpatialLayers[iDependencyId]; pDlayerParam = &pSvcParam->sSpatialLayers[iDependencyId];
iTargetWidth = pDlayerParam->iVideoWidth; iTargetWidth = pDlayerParam->iVideoWidth;
iTargetHeight = pDlayerParam->iVideoHeight; iTargetHeight = pDlayerParam->iVideoHeight;
iTemporalId = pDlayerParamInternal->uiCodingIdx2TemporalId[pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1)]; iTemporalId = pDlayerParamInternal->uiCodingIdx2TemporalId[pDlayerParamInternal->iCodingIndex &
(pSvcParam->uiGopSize - 1)];
iSrcWidth = pSvcParam->SUsedPicRect.iWidth; iSrcWidth = pSvcParam->SUsedPicRect.iWidth;
iSrcHeight = pSvcParam->SUsedPicRect.iHeight; iSrcHeight = pSvcParam->SUsedPicRect.iHeight;
if (pSvcParam->uiIntraPeriod)
pCtx->pVaa->bIdrPeriodFlag = (1 + pDlayerParamInternal->iFrameIndex >= (int32_t)pSvcParam->uiIntraPeriod) ? true :
false;
pSrcPic = pScaledPicture->pScaledInputPicture ? pScaledPicture->pScaledInputPicture : pSrcPic = pScaledPicture->pScaledInputPicture ? pScaledPicture->pScaledInputPicture :
m_pSpatialPic[iDependencyId][iPicturePos]; m_pSpatialPic[iDependencyId][iPicturePos];
WelsMoveMemoryWrapper (pSvcParam, pSrcPic, kpSrc, iSrcWidth, iSrcHeight); WelsMoveMemoryWrapper (pSvcParam, pSrcPic, kpSrc, iSrcWidth, iSrcHeight);
if (pSvcParam->bEnableDenoise) if (pSvcParam->bEnableDenoise)
@ -343,11 +387,13 @@ int32_t CWelsPreProcess::SingleLayerPreprocess (sWelsEncCtx* pCtx, const SSource
if (pSvcParam->bEnableSceneChangeDetect && !pCtx->pVaa->bIdrPeriodFlag) { if (pSvcParam->bEnableSceneChangeDetect && !pCtx->pVaa->bIdrPeriodFlag) {
if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) { if (pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
pCtx->pVaa->eSceneChangeIdc = (pCtx->bEncCurFrmAsIdrFlag ? LARGE_CHANGED_SCENE : DetectSceneChangeScreen (pCtx, pCtx->pVaa->eSceneChangeIdc = (pDlayerParamInternal->bEncCurFrmAsIdrFlag ? LARGE_CHANGED_SCENE :
pDstPic)); DetectSceneChangeScreen (pCtx,
pDstPic));
pCtx->pVaa->bSceneChangeFlag = (LARGE_CHANGED_SCENE == pCtx->pVaa->eSceneChangeIdc); pCtx->pVaa->bSceneChangeFlag = (LARGE_CHANGED_SCENE == pCtx->pVaa->eSceneChangeIdc);
} else { } else {
if ((!pCtx->bEncCurFrmAsIdrFlag) && ! (pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1))) { if ((!pDlayerParamInternal->bEncCurFrmAsIdrFlag)
&& ! (pDlayerParamInternal->iCodingIndex & (pSvcParam->uiGopSize - 1))) {
SPicture* pRefPic = pCtx->pLtr[iDependencyId].bReceivedT0LostFlag ? SPicture* pRefPic = pCtx->pLtr[iDependencyId].bReceivedT0LostFlag ?
m_pSpatialPic[iDependencyId][m_uiSpatialLayersInTemporal[iDependencyId] + m_pSpatialPic[iDependencyId][m_uiSpatialLayersInTemporal[iDependencyId] +
pCtx->pVaa->uiValidLongTermPicIdx] : m_pLastSpatialPicture[iDependencyId][0]; pCtx->pVaa->uiValidLongTermPicIdx] : m_pLastSpatialPicture[iDependencyId][0];
@ -357,61 +403,28 @@ int32_t CWelsPreProcess::SingleLayerPreprocess (sWelsEncCtx* pCtx, const SSource
} }
} }
for (int32_t i = 0; i < pSvcParam->iSpatialLayerNum; i++) { WelsUpdateSpatialIdxMap (pCtx, iDependencyId, pDstPic, iDependencyId);
if (pSvcParam->sDependencyLayers[i].uiCodingIdx2TemporalId[pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1)] m_pLastSpatialPicture[iDependencyId][1] = m_pSpatialPic[iDependencyId][iPicturePos];
!= INVALID_TEMPORAL_ID) {
++ iActualSpatialLayerNum;
}
}
if (iTemporalId != INVALID_TEMPORAL_ID) { if (iTemporalId != INVALID_TEMPORAL_ID) {
WelsUpdateSpatialIdxMap (pCtx, iActualSpatialLayerNum - 1, pDstPic, iDependencyId);
++ iSpatialNum; ++ iSpatialNum;
-- iActualSpatialLayerNum;
} }
m_pLastSpatialPicture[iDependencyId][1] = m_pSpatialPic[iDependencyId][iPicturePos];
-- iDependencyId; -- iDependencyId;
// generate other spacial layer
// pSrc is
// -- padded input pic, if downsample should be applied to generate highest layer, [if] block above
// -- highest layer, if no downsampling, [else] block above
if (pSvcParam->iSpatialLayerNum > 1) { if (pSvcParam->iSpatialLayerNum > 1) {
while (iDependencyId >= 0) { while (iDependencyId >= 0) {
pDlayerParamInternal = &pSvcParam->sDependencyLayers[iDependencyId]; pDlayerParamInternal = &pSvcParam->sDependencyLayers[iDependencyId];
pDlayerParam = &pSvcParam->sSpatialLayers[iDependencyId]; iTemporalId = pDlayerParamInternal->uiCodingIdx2TemporalId[pDlayerParamInternal->iCodingIndex &
iTargetWidth = pDlayerParam->iVideoWidth; (pSvcParam->uiGopSize - 1)];
iTargetHeight = pDlayerParam->iVideoHeight;
iTemporalId = pDlayerParamInternal->uiCodingIdx2TemporalId[pCtx->iCodingIndex & (pSvcParam->uiGopSize - 1)];
iPicturePos = m_uiSpatialLayersInTemporal[iDependencyId] - 1;
// NOT work for CGS, FIXME
// spatial layer is able to encode indeed
if ((iTemporalId != INVALID_TEMPORAL_ID)) { if ((iTemporalId != INVALID_TEMPORAL_ID)) {
// down sampling performed
pDstPic = m_pSpatialPic[iDependencyId][iPicturePos]; // small
iShrinkWidth = pScaledPicture->iScaledWidth[iDependencyId];
iShrinkHeight = pScaledPicture->iScaledHeight[iDependencyId];
DownsamplePadding (pSrcPic, pDstPic, iSrcWidth, iSrcHeight, iShrinkWidth, iShrinkHeight, iTargetWidth, iTargetHeight,
true);
WelsUpdateSpatialIdxMap (pCtx, iActualSpatialLayerNum - 1, pDstPic, iDependencyId);
-- iActualSpatialLayerNum;
++ iSpatialNum; ++ iSpatialNum;
m_pLastSpatialPicture[iDependencyId][1] = m_pSpatialPic[iDependencyId][iPicturePos];
} }
-- iDependencyId; -- iDependencyId;
} }
} }
return iSpatialNum; return iSpatialNum;
} }
/*! /*!
* \brief Whether input picture need be scaled? * \brief Whether input picture need be scaled?
*/ */
@ -999,6 +1012,7 @@ ESceneChangeIdc CWelsPreProcess::DetectSceneChangeScreen (sWelsEncCtx* pCtx, SPi
#define STATIC_SCENE_MOTION_RATIO 0.01f #define STATIC_SCENE_MOTION_RATIO 0.01f
SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam; SWelsSvcCodingParam* pSvcParam = pCtx->pSvcParam;
SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa); SVAAFrameInfoExt* pVaaExt = static_cast<SVAAFrameInfoExt*> (pCtx->pVaa);
SSpatialLayerInternal* pParamInternal = &pSvcParam->sDependencyLayers[0];
if (NULL == pCtx || NULL == pVaaExt || NULL == pCurPicture) { if (NULL == pCtx || NULL == pVaaExt || NULL == pCurPicture) {
return LARGE_CHANGED_SCENE; return LARGE_CHANGED_SCENE;
} }
@ -1040,7 +1054,7 @@ ESceneChangeIdc CWelsPreProcess::DetectSceneChangeScreen (sWelsEncCtx* pCtx, SPi
const int32_t iNegligibleMotionBlocks = (static_cast<int32_t> ((pCurPicture->iWidthInPixel >> 3) * const int32_t iNegligibleMotionBlocks = (static_cast<int32_t> ((pCurPicture->iWidthInPixel >> 3) *
(pCurPicture->iHeightInPixel >> 3) * STATIC_SCENE_MOTION_RATIO)); (pCurPicture->iHeightInPixel >> 3) * STATIC_SCENE_MOTION_RATIO));
const uint8_t iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[m_pEncCtx->sSpatialIndexMap[0].iDid], const uint8_t iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[m_pEncCtx->sSpatialIndexMap[0].iDid],
m_pEncCtx->iCodingIndex, pSvcParam->uiGopSize); pParamInternal->iCodingIndex, pSvcParam->uiGopSize);
if (iCurTid == INVALID_TEMPORAL_ID) { if (iCurTid == INVALID_TEMPORAL_ID) {
return LARGE_CHANGED_SCENE; return LARGE_CHANGED_SCENE;
} }
@ -1135,7 +1149,7 @@ ESceneChangeIdc CWelsPreProcess::DetectSceneChangeScreen (sWelsEncCtx* pCtx, SPi
} }
WelsLog (pLogCtx, WELS_LOG_DEBUG, "iVaaFrameSceneChangeIdc = %d,codingIdx = %d", iVaaFrameSceneChangeIdc, WelsLog (pLogCtx, WELS_LOG_DEBUG, "iVaaFrameSceneChangeIdc = %d,codingIdx = %d", iVaaFrameSceneChangeIdc,
pCtx->iCodingIndex); pParamInternal->iCodingIndex);
SaveBestRefToVaa (sLtrSaved, & (pVaaExt->sVaaStrBestRefCandidate[0])); SaveBestRefToVaa (sLtrSaved, & (pVaaExt->sVaaStrBestRefCandidate[0]));
pVaaExt->iVaaBestRefFrameNum = sLtrSaved.pRefPicture->iFrameNum; pVaaExt->iVaaBestRefFrameNum = sLtrSaved.pRefPicture->iFrameNum;

View File

@ -145,7 +145,7 @@ WelsErrorType CWelsSliceEncodingTask::ExecuteTask() {
#if MT_DEBUG_BS_WR #if MT_DEBUG_BS_WR
m_pSliceBs->bSliceCodedFlag = false; m_pSliceBs->bSliceCodedFlag = false;
#endif//MT_DEBUG_BS_WR #endif//MT_DEBUG_BS_WR
SSpatialLayerInternal *pParamInternal = &m_pCtx->pSvcParam->sDependencyLayers[m_pCtx->uiDependencyId];
if (m_bNeedPrefix) { if (m_bNeedPrefix) {
if (m_eNalRefIdc != NRI_PRI_LOWEST) { if (m_eNalRefIdc != NRI_PRI_LOWEST) {
WelsLoadNalForSlice (m_pSliceBs, NAL_UNIT_PREFIX, m_eNalRefIdc); WelsLoadNalForSlice (m_pSliceBs, NAL_UNIT_PREFIX, m_eNalRefIdc);
@ -171,7 +171,7 @@ WelsErrorType CWelsSliceEncodingTask::ExecuteTask() {
if (ENC_RETURN_SUCCESS != iReturn) { if (ENC_RETURN_SUCCESS != iReturn) {
WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING, WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING,
"[MT] CWelsSliceEncodingTask ExecuteTask(), WriteSliceBs not successful: coding_idx %d, um_iSliceIdx %d", "[MT] CWelsSliceEncodingTask ExecuteTask(), WriteSliceBs not successful: coding_idx %d, um_iSliceIdx %d",
m_pCtx->iCodingIndex, pParamInternal->iCodingIndex,
m_iSliceIdx); m_iSliceIdx);
return iReturn; return iReturn;
} }
@ -209,11 +209,11 @@ WelsErrorType CWelsLoadBalancingSlicingEncodingTask::InitTask() {
void CWelsLoadBalancingSlicingEncodingTask::FinishTask() { void CWelsLoadBalancingSlicingEncodingTask::FinishTask() {
CWelsSliceEncodingTask::FinishTask(); CWelsSliceEncodingTask::FinishTask();
SSpatialLayerInternal *pParamInternal = &m_pCtx->pSvcParam->sDependencyLayers[m_pCtx->uiDependencyId];
m_pSlice->uiSliceConsumeTime = (uint32_t) (WelsTime() - m_iSliceStart); m_pSlice->uiSliceConsumeTime = (uint32_t) (WelsTime() - m_iSliceStart);
WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG, WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG,
"[MT] CWelsLoadBalancingSlicingEncodingTask()FinishTask, coding_idx %d, um_iSliceIdx %d, uiSliceConsumeTime %d, m_iSliceSize %d, iFirstMbInSlice %d, count_num_mb_in_slice %d at time=%" PRId64, "[MT] CWelsLoadBalancingSlicingEncodingTask()FinishTask, coding_idx %d, um_iSliceIdx %d, uiSliceConsumeTime %d, m_iSliceSize %d, iFirstMbInSlice %d, count_num_mb_in_slice %d at time=%" PRId64,
m_pCtx->iCodingIndex, pParamInternal->iCodingIndex,
m_iSliceIdx, m_iSliceIdx,
m_pSlice->uiSliceConsumeTime, m_pSlice->uiSliceConsumeTime,
m_iSliceSize, m_iSliceSize,
@ -230,7 +230,7 @@ WelsErrorType CWelsConstrainedSizeSlicingEncodingTask::ExecuteTask() {
SSliceCtx* pSliceCtx = &pCurDq->sSliceEncCtx; SSliceCtx* pSliceCtx = &pCurDq->sSliceEncCtx;
const int32_t kiSliceIdxStep = m_pCtx->iActiveThreadsNum; const int32_t kiSliceIdxStep = m_pCtx->iActiveThreadsNum;
SSpatialLayerInternal *pParamInternal = &m_pCtx->pSvcParam->sDependencyLayers[m_pCtx->uiDependencyId];
SSliceHeaderExt* pStartSliceHeaderExt = &pCurDq->sLayerInfo.pSliceInLayer[m_iSliceIdx].sSliceHeaderExt; SSliceHeaderExt* pStartSliceHeaderExt = &pCurDq->sLayerInfo.pSliceInLayer[m_iSliceIdx].sSliceHeaderExt;
//deal with partition: TODO: here SSliceThreadPrivateData is just for parition info and actually has little relationship with threadbuffer, and iThreadIndex is not used in threadpool model, need renaming after removing old logic to avoid confusion //deal with partition: TODO: here SSliceThreadPrivateData is just for parition info and actually has little relationship with threadbuffer, and iThreadIndex is not used in threadpool model, need renaming after removing old logic to avoid confusion
@ -252,7 +252,7 @@ WelsErrorType CWelsConstrainedSizeSlicingEncodingTask::ExecuteTask() {
if (iLocalSliceIdx >= pSliceCtx->iMaxSliceNumConstraint) { if (iLocalSliceIdx >= pSliceCtx->iMaxSliceNumConstraint) {
WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING, WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING,
"[MT] CWelsConstrainedSizeSlicingEncodingTask ExecuteTask() coding_idx %d, uiLocalSliceIdx %d, pSliceCtx->iMaxSliceNumConstraint %d", "[MT] CWelsConstrainedSizeSlicingEncodingTask ExecuteTask() coding_idx %d, uiLocalSliceIdx %d, pSliceCtx->iMaxSliceNumConstraint %d",
m_pCtx->iCodingIndex, pParamInternal->iCodingIndex,
iLocalSliceIdx, pSliceCtx->iMaxSliceNumConstraint); iLocalSliceIdx, pSliceCtx->iMaxSliceNumConstraint);
return ENC_RETURN_KNOWN_ISSUE; return ENC_RETURN_KNOWN_ISSUE;
} }
@ -288,7 +288,7 @@ WelsErrorType CWelsConstrainedSizeSlicingEncodingTask::ExecuteTask() {
if (ENC_RETURN_SUCCESS != iReturn) { if (ENC_RETURN_SUCCESS != iReturn) {
WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING, WelsLog (&m_pCtx->sLogCtx, WELS_LOG_WARNING,
"[MT] CWelsConstrainedSizeSlicingEncodingTask ExecuteTask(), WriteSliceBs not successful: coding_idx %d, uiLocalSliceIdx %d, BufferSize %d, m_iSliceSize %d, iPayloadSize %d", "[MT] CWelsConstrainedSizeSlicingEncodingTask ExecuteTask(), WriteSliceBs not successful: coding_idx %d, uiLocalSliceIdx %d, BufferSize %d, m_iSliceSize %d, iPayloadSize %d",
m_pCtx->iCodingIndex, pParamInternal->iCodingIndex,
iLocalSliceIdx, m_pSliceBs->uiSize, m_iSliceSize, m_pSliceBs->sNalList[0].iPayloadSize); iLocalSliceIdx, m_pSliceBs->uiSize, m_iSliceSize, m_pSliceBs->sNalList[0].iPayloadSize);
return iReturn; return iReturn;
} }
@ -305,7 +305,7 @@ WelsErrorType CWelsConstrainedSizeSlicingEncodingTask::ExecuteTask() {
WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG, WelsLog (&m_pCtx->sLogCtx, WELS_LOG_DEBUG,
"[MT] CWelsConstrainedSizeSlicingEncodingTask(), coding_idx %d, iPartitionId %d, m_iThreadIdx %d, iLocalSliceIdx %d, m_iSliceSize %d, ParamValidationExt(), invalid uiMaxNalSizeiEndMbInPartition %d, pCurDq->pLastCodedMbIdxOfPartition[%d] %d\n", "[MT] CWelsConstrainedSizeSlicingEncodingTask(), coding_idx %d, iPartitionId %d, m_iThreadIdx %d, iLocalSliceIdx %d, m_iSliceSize %d, ParamValidationExt(), invalid uiMaxNalSizeiEndMbInPartition %d, pCurDq->pLastCodedMbIdxOfPartition[%d] %d\n",
m_pCtx->iCodingIndex, kiPartitionId, m_iThreadIdx, iLocalSliceIdx, m_iSliceSize, pParamInternal->iCodingIndex, kiPartitionId, m_iThreadIdx, iLocalSliceIdx, m_iSliceSize,
kiEndMbInPartition, kiPartitionId, pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]); kiEndMbInPartition, kiPartitionId, pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]);
iAnyMbLeftInPartition = kiEndMbInPartition - (1 + pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]); iAnyMbLeftInPartition = kiEndMbInPartition - (1 + pCurDq->pLastCodedMbIdxOfPartition[kiPartitionId]);

View File

@ -1391,6 +1391,7 @@ TEST_F (EncodeDecodeTestAPI, DiffSlicingInDlayer) {
sParam.sSpatialLayers[2].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE; sParam.sSpatialLayers[2].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
sParam.sSpatialLayers[2].sSliceArgument.uiSliceNum = (rand() % 30) + 1; sParam.sSpatialLayers[2].sSliceArgument.uiSliceNum = (rand() % 30) + 1;
int rv = encoder_->InitializeExt (&sParam); int rv = encoder_->InitializeExt (&sParam);
ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;; ASSERT_TRUE (rv == cmResultSuccess) << "Init Failed sParam: rv = " << rv;;