diff --git a/codec/encoder/core/inc/param_svc.h b/codec/encoder/core/inc/param_svc.h index 09a24403..0ff439b3 100644 --- a/codec/encoder/core/inc/param_svc.h +++ b/codec/encoder/core/inc/param_svc.h @@ -252,13 +252,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; @@ -332,10 +327,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..6328c5e1 100644 --- a/codec/encoder/core/inc/rc.h +++ b/codec/encoder/core/inc/rc.h @@ -56,10 +56,17 @@ namespace WelsSVCEnc { #define WELS_RC_GOM 1 typedef enum { - RC_MODE0, //Quality mode - RC_MODE1, //Bitrate mode + RC_QUALITY_MODE, //Quality mode + RC_BITRATE_MODE, //Bitrate mode + RC_LOW_BW_MODE, //bitrate limited mode } RC_MODES; +enum{ + BITS_NORMAL, + BITS_LIMITED, + BITS_EXCEEDED, +}; + enum { //virtual gop size VGOP_SIZE = 8, @@ -67,6 +74,7 @@ enum { //qp information GOM_MIN_QP_MODE = 12, GOM_MAX_QP_MODE = 36, + MAX_LOW_BR_QP = 42, MIN_IDR_QP = 26, MAX_IDR_QP = 32, DELTA_QP = 2, @@ -160,6 +168,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 +179,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..df206e5e 100644 --- a/codec/encoder/core/src/ratectl.cpp +++ b/codec/encoder/core/src/ratectl.cpp @@ -429,7 +429,38 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { if (0 == pTOverRc->iPFrameNum) { iLumaQp = pWelsSvcRc->iInitialQp; - } else { + } + else if (pWelsSvcRc->iCurrentBitsLevel==BITS_EXCEEDED) + { + iLumaQp = MAX_LOW_BR_QP; + //limit QP + int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1; + if (iLastIdxCodecInVGop < 0) + iLastIdxCodecInVGop += VGOP_SIZE; + int32_t iTlLast = pWelsSvcRc->iTlOfFrames[iLastIdxCodecInVGop]; + int32_t iDeltaQpTemporal = iTl - iTlLast; + if (0 == iTlLast && iTl > 0) + iDeltaQpTemporal += 3; + else if (0 == iTl && iTlLast > 0) + iDeltaQpTemporal -= 3; + + iLumaQp = WELS_CLIP3 (iLumaQp, + pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower + iDeltaQpTemporal, + pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper + iDeltaQpTemporal); + iLumaQp = WELS_CLIP3 (iLumaQp, GOM_MIN_QP_MODE, MAX_LOW_BR_QP); + + 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 +490,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_LOW_BW_MODE) + iLumaQp = (int32_t)WELS_CLIP3 (iLumaQp,pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); + } #endif pEncCtx->iGlobalQp = iLumaQp; @@ -489,12 +523,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_LOW_BW_MODE)) + { + pWelsSvcRc->iCurrentBitsLevel = BITS_EXCEEDED; + } + else if ((pWelsSvcRc->iTargetBits <= pTOverRc->iMinBitsTl) && (pEncCtx->pSvcParam->iRCMode == RC_LOW_BW_MODE)) + { + pWelsSvcRc->iCurrentBitsLevel = BITS_LIMITED; + } pWelsSvcRc->iTargetBits = WELS_CLIP3 (pWelsSvcRc->iTargetBits, pTOverRc->iMinBitsTl, pTOverRc->iMaxBitsTl); } pWelsSvcRc->dRemainingWeights -= pTOverRc->dTlayerWeight; @@ -617,7 +661,8 @@ void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iSliceId) { pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pEncCtx->iGlobalQp - pWelsSvcRc->iQpRangeLowerInFrame, pEncCtx->iGlobalQp + pWelsSvcRc->iQpRangeUpperInFrame); - pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); + if (!(pEncCtx->pSvcParam->iRCMode==RC_LOW_BW_MODE)) + 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 6d7b87ef..5631e2a4 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_BITRATE_MODE && pCtx->eSliceType == I_SLICE); VaaCalculation (pCtx->pVaa, pCurPic, pRefPic, bCalculateSQDiff, bCalculateVar, bCalculateBGD); } @@ -839,11 +839,11 @@ void CWelsPreProcess::AnalyzePictureComplexity (sWelsEncCtx* pCtx, SPicture* pCu SWelsSvcRc* SWelsSvcRc = &pCtx->pWelsSvcRc[kiDependencyId]; int32_t iComplexityAnalysisMode = 0; - if (pSvcParam->iRCMode == RC_MODE0 && pCtx->eSliceType == P_SLICE) { + if (pSvcParam->iRCMode == RC_QUALITY_MODE && pCtx->eSliceType == P_SLICE) { iComplexityAnalysisMode = FRAME_SAD; - } else if (pSvcParam->iRCMode == RC_MODE1 && pCtx->eSliceType == P_SLICE) { + } else if (pSvcParam->iRCMode >= RC_BITRATE_MODE && pCtx->eSliceType == P_SLICE) { iComplexityAnalysisMode = GOM_SAD; - } else if (pSvcParam->iRCMode == RC_MODE1 && pCtx->eSliceType == I_SLICE) { + } else if (pSvcParam->iRCMode >= RC_BITRATE_MODE && 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 527402dc..6daa740b 100644 --- a/codec/encoder/plus/src/welsEncoderExt.cpp +++ b/codec/encoder/plus/src/welsEncoderExt.cpp @@ -903,7 +903,7 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) { WelsEncoderApplyBitRate (m_pEncContext->pSvcParam,pInfo->iLayer); } 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; }