add maxbitrate verification

This commit is contained in:
ruil2
2014-11-25 17:12:06 +08:00
parent 305a2421be
commit d543ae89db
11 changed files with 5739 additions and 8499 deletions

View File

@@ -58,6 +58,7 @@ typedef struct TagLevelLimits {
int16_t iMaxMvsPer2Mb; // Max number of motion vectors per two consecutive MBs
} SLevelLimits;
#define CpbBrNalFactor 1200 //baseline,main,and extended profiles.
extern const SLevelLimits g_ksLevelLimits[LEVEL_NUMBER];
extern const uint8_t g_kuiMbCountScan4Idx[24];
extern const uint8_t g_kuiCache30ScanIdx[16];

View File

@@ -580,7 +580,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.iPicWidth = 1280; // width of picture in samples
sParam.iPicHeight = 720; // height of picture in samples
sParam.iTargetBitrate = 2500000; // target bitrate desired
sParam.iMaxBitrate = MAX_BIT_RATE;
sParam.iMaxBitrate = UNSPECIFIED_BIT_RATE;
sParam.iRCMode = RC_QUALITY_MODE; // rc mode control
sParam.iTemporalLayerNum = 3; // layer number at temporal level
sParam.iSpatialLayerNum = 4; // layer number at spatial level
@@ -600,7 +600,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.sSpatialLayers[iIndexLayer].iVideoHeight = 90;
sParam.sSpatialLayers[iIndexLayer].fFrameRate = 7.5f;
sParam.sSpatialLayers[iIndexLayer].iSpatialBitrate = 64000;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = MAX_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
++ iIndexLayer;
@@ -609,7 +609,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.sSpatialLayers[iIndexLayer].iVideoHeight = 180;
sParam.sSpatialLayers[iIndexLayer].fFrameRate = 15.0f;
sParam.sSpatialLayers[iIndexLayer].iSpatialBitrate = 160000;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = MAX_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
++ iIndexLayer;
@@ -618,7 +618,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.sSpatialLayers[iIndexLayer].iVideoHeight = 360;
sParam.sSpatialLayers[iIndexLayer].fFrameRate = 30.0f;
sParam.sSpatialLayers[iIndexLayer].iSpatialBitrate = 512000;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = MAX_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1;
@@ -628,7 +628,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
sParam.sSpatialLayers[iIndexLayer].iVideoHeight = 720;
sParam.sSpatialLayers[iIndexLayer].fFrameRate = 30.0f;
sParam.sSpatialLayers[iIndexLayer].iSpatialBitrate = 1500000;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = MAX_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
sParam.sSpatialLayers[iIndexLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1;

View File

@@ -142,5 +142,6 @@ int32_t WelsInitPps (SWelsPPS* pPps,
const bool kbUsingSubsetSps,
const bool kbEntropyCodingModeFlag);
int32_t WelsCheckRefFrameLimitation (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam);
int32_t WelsAdjustLevel( SSpatialLayerConfig* pSpatialLayer);
}
#endif//WELS_ACCESS_UNIT_PARSER_H__

View File

@@ -105,9 +105,10 @@ int32_t ForceCodingIDR (sWelsEncCtx* pCtx);
* \brief Wels SVC encoder parameters adjustment
* SVC adjustment results in new requirement in memory blocks adjustment
*/
int32_t WelsBitRateVerification(SLogContext* pLogCtx,SSpatialLayerConfig* pLayerParam,int32_t iLayerId);
int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNew);
void WelsEncoderApplyFrameRate (SWelsSvcCodingParam* pParam);
void WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iLayer);
int32_t WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int32_t iLayer);
int32_t WelsEncoderApplyLTR (SLogContext* pLogCtx, sWelsEncCtx** ppCtx, SLTRConfig* pLTRValue);
int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRecoverRequest);

View File

@@ -73,7 +73,19 @@ static inline int32_t WelsCheckLevelLimitation (const SWelsSPS* kpSps, const SLe
return 1;
}
int32_t WelsAdjustLevel (SSpatialLayerConfig* pSpatialLayer) {
int32_t iLevel = (int32_t)pSpatialLayer->uiLevelIdc;
int32_t iMaxBitrate = pSpatialLayer->iMaxSpatialBitrate;
while (iLevel <= LEVEL_5_2) {
int32_t iLevelMaxBitrate = g_ksLevelLimits[pSpatialLayer->uiLevelIdc - 1].uiMaxBR * CpbBrNalFactor;
if (iMaxBitrate < iLevelMaxBitrate) {
pSpatialLayer->uiLevelIdc = (ELevelIdc)iLevel;
return 0;
}
iLevel++;
}
return 1;
}
int32_t WelsCheckRefFrameLimitation (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam) {
int32_t i = 0;
int32_t iRefFrame = 1;

View File

@@ -70,6 +70,47 @@ int32_t WelsCodeOnePicPartition (sWelsEncCtx* pCtx,
);
int32_t WelsBitRateVerification (SLogContext* pLogCtx, SSpatialLayerConfig* pLayerParam, int32_t iLayerId) {
if (pLayerParam->iSpatialBitrate <= 0) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "Invalid bitrate settings in layer %d, bitrate= %d", iLayerId,
pLayerParam->iSpatialBitrate);
return ENC_RETURN_UNSUPPORTED_PARA;
}
if (pLayerParam->iMaxSpatialBitrate == pLayerParam->iSpatialBitrate) {
WelsLog (pLogCtx, WELS_LOG_INFO,
"Setting MaxSpatialBitrate (%d) the same at SpatialBitrate (%d) will make the actual bit rate lower than SpatialBitrate",
pLayerParam->iMaxSpatialBitrate, pLayerParam->iSpatialBitrate);
}
int32_t iLevelMaxBitrate = g_ksLevelLimits[pLayerParam->uiLevelIdc - 1].uiMaxBR * CpbBrNalFactor;
if (pLayerParam->iMaxSpatialBitrate == UNSPECIFIED_BIT_RATE) {
pLayerParam->iMaxSpatialBitrate = iLevelMaxBitrate;
WelsLog (pLogCtx, WELS_LOG_INFO, "Current MaxSpatialBitrate is zero,Get this value from level limitation(%d)",
pLayerParam->iMaxSpatialBitrate);
}
if (pLayerParam->iMaxSpatialBitrate > iLevelMaxBitrate) {
ELevelIdc iCurLevel = pLayerParam->uiLevelIdc;
if (WelsAdjustLevel (pLayerParam)) {
WelsLog (pLogCtx, WELS_LOG_ERROR,
"MaxSpatialBitrate (%d) is larger that the limitation LEVEL_5_2, considering it as error setting",
pLayerParam->iMaxSpatialBitrate);
return ENC_RETURN_UNSUPPORTED_PARA;
} else {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"Level is changed from (%d) to (%d) according to the maxbitrate",
iCurLevel, pLayerParam->uiLevelIdc);
}
}
if (pLayerParam->iMaxSpatialBitrate < pLayerParam->iSpatialBitrate) {
WelsLog (pLogCtx, WELS_LOG_ERROR,
"MaxSpatialBitrate (%d) should be larger than SpatialBitrate (%d), considering it as error setting",
pLayerParam->iMaxSpatialBitrate, pLayerParam->iSpatialBitrate);
return ENC_RETURN_UNSUPPORTED_PARA;
}
return ENC_RETURN_SUCCESS;
}
/*!
* \brief validate checking in parameter configuration
* \pParam pParam SWelsSvcCodingParam*
@@ -150,22 +191,9 @@ int32_t ParamValidation (SLogContext* pLogCtx, SWelsSvcCodingParam* pCfg) {
for (i = 0; i < pCfg->iSpatialLayerNum; ++ i) {
SSpatialLayerConfig* pSpatialLayer = &pCfg->sSpatialLayers[i];
iTotalBitrate += pSpatialLayer->iSpatialBitrate;
if (pSpatialLayer->iSpatialBitrate <= 0) {
WelsLog (pLogCtx, WELS_LOG_ERROR, "Invalid bitrate settings in layer %d, bitrate= %d", i,
pSpatialLayer->iSpatialBitrate);
if (WelsBitRateVerification (pLogCtx, pSpatialLayer, i) != ENC_RETURN_SUCCESS)
return ENC_RETURN_INVALIDINPUT;
}
if (pSpatialLayer->iMaxSpatialBitrate == pSpatialLayer->iSpatialBitrate) {
WelsLog (pLogCtx, WELS_LOG_INFO,
"Setting MaxSpatialBitrate (%d) the same at SpatialBitrate (%d) will make the actual bit rate lower than SpatialBitrate",
pSpatialLayer->iMaxSpatialBitrate, pSpatialLayer->iSpatialBitrate);
}
if (pSpatialLayer->iMaxSpatialBitrate < pSpatialLayer->iSpatialBitrate) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"MaxSpatialBitrate (%d) should be lower than SpatialBitrate (%d), considering it as invalid setting, adjust it to be UNSPECIFIED(0)",
pSpatialLayer->iMaxSpatialBitrate, pSpatialLayer->iSpatialBitrate);
pSpatialLayer->iMaxSpatialBitrate = 0;
}
}
if (iTotalBitrate > pCfg->iTargetBitrate) {
WelsLog (pLogCtx, WELS_LOG_ERROR,
@@ -475,8 +503,7 @@ void WelsEncoderApplyFrameRate (SWelsSvcCodingParam* pParam) {
}
}
void WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int iLayer) {
int32_t WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam, int iLayer) {
//TODO (Sijia): this is a temporary solution which keep the ratio between layers
//but it is also possible to fulfill the bitrate of lower layer first
@@ -494,26 +521,15 @@ void WelsEncoderApplyBitRate (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam,
pLayerParam = & (pParam->sSpatialLayers[i]);
fRatio = pLayerParam->iSpatialBitrate / (static_cast<float> (iOrigTotalBitrate));
pLayerParam->iSpatialBitrate = static_cast<int32_t> (pParam->iTargetBitrate * fRatio);
if (UNSPECIFIED_BIT_RATE != pLayerParam->iMaxSpatialBitrate
&& pLayerParam->iSpatialBitrate > pLayerParam->iMaxSpatialBitrate) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"WelsEncoderApplyBitRate(), iSpatialBitrate(%d) > iMaxSpatialBitrate(%d) at Layer %d, limiting iSpatialBitrate to iMaxSpatialBitrate!",
pLayerParam->iSpatialBitrate, pLayerParam->iMaxSpatialBitrate, iLayer);
pLayerParam->iSpatialBitrate = pLayerParam->iMaxSpatialBitrate;
}
if (WelsBitRateVerification (pLogCtx, pLayerParam, i) != ENC_RETURN_SUCCESS)
return ENC_RETURN_UNSUPPORTED_PARA;
}
} else {
SSpatialLayerConfig* pLayerParam = & (pParam->sSpatialLayers[iLayer]);
if (UNSPECIFIED_BIT_RATE != pLayerParam->iMaxSpatialBitrate
&& pLayerParam->iSpatialBitrate > pLayerParam->iMaxSpatialBitrate) {
WelsLog (pLogCtx, WELS_LOG_WARNING,
"WelsEncoderApplyBitRate(), iSpatialBitrate(%d) > iMaxSpatialBitrate(%d) at Layer %d, limiting iSpatialBitrate to iMaxSpatialBitrate!",
pLayerParam->iSpatialBitrate, pLayerParam->iMaxSpatialBitrate, iLayer);
pLayerParam->iSpatialBitrate = pLayerParam->iMaxSpatialBitrate;
}
return WelsBitRateVerification (pLogCtx, & (pParam->sSpatialLayers[iLayer]), iLayer);
}
return ENC_RETURN_SUCCESS;
}
/*!
* \brief acquire count number of layers and NALs based on configurable paramters dependency
* \pParam pCtx sWelsEncCtx*

View File

@@ -834,9 +834,16 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
break;
}
//adjust to valid range
WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer);
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iSpatialBitrate = %d", pInfo->iLayer, iBitrate);
if (WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer)) {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iSpatialBitrate = %d", pInfo->iLayer, iBitrate);
return cmInitParaError;
} else {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iSpatialBitrate = %d", pInfo->iLayer, iBitrate);
}
}
break;
case ENCODER_OPTION_MAX_BITRATE: { // Target bit-rate
@@ -879,10 +886,15 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
break;
}
//adjust to valid range
WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer);
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_MAX_BITRATE layerId= %d,iMaxSpatialBitrate = %d", pInfo->iLayer,
iBitrate);
if (WelsEncoderApplyBitRate (&m_pWelsTrace->m_sLogCtx, m_pEncContext->pSvcParam, pInfo->iLayer)) {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iMaxSpatialBitrate = %d", pInfo->iLayer, iBitrate);
return cmInitParaError;
} else {
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE layerId= %d,iMaxSpatialBitrate = %d", pInfo->iLayer, iBitrate);
}
}
break;
case ENCODER_OPTION_RC_MODE: { // 0:quality mode;1:bit-rate mode;2:bitrate limited mode

View File

@@ -206,9 +206,13 @@ TEST_F (EncoderInterfaceTest, EncoderAdditionalOptionSetTest) {
sInfo.iBitrate = rand() % 100000 - 100;
sInfo.iLayer = static_cast<LAYER_NUM> (pParamExt->iSpatialLayerNum);
iResult = pPtrEnc->SetOption (eOptionId, &sInfo);
pPtrEnc->GetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, pParamExt);
if (sInfo.iBitrate <= 0)
EXPECT_EQ (iResult, static_cast<int> (cmInitParaError));
else {
else if (pParamExt->sSpatialLayers[sInfo.iLayer].iSpatialBitrate >
pParamExt->sSpatialLayers[sInfo.iLayer].iMaxSpatialBitrate) {
EXPECT_EQ (iResult, static_cast<int> (cmInitParaError));
} else {
EXPECT_EQ (iResult, static_cast<int> (cmResultSuccess));
sReturn.iLayer = static_cast<LAYER_NUM> (pParamExt->iSpatialLayerNum);
iResult = pPtrEnc->GetOption (eOptionId, &sReturn);
@@ -224,9 +228,13 @@ TEST_F (EncoderInterfaceTest, EncoderAdditionalOptionSetTest) {
sInfo.iBitrate = rand() % 100000 - 100;
sInfo.iLayer = static_cast<LAYER_NUM> (pParamExt->iSpatialLayerNum);
iResult = pPtrEnc->SetOption (eOptionId, &sInfo);
pPtrEnc->GetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, pParamExt);
if (sInfo.iBitrate <= 0)
EXPECT_EQ (iResult, static_cast<int> (cmInitParaError));
else {
else if (pParamExt->sSpatialLayers[sInfo.iLayer].iSpatialBitrate >
pParamExt->sSpatialLayers[sInfo.iLayer].iMaxSpatialBitrate) {
EXPECT_EQ (iResult, static_cast<int> (cmInitParaError));
} else {
EXPECT_EQ (iResult, static_cast<int> (cmResultSuccess));
sReturn.iLayer = static_cast<LAYER_NUM> (pParamExt->iSpatialLayerNum);
iResult = pPtrEnc->GetOption (eOptionId, &sReturn);
@@ -438,6 +446,9 @@ void GetValidEncParamBase (SEncParamBase* pEncParamBase) {
pEncParamBase->iPicWidth = VALID_SIZE (pEncParamBase->iPicWidth);
pEncParamBase->iPicHeight = VALID_SIZE (pEncParamBase->iPicHeight);
pEncParamBase->iTargetBitrate = rand() + 1; //!=0
int32_t iLevelMaxBitrate = WelsCommon::g_ksLevelLimits[LEVEL_5_0 - 1].uiMaxBR * CpbBrNalFactor;
if (pEncParamBase->iTargetBitrate > iLevelMaxBitrate)
pEncParamBase->iTargetBitrate = iLevelMaxBitrate;
pEncParamBase->iRCMode = RC_BITRATE_MODE; //-1, 0, 1, 2
pEncParamBase->fMaxFrameRate = rand() + 0.5f; //!=0
}
@@ -584,12 +595,14 @@ TEST_F (EncoderInterfaceTest, ForceIntraFrameWithTemporal) {
sEncParamExt.iPicWidth = MB_SIZE + abs ((rand() * 2) % (MAX_WIDTH - MB_SIZE));
sEncParamExt.iPicHeight = MB_SIZE + abs ((rand() * 2) % (MAX_HEIGHT - MB_SIZE));
sEncParamExt.iTargetBitrate = rand() + 1; //!=0
int32_t iLevelMaxBitrate = WelsCommon::g_ksLevelLimits[LEVEL_5_0 - 1].uiMaxBR * CpbBrNalFactor;
if (sEncParamExt.iTargetBitrate > iLevelMaxBitrate)
sEncParamExt.iTargetBitrate = iLevelMaxBitrate;
sEncParamExt.iRCMode = RC_BITRATE_MODE; //-1, 0, 1, 2
sEncParamExt.fMaxFrameRate = rand() + 0.5f; //!=0
sEncParamExt.sSpatialLayers[0].iVideoWidth = sEncParamExt.iPicWidth;
sEncParamExt.sSpatialLayers[0].iVideoHeight = sEncParamExt.iPicHeight;
sEncParamExt.sSpatialLayers[0].iSpatialBitrate = sEncParamExt.iTargetBitrate;
int iTargetTemporalLayerNum = rand() % MAX_TEMPORAL_LAYER_NUM;
sEncParamExt.iTemporalLayerNum = (iTargetTemporalLayerNum > 2) ? iTargetTemporalLayerNum : 2;

File diff suppressed because one or more lines are too long