shithub: openh264

Download patch

ref: 61f1bac9ff383ba5958c838b7921f846d2f4277c
parent: 767073cbb2bdc3197cecd1b4ccf1c200750d1c78
parent: 4999b816abbdd8672bd042b756657820c624060b
author: ekr <ekr@rtfm.com>
date: Wed Jan 8 12:39:08 EST 2014

Merge pull request #119 from sijchen/merge6

complete the encoder interface of bit rate and frame rate updating

--- a/codec/encoder/core/inc/extern.h
+++ b/codec/encoder/core/inc/extern.h
@@ -108,6 +108,8 @@
  *			SVC adjustment results in new requirement in memory blocks adjustment
  */
 int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNew);
+void WelsEncoderApplyFrameRate (SWelsSvcCodingParam* pParam);
+void WelsEncoderApplyBitRate(SWelsSvcCodingParam* pParam);
 
 int32_t FilterLTRRecoveryRequest (sWelsEncCtx* pCtx, SLTRRecoverRequest* pLTRRecoverRequest);
 
--- a/codec/encoder/core/inc/wels_const.h
+++ b/codec/encoder/core/inc/wels_const.h
@@ -90,6 +90,10 @@
 #define MAX_FRAME_RATE			30	// maximal frame rate to support
 #define MIN_FRAME_RATE			1	// minimal frame rate need support
 
+#define MAX_BIT_RATE			INT_MAX	// maximal bit rate to support
+//TODO {Sijia}: 30fps*MaxCPB in level5.1 = 30*240000*1000bits = 7 200 000 000, larger than INT_MAX which is 2147483647, but this is also very big and abnormal number, should figure out a reasonable number after discussion
+#define MIN_BIT_RATE			1	// minimal bit rate need support
+
 #define SVC_QUALITY_BASE_QP		26
 #define SVC_QUALITY_DELTA_QP	(-3)
 
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -423,6 +423,53 @@
   return ParamValidation (pCodingParam);
 }
 
+
+void WelsEncoderApplyFrameRate(SWelsSvcCodingParam* pParam)
+{
+  SDLayerParam* pLayerParam;
+  const float kfEpsn = 0.000001f;
+  const int32_t kiNumLayer = pParam->iNumDependencyLayer;
+  int32_t i;
+  const float kfMaxFrameRate = pParam->fMaxFrameRate;
+  float fRatio;
+  float fTargetOutputFrameRate;
+
+  //set input frame rate to each layer
+  for (i=0;i<kiNumLayer;i++) {
+    pLayerParam = &(pParam->sDependencyLayers[i]);
+
+    fRatio = pLayerParam->fOutputFrameRate / pLayerParam->fInputFrameRate;
+    if ( (kfMaxFrameRate - pLayerParam->fInputFrameRate) > kfEpsn
+        || (kfMaxFrameRate - pLayerParam->fInputFrameRate) < -kfEpsn ) {
+      pLayerParam->fInputFrameRate = kfMaxFrameRate;
+      fTargetOutputFrameRate = kfMaxFrameRate*fRatio;
+      pLayerParam->fOutputFrameRate = (fTargetOutputFrameRate>=6)?fTargetOutputFrameRate:(pLayerParam->fInputFrameRate);
+      //TODO:{Sijia} from design, there is no sense to have temporal layer when under 6fps even with such setting?
+    }
+  }
+}
+
+
+void WelsEncoderApplyBitRate(SWelsSvcCodingParam* pParam)
+{
+  //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
+
+  SDLayerParam* pLayerParam;
+  const int32_t iNumLayers = pParam->iNumDependencyLayer;
+  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);
+  }
+}
 /*!
  * \brief	acquire count number of layers and NALs based on configurable paramters dependency
  * \pParam	pCtx				sWelsEncCtx*
--- a/codec/encoder/plus/src/welsEncoderExt.cpp
+++ b/codec/encoder/plus/src/welsEncoderExt.cpp
@@ -942,8 +942,12 @@
              "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_FRAME_RATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d\n",
              m_uiCountFrameNum, m_iCspInternal, iValue);
 #endif//REC_FRAME_COUNT
-    m_pEncContext->pSvcParam->fMaxFrameRate	= iValue;
-
+    if (iValue<=0) {
+      return cmInitParaError;
+    }
+    //adjust to valid range
+    m_pEncContext->pSvcParam->fMaxFrameRate	= WELS_CLIP3 (iValue, MIN_FRAME_RATE, MAX_FRAME_RATE);
+    WelsEncoderApplyFrameRate (m_pEncContext->pSvcParam);
   }
   break;
   case ENCODER_OPTION_BITRATE: {	// Target bit-rate
@@ -950,11 +954,15 @@
     int32_t iValue = * ((int32_t*)pOption);
 #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);
+      "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_BITRATE, m_uiCountFrameNum= %d, m_iCspInternal= 0x%x, iValue= %d\n",
+      m_uiCountFrameNum, m_iCspInternal, iValue);
 #endif//REC_FRAME_COUNT
-    m_pEncContext->pSvcParam->iTargetBitrate	= iValue;
-
+    if (iValue<=0) {
+        return cmInitParaError;
+    }
+    //adjust to valid range
+    m_pEncContext->pSvcParam->iTargetBitrate	= WELS_CLIP3 (iValue, MIN_BIT_RATE, MAX_BIT_RATE);
+    WelsEncoderApplyBitRate (m_pEncContext->pSvcParam);
   }
   break;
   case ENCODER_OPTION_RC_MODE: {	// 0:quality mode;1:bit-rate mode