shithub: openh264

Download patch

ref: 9d73d273ff81f12fb05c86d21231106ae307b8ce
parent: bef50d9ae1d035097b7dfee8eaa6003de615f47c
parent: 258185f8c26d7af2ad6eb3a8aeef0aeb4b6f7b51
author: Licai Guo <licaguo@cisco.com>
date: Thu Mar 20 10:57:54 EDT 2014

Merge pull request #554 from ruil2/encoder_update

 add maxbitrate parameter

--- a/codec/api/svc/codec_app_def.h
+++ b/codec/api/svc/codec_app_def.h
@@ -76,6 +76,7 @@
   ENCODER_OPTION_SVC_ENCODE_PARAM_EXT,
   ENCODER_OPTION_FRAME_RATE,
   ENCODER_OPTION_BITRATE,
+  ENCODER_OPTION_MAX_BITRATE,
   ENCODER_OPTION_INTER_SPATIAL_PRED,
   ENCODER_OPTION_RC_MODE,
   ENCODER_PADDING_PADDING,
@@ -118,6 +119,14 @@
   VIDEO_CODING_LAYER = 1
 } LAYER_TYPE;
 
+typedef enum {
+    SPATIAL_LAYER_0 = 0,
+    SPATIAL_LAYER_1 = 1,
+    SPATIAL_LAYER_2 = 2,
+    SPATIAL_LAYER_3 = 3,
+    SPATIAL_LAYER_ALL = 4,
+} LAYER_NUM;
+
 //enumerate the type of video bitstream which is provided to decoder
 typedef enum {
   VIDEO_BITSTREAM_AVC               = 0,
@@ -174,6 +183,7 @@
   int	iVideoHeight;		// video size in cy specified for a layer
   float	fFrameRate;		// frame rate specified for a layer
   int	iSpatialBitrate;	// target bitrate for a spatial layer
+  int   iMaxSpatialBitrate;
   unsigned int	uiProfileIdc;	// value of profile IDC (0 for auto-detection)
   int    iDLayerQp;
 
@@ -222,6 +232,7 @@
   /* rc control */
   bool    bEnableRc;
   bool    bEnableFrameSkip; // allow skipping frames to keep the bitrate within limits
+  int     iMaxBitrate;        // max bitrate desired
   int     iMaxQp;
   int     iMinQp;
 
@@ -299,6 +310,11 @@
   int 		iPicHeight;				// luma picture height in y coordinate
   long long uiTimeStamp;
 } SSourcePicture;
+
+typedef struct Bitrate_Info_s{
+  LAYER_NUM iLayer;
+  int iBitrate;    //the maximum bitrate
+}SBitrateInfo;
 
 typedef struct Dump_Layer_s{
 	int iLayer;
--- a/codec/api/svc/codec_def.h
+++ b/codec/api/svc/codec_def.h
@@ -75,7 +75,6 @@
   cmUnsupportedData,
 } CM_RETURN;
 
-
 /* nal unit type */
 enum ENalUnitType {
   NAL_UNKNOWN = 0,
--- a/codec/encoder/core/inc/extern.h
+++ b/codec/encoder/core/inc/extern.h
@@ -107,7 +107,7 @@
  */
 int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNew);
 void WelsEncoderApplyFrameRate (SWelsSvcCodingParam* pParam);
-void WelsEncoderApplyBitRate(SWelsSvcCodingParam* pParam);
+void WelsEncoderApplyBitRate(SWelsSvcCodingParam* pParam,int32_t iLayer);
 
 int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRecoverRequest);
 
--- a/codec/encoder/core/inc/param_svc.h
+++ b/codec/encoder/core/inc/param_svc.h
@@ -149,6 +149,7 @@
   param.uiFrameToBeCoded	= (uint32_t) - 1;		// frame to be encoded (at input frame rate)
 
   param.iTargetBitrate			= 0;	// overall target bitrate introduced in RC module
+  param.iMaxBitrate             = MAX_BIT_RATE;
 #ifdef MT_ENABLED
   param.iMultipleThreadIdc		= 0;	// auto to detect cpu cores inside
 #else
@@ -279,7 +280,6 @@
     pDlp->iSpatialBitrate	=
 		sSpatialLayers[iIdxSpatial].iSpatialBitrate = pCodingParam.iTargetBitrate;	// target bitrate for current spatial layer
 
-
    pDlp->iDLayerQp = SVC_QUALITY_BASE_QP;
 
     uiProfileIdc	= PRO_SCALABLE_BASELINE;
@@ -334,6 +334,7 @@
   iPaddingFlag = pCodingParam.iPaddingFlag;
 
   iTargetBitrate		= pCodingParam.iTargetBitrate;	// target bitrate
+  iMaxBitrate           = pCodingParam.iMaxBitrate;
 
   /* Denoise Control */
   bEnableDenoise = pCodingParam.bEnableDenoise ? true : false;    // Denoise Control  // only support 0 or 1 now
@@ -405,7 +406,6 @@
     pDlp->iFrameHeight		= pCodingParam.sSpatialLayers[iIdxSpatial].iVideoHeight;// frame height
     pDlp->iSpatialBitrate	=
       pCodingParam.sSpatialLayers[iIdxSpatial].iSpatialBitrate;	// target bitrate for current spatial layer
-
 
     //multi slice
     pDlp->sSliceCfg.uiSliceMode = pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.uiSliceMode;
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -376,7 +376,7 @@
 }
 
 
-void WelsEncoderApplyBitRate(SWelsSvcCodingParam* pParam)
+void WelsEncoderApplyBitRate(SWelsSvcCodingParam* pParam,int iLayer)
 {
   //TODO (Sijia):  this is a temporary solution which keep the ratio between layers
   //but it is also possible to fulfill the bitrate of lower layer first
@@ -384,16 +384,30 @@
   SDLayerParam* pLayerParam;
   const int32_t iNumLayers = pParam->iSpatialLayerNum;
   int32_t i, iOrigTotalBitrate=0;
-  //read old BR
-  for (i=0;i<iNumLayers;i++) {
-    iOrigTotalBitrate += pParam->sDependencyLayers[i].iSpatialBitrate;
-  }
-  //write new BR
-  float fRatio = 0.0;
-  for (i=0;i<iNumLayers;i++) {
-    pLayerParam = &(pParam->sDependencyLayers[i]);
-    fRatio = pLayerParam->iSpatialBitrate/(static_cast<float>(iOrigTotalBitrate));
-    pLayerParam->iSpatialBitrate = static_cast<int32_t>(pParam->iTargetBitrate*fRatio);
+  if(iLayer == SPATIAL_LAYER_ALL){
+    if(pParam->iMaxBitrate <pParam->iTargetBitrate){
+      WelsLog (NULL, WELS_LOG_WARNING,"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE,overall settting,TargetBitrate = %d,iMaxBitrate = %d\n",
+        pParam->iTargetBitrate,pParam->iMaxBitrate);
+      pParam->iMaxBitrate  = pParam->iTargetBitrate;
+    }
+    //read old BR
+    for (i=0;i<iNumLayers;i++) {
+     iOrigTotalBitrate += pParam->sDependencyLayers[i].iSpatialBitrate;
+    }
+    //write new BR
+    float fRatio = 0.0;
+    for (i=0;i<iNumLayers;i++) {
+      pLayerParam = &(pParam->sDependencyLayers[i]);
+      fRatio = pLayerParam->iSpatialBitrate/(static_cast<float>(iOrigTotalBitrate));
+      pLayerParam->iSpatialBitrate = static_cast<int32_t>(pParam->iTargetBitrate*fRatio);
+    }
+  }else{
+    if(pParam->sSpatialLayers[iLayer].iMaxSpatialBitrate <pParam->sSpatialLayers[iLayer].iSpatialBitrate){
+      WelsLog (NULL, WELS_LOG_WARNING,"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE,iLayer = %d,iTargetBitrate = %d,iMaxBitrate = %d\n",
+        iLayer,pParam->sSpatialLayers[iLayer].iSpatialBitrate,pParam->sSpatialLayers[iLayer].iMaxSpatialBitrate);
+      pParam->sSpatialLayers[iLayer].iMaxSpatialBitrate = pParam->sSpatialLayers[iLayer].iSpatialBitrate;
+    }
+
   }
 }
 /*!
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -510,8 +510,10 @@
   }
 
   const int32_t kiEncoderReturn = EncodeFrameInternal(kpSrcPic, pBsInfo);
+
   if(kiEncoderReturn != cmResultSuccess)
     return kiEncoderReturn;
+
 #ifdef REC_FRAME_COUNT
   ++ m_uiCountFrameNum;
   WelsLog (m_pEncContext, WELS_LOG_INFO,
@@ -521,7 +523,7 @@
 #ifdef DUMP_SRC_PICTURE
   DumpSrcPicture (pSrc);
 #endif // DUMP_SRC_PICTURE
-  return cmResultSuccess;
+  return kiEncoderReturn;
 }
 
 
@@ -540,7 +542,6 @@
     WelsLog (m_pEncContext, WELS_LOG_ERROR, "unexpected return(%d) from EncodeFrameInternal()!\n", kiEncoderReturn);
     return cmUnkonwReason;
   }
-
   ///////////////////for test
 #ifdef OUTPUT_BIT_STREAM
   if (pBsInfo->eOutputFrameType != videoFrameTypeInvalid && pBsInfo->eOutputFrameType != videoFrameTypeSkip) {
@@ -826,20 +827,82 @@
   }
   break;
   case ENCODER_OPTION_BITRATE: {	// Target bit-rate
-    int32_t iValue = * ((int32_t*)pOption);
+    SBitrateInfo*pInfo = (static_cast<SBitrateInfo *>(pOption));
+    int32_t iBitrate = pInfo->iBitrate;
 #ifdef REC_FRAME_COUNT
     WelsLog (m_pEncContext, WELS_LOG_INFO,
       "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d\n",
       m_uiCountFrameNum, m_iCspInternal, iValue);
 #endif//REC_FRAME_COUNT
-    if (iValue<=0) {
-        return cmInitParaError;
+    if (iBitrate<=0) {
+	  WelsLog (m_pEncContext, WELS_LOG_ERROR,"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE,iBitrate = %d\n",iBitrate);
+      return cmInitParaError;
     }
+    iBitrate	= WELS_CLIP3 (iBitrate, MIN_BIT_RATE, MAX_BIT_RATE);
+	switch(pInfo->iLayer){
+	case SPATIAL_LAYER_ALL:
+	  m_pEncContext->pSvcParam->iTargetBitrate = iBitrate;
+	break;
+	case SPATIAL_LAYER_0:
+	  m_pEncContext->pSvcParam->sSpatialLayers[0].iSpatialBitrate = iBitrate;
+	break;
+	case SPATIAL_LAYER_1:
+	  m_pEncContext->pSvcParam->sSpatialLayers[1].iSpatialBitrate = iBitrate;
+	break;
+	case SPATIAL_LAYER_2:
+	  m_pEncContext->pSvcParam->sSpatialLayers[2].iSpatialBitrate = iBitrate;
+	break;
+	case SPATIAL_LAYER_3:
+	  m_pEncContext->pSvcParam->sSpatialLayers[3].iSpatialBitrate = iBitrate;
+	break;
+	default:
+	   WelsLog (m_pEncContext, WELS_LOG_ERROR,"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE,iLayer = %d\n",pInfo->iLayer);
+	return cmInitParaError;
+	break;
+	}
     //adjust to valid range
-    m_pEncContext->pSvcParam->iTargetBitrate	= WELS_CLIP3 (iValue, MIN_BIT_RATE, MAX_BIT_RATE);
-    WelsEncoderApplyBitRate (m_pEncContext->pSvcParam);
+    WelsEncoderApplyBitRate (m_pEncContext->pSvcParam,pInfo->iLayer);
   }
   break;
+  case ENCODER_OPTION_MAX_BITRATE: {	// Target bit-rate
+    SBitrateInfo*pInfo = (static_cast<SBitrateInfo *>(pOption));
+    int32_t iBitrate = pInfo->iBitrate;
+
+#ifdef REC_FRAME_COUNT
+    WelsLog (m_pEncContext, WELS_LOG_INFO,
+      "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d\n",
+      m_uiCountFrameNum, m_iCspInternal, iValue);
+#endif//REC_FRAME_COUNT
+	if (iBitrate<=0) {
+	  WelsLog (m_pEncContext, WELS_LOG_ERROR,"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_MAX_BITRATE,iBitrate = %d\n",iBitrate);
+	   return cmInitParaError;
+	}
+	iBitrate	= WELS_CLIP3 (iBitrate, MIN_BIT_RATE, MAX_BIT_RATE);
+	switch(pInfo->iLayer){
+	case SPATIAL_LAYER_ALL:
+	  m_pEncContext->pSvcParam->iMaxBitrate = iBitrate;
+	break;
+	case SPATIAL_LAYER_0:
+	  m_pEncContext->pSvcParam->sSpatialLayers[0].iMaxSpatialBitrate = iBitrate;
+	break;
+	case SPATIAL_LAYER_1:
+	  m_pEncContext->pSvcParam->sSpatialLayers[1].iMaxSpatialBitrate = iBitrate;
+	break;
+	case SPATIAL_LAYER_2:
+	  m_pEncContext->pSvcParam->sSpatialLayers[2].iMaxSpatialBitrate = iBitrate;
+	break;
+	case SPATIAL_LAYER_3:
+	  m_pEncContext->pSvcParam->sSpatialLayers[3].iMaxSpatialBitrate = iBitrate;
+	break;
+	default:
+	  WelsLog (m_pEncContext, WELS_LOG_ERROR,"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_MAX_BITRATE,iLayer = %d\n",pInfo->iLayer);
+			return cmInitParaError;
+	break;
+	}
+	  //adjust to valid range
+	WelsEncoderApplyBitRate (m_pEncContext->pSvcParam,pInfo->iLayer);
+  }
+  break;
   case ENCODER_OPTION_RC_MODE: {	// 0:quality mode;1:bit-rate mode
     int32_t iValue = * ((int32_t*)pOption);
     m_pEncContext->pSvcParam->iRCMode	= iValue;
@@ -990,7 +1053,29 @@
              "CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_BITRATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n",
              m_uiCountFrameNum, m_iCspInternal);
 #endif//REC_FRAME_COUNT
-    * ((int32_t*)pOption)	= m_pEncContext->pSvcParam->iTargetBitrate;
+    SBitrateInfo*pInfo = (static_cast<SBitrateInfo *>(pOption));
+    if((pInfo->iLayer!=SPATIAL_LAYER_ALL)||(pInfo->iLayer!=SPATIAL_LAYER_0)||(pInfo->iLayer!=SPATIAL_LAYER_1)||(pInfo->iLayer!=SPATIAL_LAYER_2)||(pInfo->iLayer!=SPATIAL_LAYER_3))
+        return cmInitParaError;
+    if(pInfo->iLayer == SPATIAL_LAYER_ALL){
+      pInfo->iBitrate = m_pEncContext->pSvcParam->iTargetBitrate;
+    }else{
+      pInfo->iBitrate = m_pEncContext->pSvcParam->sSpatialLayers[pInfo->iLayer].iSpatialBitrate;
+	}
+  }
+  break;
+  case ENCODER_OPTION_MAX_BITRATE: {	// Target bit-rate
+#ifdef REC_FRAME_COUNT
+    WelsLog (m_pEncContext, WELS_LOG_INFO,"CWelsH264SVCEncoder::GetOption():ENCODER_OPTION_MAX_BITRATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x\n",
+	          m_uiCountFrameNum, m_iCspInternal);
+#endif//REC_FRAME_COUNT
+    SBitrateInfo*pInfo = (static_cast<SBitrateInfo *>(pOption));
+	if((pInfo->iLayer!=SPATIAL_LAYER_ALL)||(pInfo->iLayer!=SPATIAL_LAYER_0)||(pInfo->iLayer!=SPATIAL_LAYER_1)||(pInfo->iLayer!=SPATIAL_LAYER_2)||(pInfo->iLayer!=SPATIAL_LAYER_3))
+	  return cmInitParaError;
+	if(pInfo->iLayer == SPATIAL_LAYER_ALL){
+      pInfo->iBitrate = m_pEncContext->pSvcParam->iMaxBitrate;
+	}else{
+	  pInfo->iBitrate = m_pEncContext->pSvcParam->sSpatialLayers[pInfo->iLayer].iMaxSpatialBitrate;
+	}
   }
   break;
   default: