diff --git a/codec/encoder/core/inc/extern.h b/codec/encoder/core/inc/extern.h index d4c55bb4..31be5c13 100644 --- a/codec/encoder/core/inc/extern.h +++ b/codec/encoder/core/inc/extern.h @@ -108,6 +108,8 @@ int32_t ForceCodingIDR (sWelsEncCtx* pCtx); * 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); diff --git a/codec/encoder/core/inc/wels_const.h b/codec/encoder/core/inc/wels_const.h index 7ea61123..047960be 100644 --- 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) diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index cc515235..dca8db9d 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -423,6 +423,53 @@ int32_t ParamValidationExt (void* pParam) { 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;isDependencyLayers[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;isDependencyLayers[i].iSpatialBitrate; + } + //write new BR + float fRatio = 0.0; + for (i=0;isDependencyLayers[i]); + fRatio = pLayerParam->iSpatialBitrate/(static_cast(iOrigTotalBitrate)); + pLayerParam->iSpatialBitrate = static_cast(pParam->iTargetBitrate*fRatio); + } +} /*! * \brief acquire count number of layers and NALs based on configurable paramters dependency * \pParam pCtx sWelsEncCtx* diff --git a/codec/encoder/plus/src/welsEncoderExt.cpp b/codec/encoder/plus/src/welsEncoderExt.cpp index f307ba8d..e1af01d2 100644 --- a/codec/encoder/plus/src/welsEncoderExt.cpp +++ b/codec/encoder/plus/src/welsEncoderExt.cpp @@ -942,19 +942,27 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) { "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 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