From 4bc881c3aebb361fe9db888af16efa945b6c570a Mon Sep 17 00:00:00 2001 From: lyao2 Date: Thu, 20 Mar 2014 09:26:16 +0800 Subject: [PATCH 1/2] RC LOWBR mode merge --- codec/encoder/core/inc/param_svc.h | 14 ++------- codec/encoder/core/inc/rc.h | 12 ++++++-- codec/encoder/core/src/ratectl.cpp | 35 ++++++++++++++++++++-- codec/encoder/core/src/wels_preprocess.cpp | 6 ++-- codec/encoder/plus/src/welsEncoderExt.cpp | 2 +- 5 files changed, 49 insertions(+), 20 deletions(-) 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; } From 071254748fe93e6df8023e8c388bf4d53ab6f598 Mon Sep 17 00:00:00 2001 From: lyao2 Date: Thu, 20 Mar 2014 13:13:32 +0800 Subject: [PATCH 2/2] avoid QP sudden fluctates --- codec/encoder/core/inc/rc.h | 7 +++--- codec/encoder/core/src/ratectl.cpp | 28 +++++++++++++++++----- codec/encoder/core/src/wels_preprocess.cpp | 8 +++---- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/codec/encoder/core/inc/rc.h b/codec/encoder/core/inc/rc.h index 831c6bb3..6328c5e1 100644 --- a/codec/encoder/core/inc/rc.h +++ b/codec/encoder/core/inc/rc.h @@ -56,9 +56,9 @@ namespace WelsSVCEnc { #define WELS_RC_GOM 1 typedef enum { - RC_MODE0, //Quality mode - RC_MODE1, //Bitrate mode - RC_MODE_LOWBR, //bitrate limited mode + RC_QUALITY_MODE, //Quality mode + RC_BITRATE_MODE, //Bitrate mode + RC_LOW_BW_MODE, //bitrate limited mode } RC_MODES; enum{ @@ -74,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, diff --git a/codec/encoder/core/src/ratectl.cpp b/codec/encoder/core/src/ratectl.cpp index 0caeb249..df206e5e 100644 --- a/codec/encoder/core/src/ratectl.cpp +++ b/codec/encoder/core/src/ratectl.cpp @@ -432,7 +432,23 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { } else if (pWelsSvcRc->iCurrentBitsLevel==BITS_EXCEEDED) { - iLumaQp = 42; + 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; @@ -476,7 +492,7 @@ void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) { iLumaQp = (int32_t)(iLumaQp - pEncCtx->pVaa->sAdaptiveQuantParam.dAverMotionTextureIndexToDeltaQp); - if (pEncCtx->pSvcParam->iRCMode!=RC_MODE_LOWBR) + if (pEncCtx->pSvcParam->iRCMode!=RC_LOW_BW_MODE) iLumaQp = (int32_t)WELS_CLIP3 (iLumaQp,pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp); } @@ -515,11 +531,11 @@ void RcDecideTargetBits (sWelsEncCtx* pEncCtx) { } else { pWelsSvcRc->iTargetBits = (int32_t) (pWelsSvcRc->iRemainingBits * pTOverRc->dTlayerWeight / pWelsSvcRc->dRemainingWeights); - if ((pWelsSvcRc->iTargetBits <= 0) && (pEncCtx->pSvcParam->iRCMode == RC_MODE_LOWBR)) + 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_MODE_LOWBR)) + else if ((pWelsSvcRc->iTargetBits <= pTOverRc->iMinBitsTl) && (pEncCtx->pSvcParam->iRCMode == RC_LOW_BW_MODE)) { pWelsSvcRc->iCurrentBitsLevel = BITS_LIMITED; } @@ -645,8 +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); - if (!(pEncCtx->pSvcParam->iRCMode==RC_MODE_LOWBR)) - 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 128147b6..84f8f81d 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); } @@ -831,11 +831,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;