shithub: openh264

Download patch

ref: 7a29b1f55a4b03948ec70820dead1de963cb1952
parent: d81dbeaa2e24cf7ad7154203145105463bdcc788
parent: 071254748fe93e6df8023e8c388bf4d53ab6f598
author: Licai Guo <licaguo@cisco.com>
date: Fri Mar 21 05:15:18 EDT 2014

Merge pull request #549 from lyao2/rc_tune

RC LOWBR mode merge

--- a/codec/encoder/core/inc/param_svc.h
+++ b/codec/encoder/core/inc/param_svc.h
@@ -252,14 +252,9 @@
   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 @@
 
   /* 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
--- a/codec/encoder/core/inc/rc.h
+++ b/codec/encoder/core/inc/rc.h
@@ -56,10 +56,17 @@
 #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 @@
   //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 @@
   // 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,7 +179,7 @@
   int32_t   iFrameDqBits;
 
   double*    pGomComplexity;
-  int32_t*  	pGomForegroundBlockNum;
+  int32_t*   pGomForegroundBlockNum;
   int32_t*   pCurrentFrameGomSad;
   int32_t*   pGomCost;
 
@@ -177,7 +186,7 @@
   int32_t   iAverageFrameQp;
   int32_t   iNumberMbFrame;
   int32_t   iNumberMbGom;
-  int32_t	  iSliceNum;
+  int32_t	iSliceNum;
   int32_t   iGomSize;
 
   int32_t   iSkipFrameNum;
--- a/codec/encoder/core/src/ratectl.cpp
+++ b/codec/encoder/core/src/ratectl.cpp
@@ -429,7 +429,38 @@
 
   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 @@
 #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,6 +523,8 @@
 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);
@@ -495,6 +531,14 @@
   } 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 @@
 
   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;
 
--- a/codec/encoder/core/src/wels_preprocess.cpp
+++ b/codec/encoder/core/src/wels_preprocess.cpp
@@ -346,7 +346,7 @@
   {
     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 @@
   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;
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -903,7 +903,7 @@
 	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;
   }