shithub: openh264

Download patch

ref: a6f44f5f79661d036a654964b7497550381d668d
parent: 37b64fc9d60e3ea9b8764eb1250fe9de16096c9e
parent: 45c78f438e803f454cb30786e8c35a3c0969b3bd
author: ruil2 <ruil2@cisco.com>
date: Thu Jun 19 08:25:33 EDT 2014

Merge pull request #983 from JuannyWang/delay_skip

 [delay skip] delay skip to relieve bitrate burst somehow

--- a/codec/console/enc/src/welsenc.cpp
+++ b/codec/console/enc/src/welsenc.cpp
@@ -153,6 +153,18 @@
           }
           iLeftTargetBitrate -= pDLayer->iSpatialBitrate;
         }
+      } else if (strTag[0].compare ("MaxSpatialBitrate") == 0) {
+        pDLayer->iMaxSpatialBitrate = 1000 * atoi (strTag[1].c_str());
+        if (pSvcParam.iRCMode != RC_OFF_MODE) {
+          if (pDLayer->iMaxSpatialBitrate <= 0) {
+            fprintf (stderr, "Invalid max spatial bitrate(%d) in dependency layer #%d.\n", pDLayer->iMaxSpatialBitrate, iLayer);
+            return -1;
+          }
+          if (pDLayer->iMaxSpatialBitrate < pDLayer->iSpatialBitrate) {
+            fprintf (stderr, "Invalid max spatial(#%d) bitrate(%d) setting::: < layerBitrate(%d)!\n", iLayer, pDLayer->iMaxSpatialBitrate, pDLayer->iSpatialBitrate);
+            return -1;
+          }
+        }
       } else if (strTag[0].compare ("InitialQP") == 0) {
         sLayerCtx.iDLayerQp	= atoi (strTag[1].c_str());
       } else if (strTag[0].compare ("SliceMode") == 0) {
@@ -253,6 +265,12 @@
           fprintf (stderr, "Invalid target bitrate setting due to RC enabled. Check TargetBitrate field please!\n");
           return 1;
         }
+      } else if (strTag[0].compare ("MaxOverallBitrate") == 0) {
+        pSvcParam.iMaxBitrate	= 1000 * atoi (strTag[1].c_str());
+        if ((pSvcParam.iRCMode != RC_OFF_MODE) && pSvcParam.iMaxBitrate <= 0) {
+          fprintf (stderr, "Invalid max overall bitrate setting due to RC enabled. Check MaxOverallBitrate field please!\n");
+          return 1;
+        }
       } else if (strTag[0].compare ("EnableDenoise") == 0) {
         pSvcParam.bEnableDenoise	= atoi (strTag[1].c_str()) ? true : false;
       } else if (strTag[0].compare ("EnableSceneChangeDetection") == 0) {
@@ -339,6 +357,7 @@
   printf ("  -betaOffset BetaOffset (-6..+6): valid range\n");
   printf ("  -rc	  rate control mode: 0-quality mode; 1-bitrate mode; 2-bitrate limited mode; -1-rc off \n");
   printf ("  -tarb	  Overall target bitrate\n");
+  printf ("  -maxbrTotal  Overall max bitrate\n");
   printf ("  -numl   Number Of Layers: Must exist with layer_cfg file and the number of input layer_cfg file must equal to the value set by this command\n");
   printf ("  The options below are layer-based: (need to be set with layer id)\n");
   printf ("  -lconfig (Layer) (spatial layer configure file)\n");
@@ -348,6 +367,7 @@
   printf ("  -frout  	(Layer) (output frame rate)\n");
   printf ("  -lqp		(Layer) (base quality layer qp : must work with -ldeltaqp or -lqparr)\n");
   printf ("  -ltarb	    (Layer) (spatial layer target bitrate)\n");
+  printf ("  -lmaxb     (Layer) (spatial layer max bitrate)\n");
   printf ("  -slcmd   (Layer) (spatial layer slice mode): pls refer to layerX.cfg for details ( -slcnum: set target slice num; -slcsize: set target slice size constraint ) \n");
   printf ("  -trace   (Level)\n");
   printf ("\n");
@@ -436,6 +456,9 @@
     else if (!strcmp (pCommand, "-tarb") && (n < argc))
       pSvcParam.iTargetBitrate = 1000*atoi (argv[n++]);
 
+    else if (!strcmp (pCommand, "-maxbrTotal") && (n < argc))
+      pSvcParam.iMaxBitrate = 1000*atoi  (argv[n++]);
+
     else if (!strcmp (pCommand, "-numl") && (n < argc)) {
       pSvcParam.iSpatialLayerNum = atoi (argv[n++]);
     }
@@ -484,6 +507,12 @@
       pDLayer->iSpatialBitrate	= 1000 * atoi (argv[n++]);
     }
 
+    else if (!strcmp (pCommand, "-lmaxb") && (n + 1 < argc)) {
+      unsigned int	iLayer = atoi (argv[n++]);
+      SSpatialLayerConfig* pDLayer = &pSvcParam.sSpatialLayers[iLayer];
+      pDLayer->iMaxSpatialBitrate	= 1000 * atoi (argv[n++]);
+    }
+
     else if (!strcmp (pCommand, "-slcmd") && (n + 1 < argc)) {
       unsigned int	iLayer = atoi (argv[n++]);
       SSpatialLayerConfig* pDLayer = &pSvcParam.sSpatialLayers[iLayer];
@@ -537,6 +566,7 @@
   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.iRCMode       = RC_QUALITY_MODE;       //  rc mode control
   sParam.iTemporalLayerNum = 3;	// layer number at temporal level
   sParam.iSpatialLayerNum	= 4;	// layer number at spatial level
@@ -558,6 +588,7 @@
   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].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
 
   ++ iIndexLayer;
@@ -566,6 +597,7 @@
   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].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
 
   ++ iIndexLayer;
@@ -574,6 +606,7 @@
   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].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
   sParam.sSpatialLayers[iIndexLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1;
 
@@ -583,6 +616,7 @@
   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].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
   sParam.sSpatialLayers[iIndexLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1;
 
--- a/codec/encoder/core/inc/param_svc.h
+++ b/codec/encoder/core/inc/param_svc.h
@@ -307,7 +307,10 @@
     iPaddingFlag = pCodingParam.iPaddingFlag;
 
     iTargetBitrate		= pCodingParam.iTargetBitrate;	// target bitrate
-    iMaxBitrate           = pCodingParam.iMaxBitrate;
+    iMaxBitrate         = pCodingParam.iMaxBitrate;
+    if (iMaxBitrate < iTargetBitrate) {
+      iMaxBitrate  = iTargetBitrate;
+    }
 
     uiMaxNalSize          = pCodingParam.uiMaxNalSize;
     /* Denoise Control */
--- a/codec/encoder/core/inc/rc.h
+++ b/codec/encoder/core/inc/rc.h
@@ -212,6 +212,7 @@
   int32_t   iBufferFullnessPadding;
   int32_t   iPaddingSize;
   int32_t   iPaddingBitrateStat;
+  bool      bSkipFlag;
 
   SRCSlicing*	pSlicingOverRc;
   SRCTemporal* pTemporalOverRc;
@@ -218,6 +219,7 @@
 } SWelsSvcRc;
 
 typedef  void (*PWelsRCPictureInitFunc) (void* pCtx);
+typedef  void (*PWelsRCPictureDelayJudgeFunc) (void* pCtx);
 typedef  void (*PWelsRCPictureInfoUpdateFunc) (void* pCtx, int32_t iLayerSize);
 typedef  void (*PWelsRCMBInfoUpdateFunc) (void* pCtx, SMB* pCurMb, int32_t iCostLuma, SSlice* pSlice);
 typedef  void (*PWelsRCMBInitFunc) (void* pCtx, SMB* pCurMb, SSlice* pSlice);
@@ -224,6 +226,7 @@
 
 typedef  struct  WelsRcFunc_s {
   PWelsRCPictureInitFunc			pfWelsRcPictureInit;
+  PWelsRCPictureDelayJudgeFunc      pfWelsRcPicDelayJudge;
   PWelsRCPictureInfoUpdateFunc	pfWelsRcPictureInfoUpdate;
   PWelsRCMBInitFunc				pfWelsRcMbInit;
   PWelsRCMBInfoUpdateFunc			pfWelsRcMbInfoUpdate;
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -2938,6 +2938,23 @@
     return ENC_RETURN_SUCCESS;
   }
 
+  //loop each layer to check if have skip frame when RC and frame skip enable
+  if (RC_OFF_MODE != pCtx->pSvcParam->iRCMode && true == pCtx->pSvcParam->bEnableFrameSkip) {
+    bool bSkipMustFlag = false;
+    for (int32_t i = 0; i< iSpatialNum; i++) {
+      pCtx->uiDependencyId = (uint8_t)(pSpatialIndexMap+i)->iDid;
+      pCtx->pFuncList->pfRc.pfWelsRcPicDelayJudge(pCtx);
+      if (true == pCtx->pWelsSvcRc[pCtx->uiDependencyId].bSkipFlag) {
+        bSkipMustFlag = true;
+      }
+    }
+    if (true == bSkipMustFlag) {
+      pFbi->eOutputFrameType = videoFrameTypeSkip;
+      return ENC_RETURN_SUCCESS;
+    }
+  }
+
+
   InitFrameCoding (pCtx, eFrameType);
 
   iCurTid	= GetTemporalLevel (&pSvcParam->sDependencyLayers[pSpatialIndexMap->iDid], pCtx->iCodingIndex,
--- a/codec/encoder/core/src/ratectl.cpp
+++ b/codec/encoder/core/src/ratectl.cpp
@@ -711,6 +711,22 @@
   }
 }
 
+void WelsRcFrameDelayJudge(void* pCtx) {
+  sWelsEncCtx* pEncCtx = (sWelsEncCtx*)pCtx;
+  SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
+  SSpatialLayerConfig* pDLayerParam     = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId];
+  SSpatialLayerInternal* pDLayerParamInternal     = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];
+
+  int32_t iSentBits = WELS_ROUND(pDLayerParam->iSpatialBitrate / pDLayerParamInternal->fOutputFrameRate);
+
+  pWelsSvcRc->bSkipFlag = false;
+  if (pWelsSvcRc->iBufferFullnessSkip > pWelsSvcRc->iBufferSizeSkip) {
+    pWelsSvcRc->bSkipFlag = true;
+    pWelsSvcRc->iBufferFullnessSkip -= iSentBits;
+    pWelsSvcRc->iBufferFullnessSkip = WELS_MAX(pWelsSvcRc->iBufferFullnessSkip, 0);
+  }
+}
+
 void RcVBufferCalculationPadding (sWelsEncCtx* pEncCtx) {
   SWelsSvcRc* pWelsSvcRc = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
   const int32_t kiOutputBits = WELS_DIV_ROUND(pWelsSvcRc->iBitsPerFrame, INT_MULTIPLY);
@@ -862,8 +878,8 @@
 #endif
 
 
-  if (pEncCtx->pSvcParam->bEnableFrameSkip &&
-      pEncCtx->uiDependencyId == pEncCtx->pSvcParam->iSpatialLayerNum - 1) {
+  if (pEncCtx->pSvcParam->bEnableFrameSkip /*&&
+      pEncCtx->uiDependencyId == pEncCtx->pSvcParam->iSpatialLayerNum - 1*/) {
     RcVBufferCalculationSkip (pEncCtx);
   }
 
@@ -976,6 +992,7 @@
   switch (iModule) {
   case WELS_RC_DISABLE:
     pRcf->pfWelsRcPictureInit = WelsRcPictureInitDisable;
+    pRcf->pfWelsRcPicDelayJudge = NULL;
     pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateDisable;
     pRcf->pfWelsRcMbInit = WelsRcMbInitDisable;
     pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateDisable;
@@ -983,6 +1000,7 @@
   case WELS_RC_GOM:
   default:
     pRcf->pfWelsRcPictureInit = WelsRcPictureInitGom;
+    pRcf->pfWelsRcPicDelayJudge = WelsRcFrameDelayJudge;
     pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateGom;
     pRcf->pfWelsRcMbInit = WelsRcMbInitGom;
     pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateGom;
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -623,10 +623,11 @@
     WelsLog (m_pEncContext, WELS_LOG_INFO, "ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, sEncodingParam.iInputCsp= 0x%x\n",
              sEncodingParam.iInputCsp);
     WelsLog (m_pEncContext, WELS_LOG_INFO,
-             "coding_param->iPicWidth= %d;coding_param->iPicHeight= %d;coding_param->iTargetBitrate= %d;coding_param->iRCMode= %d;coding_param->iPaddingFlag= %d;coding_param->iTemporalLayerNum= %d;coding_param->iSpatialLayerNum= %d;coding_param->fFrameRate= %.6ff;coding_param->iInputCsp= %d;coding_param->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableLongTermReference= %d;coding_param->iLtrMarkPeriod= %d;\n",
+             "coding_param->iPicWidth= %d;coding_param->iPicHeight= %d;coding_param->iTargetBitrate= %d; coding_param->iMaxBitrate= %d; coding_param->iRCMode= %d;coding_param->iPaddingFlag= %d;coding_param->iTemporalLayerNum= %d;coding_param->iSpatialLayerNum= %d;coding_param->fFrameRate= %.6ff;coding_param->iInputCsp= %d;coding_param->uiIntraPeriod= %d;coding_param->bEnableSpsPpsIdAddition = %d;coding_param->bPrefixNalAddingCtrl = %d;coding_param->bEnableDenoise= %d;coding_param->bEnableBackgroundDetection= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableAdaptiveQuant= %d;coding_param->bEnableLongTermReference= %d;coding_param->iLtrMarkPeriod= %d;\n",
              sEncodingParam.iPicWidth,
              sEncodingParam.iPicHeight,
              sEncodingParam.iTargetBitrate,
+             sEncodingParam.iMaxBitrate,
              sEncodingParam.iRCMode,
              sEncodingParam.iPaddingFlag,
              sEncodingParam.iTemporalLayerNum,
@@ -646,11 +647,12 @@
     while (i < sEncodingParam.iSpatialLayerNum) {
       SSpatialLayerConfig* pSpatialCfg = &sEncodingParam.sSpatialLayers[i];
       WelsLog (m_pEncContext, WELS_LOG_INFO,
-               "coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iSpatialBitrate= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.iSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d;\n",
+               "coding_param->sSpatialLayers[%d]: .iVideoWidth= %d; .iVideoHeight= %d; .fFrameRate= %.6ff; .iSpatialBitrate= %d; .iMaxSpatialBitrate= %d; .sSliceCfg.uiSliceMode= %d; .sSliceCfg.sSliceArgument.iSliceNum= %d; .sSliceCfg.sSliceArgument.uiSliceSizeConstraint= %d;\n",
                i, pSpatialCfg->iVideoWidth,
                pSpatialCfg->iVideoHeight,
                pSpatialCfg->fFrameRate,
                pSpatialCfg->iSpatialBitrate,
+               pSpatialCfg->iMaxSpatialBitrate,
                pSpatialCfg->sSliceCfg.uiSliceMode,
                pSpatialCfg->sSliceCfg.sSliceArgument.uiSliceNum,
                pSpatialCfg->sSliceCfg.sSliceArgument.uiSliceSizeConstraint
--- a/testbin/layer2.cfg
+++ b/testbin/layer2.cfg
@@ -13,6 +13,7 @@
 InitialQP       24			# Quantization parameters for base quality layer
 #================================ RATE CONTROL ===============================
 SpatialBitrate		600		# Unit: kbps, controled by DisableRC also
+MaxSpatialBitrate   800     # Unit: kbps, max bitrate for current layer
 #============================== MultiSlice Slice Argument ==============================
 # for S/M Slice(s) mode settings
 SliceMode			0		# 0: sigle slice mode; >0: multiple slices mode, see below;
--- a/testbin/layer2_arbitrary_res.cfg
+++ b/testbin/layer2_arbitrary_res.cfg
@@ -14,6 +14,7 @@
 InitialQP       24			# Quantization parameters for base quality layer
 #================================ RATE CONTROL ===============================
 SpatialBitrate		600		# Unit: kbps, controled by DisableRC also
+MaxSpatialBitrate   800     # Unit: kbps, max bitrate for current layer
 #============================== MultiSlice Slice Argument ==============================
 # for S/M Slice(s) mode settings
 SliceMode			0		# 0: sigle slice mode; >0: multiple slices mode, see below;
--- a/testbin/layer2_vd.cfg
+++ b/testbin/layer2_vd.cfg
@@ -14,6 +14,7 @@
 InitialQP       24			# Quantization parameters for base quality layer
 #================================ RATE CONTROL ===============================
 SpatialBitrate		600		# Unit: kbps, controled by DisableRC also
+MaxSpatialBitrate   800     # Unit: kbps, max bitrate for current layer
 #============================== MultiSlice Slice Argument ==============================
 # for S/M Slice(s) mode settings
 SliceMode			0		# 0: sigle slice mode; >0: multiple slices mode, see below;
--- a/testbin/layer2_vd_rc.cfg
+++ b/testbin/layer2_vd_rc.cfg
@@ -14,6 +14,7 @@
 InitialQP       24			# Quantization parameters for base quality layer
 #================================ RATE CONTROL ===============================
 SpatialBitrate		600		# Unit: kbps, controled by DisableRC also
+MaxSpatialBitrate   800     # Unit: kbps, max bitrate for current layer
 #============================== MultiSlice Slice Argument ==============================
 # for S/M Slice(s) mode settings
 SliceMode			0		# 0: sigle slice mode; >0: multiple slices mode, see below;
--- a/testbin/welsenc.cfg
+++ b/testbin/welsenc.cfg
@@ -31,6 +31,7 @@
 #============================== RATE CONTROL ==============================
 RCMode			        0				    # 0: quality mode;  1: bitrate mode;  2: bitrate limited mode;  -1: rc off mode
 TargetBitrate			5000				    # Unit: kbps, controled by EnableRC also
+MaxOverallBitrate       6000                    # Unit: kbps, max bitrate overall
 EnableFrameSkip			1		#Enable Frame Skip
 
 #============================== DENOISE CONTROL ==============================
--- a/testbin/welsenc_arbitrary_res.cfg
+++ b/testbin/welsenc_arbitrary_res.cfg
@@ -32,6 +32,7 @@
 #============================== RATE CONTROL ==============================
 RCMode                          0                                   # 0: quality mode;  1: bitrate mode;  2: bitrate limited mode;  -1: rc off mode
 TargetBitrate			5000				    # Unit: kbps, controled by EnableRC also
+MaxOverallBitrate       6000                    # Unit: kbps, max bitrate overall
 
 #============================== DENOISE CONTROL ==============================
 EnableDenoise                   0              # Enable Denoise (1: enable, 0: disable)
--- a/testbin/welsenc_ios.cfg
+++ b/testbin/welsenc_ios.cfg
@@ -32,6 +32,7 @@
 #============================== RATE CONTROL ==============================
 RCMode                          0                                   # 0: quality mode;  1: bitrate mode;  2: bitrate limited mode;  -1: rc off mode
 TargetBitrate			5000				    # Unit: kbps, controled by EnableRC also
+MaxOverallBitrate       6000                 # Unit: kbps, max bitrate overall
 EnableFrameSkip			1		#Enable Frame Skip
 
 #============================== DENOISE CONTROL ==============================
--- a/testbin/welsenc_vd_1d.cfg
+++ b/testbin/welsenc_vd_1d.cfg
@@ -32,6 +32,7 @@
 #============================== RATE CONTROL ==============================
 RCMode                          0                                   # 0: quality mode;  1: bitrate mode;  2: bitrate limited mode;  -1: rc off mode
 TargetBitrate			5000				    # Unit: kbps, controled by EnableRC also
+MaxOverallBitrate       6000                    # Unit: kbps, max bitrate overall
 
 #============================== DENOISE CONTROL ==============================
 EnableDenoise                   0              # Enable Denoise (1: enable, 0: disable)
--- a/testbin/welsenc_vd_rc.cfg
+++ b/testbin/welsenc_vd_rc.cfg
@@ -32,6 +32,7 @@
 #============================== RATE CONTROL ==============================
 RCMode                          0                                   # 0: quality mode;  1: bitrate mode;  2: bitrate limited mode;  -1: rc off mode
 TargetBitrate			600				    # Unit: kbps, controled by EnableRC also
+MaxOverallBitrate       800                 # Unit: kbps, max bitrate overall
 
 #============================== DENOISE CONTROL ==============================
 EnableDenoise                   1              # Enable Denoise (1: enable, 0: disable)