diff --git a/codec/encoder/core/inc/param_svc.h b/codec/encoder/core/inc/param_svc.h index b199c938..b349025b 100644 --- a/codec/encoder/core/inc/param_svc.h +++ b/codec/encoder/core/inc/param_svc.h @@ -247,13 +247,8 @@ int32_t ParamBaseTranscode (const SEncParamBase& pCodingParam, const bool kbEnab SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1); SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1); - bEnableRc = kbEnableRc; - if (pCodingParam.iRCMode != RC_MODE0 && pCodingParam.iRCMode != RC_MODE1) - iRCMode = RC_MODE1; - else - iRCMode = pCodingParam.iRCMode; // rc mode - - + bEnableRc = kbEnableRc; + iRCMode = pCodingParam.iRCMode; // rc mode int8_t iIdxSpatial = 0; uint8_t uiProfileIdc = PRO_BASELINE; @@ -327,10 +322,7 @@ int32_t ParamTranscode (const SEncParamExt& pCodingParam) { /* Rate Control */ bEnableRc = pCodingParam.bEnableRc; - if (pCodingParam.iRCMode != RC_MODE0 && pCodingParam.iRCMode != RC_MODE1) - iRCMode = RC_MODE1; - else - iRCMode = pCodingParam.iRCMode; // rc mode + iRCMode = pCodingParam.iRCMode; // rc mode iPaddingFlag = pCodingParam.iPaddingFlag; iTargetBitrate = pCodingParam.iTargetBitrate; // target bitrate diff --git a/codec/encoder/core/inc/rc.h b/codec/encoder/core/inc/rc.h index 0cdf2b75..831c6bb3 100644 --- a/codec/encoder/core/inc/rc.h +++ b/codec/encoder/core/inc/rc.h @@ -58,8 +58,15 @@ namespace WelsSVCEnc { typedef enum { RC_MODE0, //Quality mode RC_MODE1, //Bitrate mode + RC_MODE_LOWBR, //bitrate limited mode } RC_MODES; +enum{ + BITS_NORMAL, + BITS_LIMITED, + BITS_EXCEEDED, +}; + enum { //virtual gop size VGOP_SIZE = 8, @@ -160,6 +167,7 @@ typedef struct TagWelsRc { // bits allocation and status int32_t iRemainingBits; int32_t iTargetBits; + int32_t iCurrentBitsLevel;//0:normal; 1:limited; 2:exceeded. int32_t iIdrNum; int32_t iIntraComplexity; @@ -170,14 +178,14 @@ typedef struct TagWelsRc { int32_t iFrameDqBits; double* pGomComplexity; - int32_t* pGomForegroundBlockNum; + int32_t* pGomForegroundBlockNum; int32_t* pCurrentFrameGomSad; int32_t* pGomCost; int32_t iAverageFrameQp; int32_t iNumberMbFrame; int32_t iNumberMbGom; - int32_t iSliceNum; + int32_t iSliceNum; int32_t iGomSize; int32_t iSkipFrameNum; diff --git a/codec/encoder/core/src/ratectl.cpp b/codec/encoder/core/src/ratectl.cpp index c63cc826..0caeb249 100644 --- a/codec/encoder/core/src/ratectl.cpp +++ b/codec/encoder/core/src/ratectl.cpp @@ -429,7 +429,22 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { if (0 == pTOverRc->iPFrameNum) { iLumaQp = pWelsSvcRc->iInitialQp; - } else { + } + else if (pWelsSvcRc->iCurrentBitsLevel==BITS_EXCEEDED) + { + iLumaQp = 42; + pWelsSvcRc->dQStep = RcConvertQp2QStep (iLumaQp); + pWelsSvcRc->iLastCalculatedQScale = iLumaQp; + + if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { + iLumaQp = (int32_t)(iLumaQp - pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp); + } + + pEncCtx->iGlobalQp = iLumaQp; + + return; + } + else { double dCmplxRatio = (double)pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity / pTOverRc->iFrameCmplxMean; dCmplxRatio = WELS_CLIP3 (dCmplxRatio, 1.0 - FRAME_CMPLX_RATIO_RANGE, 1.0 + FRAME_CMPLX_RATIO_RANGE); @@ -459,8 +474,11 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { #ifndef _NOT_USE_AQ_FOR_TEST_ if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) { - iLumaQp = (int32_t)WELS_CLIP3 (iLumaQp - pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp, - pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); + iLumaQp = (int32_t)(iLumaQp - pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp); + + if (pEncCtx->pSvcParam->iRCMode!=RC_MODE_LOWBR) + iLumaQp = (int32_t)WELS_CLIP3 (iLumaQp,pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); + } #endif pEncCtx->iGlobalQp = iLumaQp; @@ -489,12 +507,22 @@ void RcInitSliceInformation (sWelsEncCtx* pEncCtx) { void RcDecideTargetBits (sWelsEncCtx* pEncCtx) { SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId]; SRCTemporal* pTOverRc = &pWelsSvcRc->pTemporalOverRc[pEncCtx->uiTemporalId]; + + pWelsSvcRc->iCurrentBitsLevel = BITS_NORMAL; //allocate bits if (pEncCtx->eSliceType == I_SLICE) { pWelsSvcRc->iTargetBits = (int32_t) (pWelsSvcRc->dBitsPerFrame * IDR_BITRATE_RATIO); } else { pWelsSvcRc->iTargetBits = (int32_t) (pWelsSvcRc->iRemainingBits * pTOverRc->dTlayerWeight / pWelsSvcRc->dRemainingWeights); + if ((pWelsSvcRc->iTargetBits <= 0) && (pEncCtx->pSvcParam->iRCMode == RC_MODE_LOWBR)) + { + pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED; + } + else if ((pWelsSvcRc->iTargetBits <= pTOverRc->iMinBitsTl) && (pEncCtx->pSvcParam->iRCMode == RC_MODE_LOWBR)) + { + pWelsSvcRc->iCurrentBitsLevel = BITS_LIMITED; + } pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, pTOverRc->iMinBitsTl, pTOverRc->iMaxBitsTl); } pWelsSvcRc->dRemainingWeights -= pTOverRc->dTlayerWeight; @@ -617,6 +645,7 @@ void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iSliceId) { pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pEncCtx->iGlobalQp - pWelsSvcRc->iQpRangeLowerInFrame, pEncCtx->iGlobalQp + pWelsSvcRc->iQpRangeUpperInFrame); + if (!(pEncCtx->pSvcParam->iRCMode==RC_MODE_LOWBR)) pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); pSOverRc->iGomBitsSlice = 0; diff --git a/codec/encoder/core/src/wels_preprocess.cpp b/codec/encoder/core/src/wels_preprocess.cpp index a7179e88..128147b6 100644 --- a/codec/encoder/core/src/wels_preprocess.cpp +++ b/codec/encoder/core/src/wels_preprocess.cpp @@ -346,7 +346,7 @@ int32_t CWelsPreProcess::AnalyzeSpatialPic (sWelsEncCtx* pCtx, const int32_t kiD { SPicture* pLastPic = m_pLastSpatialPicture[kiDidx][0]; bool bCalculateSQDiff = ((pLastPic->pData[0] == pRefPic->pData[0]) && bNeededMbAq); - bool bCalculateVar = (pSvcParam->iRCMode == RC_MODE1 && pCtx->eSliceType == I_SLICE); + bool bCalculateVar = (pSvcParam->iRCMode >= RC_MODE1 && pCtx->eSliceType == I_SLICE); VaaCalculation (pCtx->pVaa, pCurPic, pRefPic, bCalculateSQDiff, bCalculateVar, bCalculateBGD); } @@ -833,9 +833,9 @@ void CWelsPreProcess::AnalyzePictureComplexity (sWelsEncCtx* pCtx, SPicture* pCu if (pSvcParam->iRCMode == RC_MODE0 && pCtx->eSliceType == P_SLICE) { iComplexityAnalysisMode = FRAME_SAD; - } else if (pSvcParam->iRCMode == RC_MODE1 && pCtx->eSliceType == P_SLICE) { + } else if (pSvcParam->iRCMode >= RC_MODE1 && pCtx->eSliceType == P_SLICE) { iComplexityAnalysisMode = GOM_SAD; - } else if (pSvcParam->iRCMode == RC_MODE1 && pCtx->eSliceType == I_SLICE) { + } else if (pSvcParam->iRCMode >= RC_MODE1 && pCtx->eSliceType == I_SLICE) { iComplexityAnalysisMode = GOM_VAR; } else { return; diff --git a/codec/encoder/plus/src/welsEncoderExt.cpp b/codec/encoder/plus/src/welsEncoderExt.cpp index 49c64fa0..a423c8d4 100644 --- a/codec/encoder/plus/src/welsEncoderExt.cpp +++ b/codec/encoder/plus/src/welsEncoderExt.cpp @@ -840,7 +840,7 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) { WelsEncoderApplyBitRate (m_pEncContext->pSvcParam); } break; - case ENCODER_OPTION_RC_MODE: { // 0:quality mode;1:bit-rate mode + case ENCODER_OPTION_RC_MODE: { // 0:quality mode;1:bit-rate mode;2:bitrate limited mode int32_t iValue = * ((int32_t*)pOption); m_pEncContext->pSvcParam->iRCMode = iValue; }