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: