ref: 0a1b61508b45adfcaa5f204ac27b613a2fbe256f
parent: 3f333b01fdc194d03d5c3902c3a819d53041e7ae
author: ruil2 <[email protected]>
date: Wed Jun 25 09:31:48 EDT 2014
fix defect7654 that the encoder won't generate IDR when temporal layer setting changes
--- a/codec/encoder/core/inc/au_set.h
+++ b/codec/encoder/core/inc/au_set.h
@@ -45,7 +45,7 @@
#include "bit_stream.h"
#include "parameter_sets.h"
#include "param_svc.h"
-
+#include "utils.h"
namespace WelsSVCEnc {
/*!
*************************************************************************************
@@ -139,6 +139,6 @@
const uint32_t kuiPpsId,
const bool kbDeblockingFilterPresentFlag,
const bool kbUsingSubsetSps);
-
+int32_t WelsCheckRefFrameLimitation(SLogContext* pLogCtx,SWelsSvcCodingParam* pParam);
}
#endif//WELS_ACCESS_UNIT_PARSER_H__
--- a/codec/encoder/core/inc/param_svc.h
+++ b/codec/encoder/core/inc/param_svc.h
@@ -116,8 +116,8 @@
iCountThreadsNum; // # derived from disable_multiple_slice_idc (=0 or >1) means;
int8_t iDecompStages; // GOP size dependency
+ int32_t iMaxNumRefFrame;
-
public:
TagWelsSvcCodingParam() {
FillDefault();
@@ -190,7 +190,7 @@
void FillDefault() {
FillDefault (*this);
uiGopSize = 1; // GOP size (at maximal frame rate: 16)
-
+ iMaxNumRefFrame = 1;
SUsedPicRect.iLeft =
SUsedPicRect.iTop =
SUsedPicRect.iWidth =
@@ -369,6 +369,8 @@
iNumRefFrame = WELS_CLIP3 (iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM);
}
}
+ if (iNumRefFrame > iMaxNumRefFrame)
+ iMaxNumRefFrame = iNumRefFrame;
iLtrMarkPeriod = pCodingParam.iLtrMarkPeriod;
bPrefixNalAddingCtrl = pCodingParam.bPrefixNalAddingCtrl;
@@ -391,8 +393,8 @@
float fLayerFrameRate = WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate,
MIN_FRAME_RATE, fParamMaxFrameRate);
pSpatialLayer->fFrameRate =
- pDlp->fInputFrameRate =
- pDlp->fOutputFrameRate = WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
+ pDlp->fInputFrameRate =
+ pDlp->fOutputFrameRate = WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
if (pDlp->fInputFrameRate > fMaxFr + EPSN)
fMaxFr = pDlp->fInputFrameRate;
--- a/codec/encoder/core/src/au_set.cpp
+++ b/codec/encoder/core/src/au_set.cpp
@@ -40,6 +40,7 @@
#include "au_set.h"
#include "svc_enc_golomb.h"
+#include "macros.h"
namespace WelsSVCEnc {
@@ -102,6 +103,44 @@
}
+int32_t WelsCheckRefFrameLimitation (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam) {
+ int32_t i = 0;
+ int32_t iRefFrame = 1;
+ //get the number of reference frame according to level limitation.
+ for (i = 0; i < pParam->iSpatialLayerNum; ++ i) {
+ SSpatialLayerConfig* pSpatialLayer = &pParam->sSpatialLayers[i];
+ uint32_t uiPicInMBs = ((pSpatialLayer->iVideoHeight + 15) >> 4) * ((pSpatialLayer->iVideoWidth + 15) >> 4);
+ if (pSpatialLayer->uiLevelIdc == LEVEL_UNKNOWN) {
+ pSpatialLayer->uiLevelIdc = LEVEL_5_0;
+ WelsLog (pLogCtx, WELS_LOG_WARNING, "change level to level5.0\n");
+ }
+ iRefFrame = g_ksLevelLimit[pSpatialLayer->uiLevelIdc - 1].uiMaxDPBMB / uiPicInMBs;
+ if (iRefFrame < pParam->iMaxNumRefFrame)
+ pParam->iMaxNumRefFrame = iRefFrame;
+ if (pParam->iMaxNumRefFrame < 1) {
+ pParam->iMaxNumRefFrame = 1;
+ WelsLog (pLogCtx, WELS_LOG_ERROR, "error Level setting (%d)\n", pSpatialLayer->uiLevelIdc);
+ return ENC_RETURN_UNSUPPORTED_PARA;
+ }
+ }
+ //check temporal layer number according to the number of reference frame
+ int32_t iMaxTemporalLayer = pParam->iNumRefFrame - pParam->iLTRRefNum;
+ if (iMaxTemporalLayer < 1) {
+ iMaxTemporalLayer = 1;
+ WelsLog (pLogCtx, WELS_LOG_ERROR, "Invalid the number of reference frame ltr num(%d)\n", pParam->iLTRRefNum);
+ return ENC_RETURN_UNSUPPORTED_PARA;
+ }
+ if (pParam->iTemporalLayerNum > iMaxTemporalLayer)
+ pParam->iTemporalLayerNum = iMaxTemporalLayer;
+
+ //get the maximum num of reference frame according to temporal Layer
+ iRefFrame = WELS_CLIP3 ((pParam->iTemporalLayerNum + pParam->iLTRRefNum), MIN_REF_PIC_COUNT,
+ MAX_REFERENCE_REORDER_COUNT_NUM);
+ if (pParam->iMaxNumRefFrame < iRefFrame)
+ pParam->iMaxNumRefFrame = iRefFrame;
+
+ return ENC_RETURN_SUCCESS;
+}
static inline int32_t WelsGetLevelIdc (const SWelsSPS* kpSps, float fFrameRate, int32_t iTargetBitRate) {
int32_t iOrder;
for (iOrder = 0; iOrder < LEVEL_NUMBER; iOrder++) {
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -156,6 +156,8 @@
}
}
+ return WelsCheckRefFrameLimitation (pLogCtx, pCfg);
+
return ENC_RETURN_SUCCESS;
}
@@ -753,7 +755,7 @@
pMa = (*ppCtx)->pMemAlign;
pParam = (*ppCtx)->pSvcParam;
iDlayerCount = pParam->iSpatialLayerNum;
- iNumRef = pParam->iNumRefFrame;
+ iNumRef = pParam->iMaxNumRefFrame;
const int32_t kiFeatureStrategyIndex = FME_DEFAULT_FEATURE_INDEX;
const int32_t kiMe16x16 = ME_DIA_CROSS;
@@ -927,7 +929,8 @@
// Need port pSps/pPps initialization due to spatial scalability changed
if (!bUseSubsetSps) {
- WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod, pParam->iNumRefFrame,
+ WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
+ pParam->iMaxNumRefFrame,
iSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE);
if (iDlayerCount > 1) {
@@ -937,7 +940,7 @@
}
} else {
WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
- pParam->iNumRefFrame,
+ pParam->iMaxNumRefFrame,
iSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE);
}
@@ -1420,7 +1423,7 @@
if (pParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {
(*ppCtx)->pVaa = (SVAAFrameInfoExt*)pMa->WelsMallocz (sizeof (SVAAFrameInfoExt), "pVaa");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pVaa), FreeMemorySvc (ppCtx))
- if (RequestMemoryVaaScreen ((*ppCtx)->pVaa, pMa, (*ppCtx)->pSvcParam->iNumRefFrame, iCountMaxMbNum << 2)) {
+ if (RequestMemoryVaaScreen ((*ppCtx)->pVaa, pMa, (*ppCtx)->pSvcParam->iMaxNumRefFrame, iCountMaxMbNum << 2)) {
WelsLog (*ppCtx, WELS_LOG_WARNING, "RequestMemorySvc(), RequestMemoryVaaScreen failed!");
FreeMemorySvc (ppCtx);
return 1;
@@ -1674,7 +1677,7 @@
FreePicture (pMa, &pRefList->pRef[iRef]);
}
++ iRef;
- } while (iRef < 1 + pParam->iNumRefFrame);
+ } while (iRef < 1 + pParam->iMaxNumRefFrame);
pMa->WelsFree (pCtx->ppRefPicListExt[ilayer], "ppRefPicListExt[]");
pCtx->ppRefPicListExt[ilayer] = NULL;
@@ -1727,7 +1730,7 @@
pCtx->pVaa->sVaaCalcInfo.pMad8x8 = NULL;
}
if (pCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME)
- ReleaseMemoryVaaScreen (pCtx->pVaa, pMa, pCtx->pSvcParam->iNumRefFrame);
+ ReleaseMemoryVaaScreen (pCtx->pVaa, pMa, pCtx->pSvcParam->iMaxNumRefFrame);
pMa->WelsFree (pCtx->pVaa, "pVaa");
pCtx->pVaa = NULL;
}
@@ -3568,10 +3571,7 @@
/* Decide whether need reset for IDR frame based on adjusting prarameters changed */
/* Temporal levels, spatial settings and/ or quality settings changed need update parameter sets related. */
bNeedReset = (pOldParam == NULL) ||
- (pOldParam->iTemporalLayerNum != pNewParam->iTemporalLayerNum) ||
- (pOldParam->uiGopSize != pNewParam->uiGopSize) ||
(pOldParam->iSpatialLayerNum != pNewParam->iSpatialLayerNum) ||
- (pOldParam->iDecompStages != pNewParam->iDecompStages) ||
(pOldParam->iPicWidth != pNewParam->iPicWidth
|| pOldParam->iPicHeight != pNewParam->iPicHeight) ||
(pOldParam->SUsedPicRect.iWidth != pNewParam->SUsedPicRect.iWidth
@@ -3578,6 +3578,11 @@
|| pOldParam->SUsedPicRect.iHeight != pNewParam->SUsedPicRect.iHeight) ||
(pOldParam->bEnableLongTermReference != pNewParam->bEnableLongTermReference) ||
(pOldParam->iLTRRefNum != pNewParam->iLTRRefNum);
+ if (pNewParam->iMaxNumRefFrame > pOldParam->iMaxNumRefFrame) {
+ pNewParam->iMaxNumRefFrame = pOldParam->iMaxNumRefFrame;
+ bNeedReset = true;
+ }
+
if (!bNeedReset) { // Check its picture resolutions/quality settings respectively in each dependency layer
iIndexD = 0;
assert (pOldParam->iSpatialLayerNum == pNewParam->iSpatialLayerNum);
@@ -3615,12 +3620,6 @@
bNeedReset = true;
break;
}
-
- if (kpOldDlp->iHighestTemporalId != kpNewDlp->iHighestTemporalId) {
- bNeedReset = true;
- break;
- }
-
++ iIndexD;
} while (iIndexD < pOldParam->iSpatialLayerNum);
}
@@ -3801,12 +3800,13 @@
int16_t* pFirstMbInSlice = (int16_t*)pMA->WelsMalloc (iMaxSliceNum * sizeof (int16_t), "pSliceSeg->pFirstMbInSlice");
if (NULL == pFirstMbInSlice)
return ENC_RETURN_MEMALLOCERR;
- memset(pFirstMbInSlice, 0, sizeof(int16_t) * iMaxSliceNum);
+ memset (pFirstMbInSlice, 0, sizeof (int16_t) * iMaxSliceNum);
memcpy (pFirstMbInSlice, pCurLayer->pSliceEncCtx->pFirstMbInSlice, sizeof (int16_t) * iMaxSliceNumOld);
pMA->WelsFree (pCurLayer->pSliceEncCtx->pFirstMbInSlice, "pSliceSeg->pFirstMbInSlice");
pCurLayer->pSliceEncCtx->pFirstMbInSlice = pFirstMbInSlice;
- int32_t* pCountMbNumInSlice = (int32_t*)pMA->WelsMalloc (iMaxSliceNum * sizeof (int32_t),"pSliceSeg->pCountMbNumInSlice");
+ int32_t* pCountMbNumInSlice = (int32_t*)pMA->WelsMalloc (iMaxSliceNum * sizeof (int32_t),
+ "pSliceSeg->pCountMbNumInSlice");
if (NULL == pCountMbNumInSlice)
return ENC_RETURN_MEMALLOCERR;
memcpy (pCountMbNumInSlice, pCurLayer->pSliceEncCtx->pCountMbNumInSlice, sizeof (int32_t) * iMaxSliceNumOld);
@@ -3824,13 +3824,15 @@
memcpy (pSlcingOverRc, pCtx->pWelsSvcRc->pSlicingOverRc, sizeof (SRCSlicing) * iMaxSliceNumOld);
uiSliceIdx = iMaxSliceNumOld;
SRCSlicing* pSORC = &pSlcingOverRc[uiSliceIdx];
- const int32_t kiBitsPerMb = WELS_DIV_ROUND(pCtx->pWelsSvcRc->iTargetBits * INT_MULTIPLY, pCtx->pWelsSvcRc->iNumberMbFrame);
+ const int32_t kiBitsPerMb = WELS_DIV_ROUND (pCtx->pWelsSvcRc->iTargetBits * INT_MULTIPLY,
+ pCtx->pWelsSvcRc->iNumberMbFrame);
while (uiSliceIdx < iMaxSliceNum) {
pSORC->iComplexityIndexSlice = 0;
pSORC->iCalculatedQpSlice = pCtx->iGlobalQp;
pSORC->iTotalQpSlice = 0;
pSORC->iTotalMbSlice = 0;
- pSORC->iTargetBitsSlice = WELS_DIV_ROUND(kiBitsPerMb * pCurLayer->pSliceEncCtx->pCountMbNumInSlice[uiSliceIdx], INT_MULTIPLY);
+ pSORC->iTargetBitsSlice = WELS_DIV_ROUND (kiBitsPerMb * pCurLayer->pSliceEncCtx->pCountMbNumInSlice[uiSliceIdx],
+ INT_MULTIPLY);
pSORC->iFrameBitsSlice = 0;
pSORC->iGomBitsSlice = 0;
pSORC ++;
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -356,22 +356,23 @@
if (pCfg->iUsageType == SCREEN_CONTENT_REAL_TIME) {
if (pCfg->bEnableLongTermReference) {
pCfg->iLTRRefNum = WELS_CLIP3 (pCfg->iLTRRefNum, 1, LONG_TERM_REF_NUM_SCREEN);
- if (pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT)
+ if(pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT)
pCfg->iNumRefFrame = WELS_MAX (1, WELS_LOG2 (pCfg->uiGopSize)) + pCfg->iLTRRefNum;
} else {
pCfg->iLTRRefNum = 0;
- if (pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT)
- pCfg->iNumRefFrame = WELS_MAX (1, pCfg->uiGopSize >> 1);
+ if(pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT)
+ pCfg->iNumRefFrame = WELS_MAX (1, pCfg->uiGopSize >> 1);;
}
} else {
pCfg->iLTRRefNum = pCfg->bEnableLongTermReference ? WELS_CLIP3 (pCfg->iLTRRefNum, 1, LONG_TERM_REF_NUM) : 0;
- if (pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT) {
+ if(pCfg->iNumRefFrame == AUTO_REF_PIC_COUNT){
pCfg->iNumRefFrame = ((pCfg->uiGopSize >> 1) > 1) ? ((pCfg->uiGopSize >> 1) + pCfg->iLTRRefNum) :
- (MIN_REF_PIC_COUNT + pCfg->iLTRRefNum);
+ (MIN_REF_PIC_COUNT + pCfg->iLTRRefNum);
pCfg->iNumRefFrame = WELS_CLIP3 (pCfg->iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM);
}
}
-
+ if(pCfg->iNumRefFrame > pCfg->iMaxNumRefFrame)
+ pCfg->iMaxNumRefFrame = pCfg->iNumRefFrame;
if (pCfg->iLtrMarkPeriod == 0) {
pCfg->iLtrMarkPeriod = 30;
}
@@ -559,12 +560,12 @@
pLayerInfo->uiProfileIdc = uiProfileIdc;
if ((iLayer == SPATIAL_LAYER_0) && (uiProfileIdc != PRO_BASELINE)) {
pLayerInfo->uiProfileIdc = PRO_BASELINE;
- WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support profile(%d),change to baseline profile", uiProfileIdc);
+ WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support profile(%d),change to baseline profile\n", uiProfileIdc);
}
if (iLayer > SPATIAL_LAYER_0) {
if ((uiProfileIdc != PRO_BASELINE) || (uiProfileIdc != PRO_SCALABLE_BASELINE)) {
pLayerInfo->uiProfileIdc = PRO_BASELINE;
- WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support profile(%d),change to baseline profile", uiProfileIdc);
+ WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support profile(%d),change to baseline profile\n", uiProfileIdc);
}
}
}
@@ -571,11 +572,17 @@
void CWelsH264SVCEncoder::CheckLevelSetting (int32_t iLayer, ELevelIdc uiLevelIdc) {
SSpatialLayerConfig* pLayerInfo = &m_pEncContext->pSvcParam->sSpatialLayers[iLayer];
pLayerInfo->uiLevelIdc = uiLevelIdc;
- //TBD
+ if( (uiLevelIdc< LEVEL_1_0)||(uiLevelIdc >LEVEL_5_2)){
+ pLayerInfo->uiLevelIdc = LEVEL_5_2;
+ WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support level(%d) change to LEVEL_5_2\n",uiLevelIdc);
+ }
}
void CWelsH264SVCEncoder::CheckReferenceNumSetting (int32_t iNumRef) {
m_pEncContext->pSvcParam->iNumRefFrame = iNumRef;
- //TBD
+ if((iNumRef < MIN_REF_PIC_COUNT)||(iNumRef> MAX_REFERENCE_PICTURE_COUNT_NUM)){
+ m_pEncContext->pSvcParam->iNumRefFrame = AUTO_REF_PIC_COUNT;
+ WelsLog (m_pEncContext, WELS_LOG_WARNING, "doesn't support the number of reference frame(%d) change to auto select mode\n",iNumRef);
+ }
}
/************************************************************************
* InDataFormat, IDRInterval, SVC Encode Param, Frame Rate, Bitrate,..