From 258185f8c26d7af2ad6eb3a8aeef0aeb4b6f7b51 Mon Sep 17 00:00:00 2001 From: ruil2 Date: Thu, 20 Mar 2014 14:30:20 +0800 Subject: [PATCH] add maxbitrate parameter --- codec/api/svc/codec_app_def.h | 16 ++++ codec/api/svc/codec_def.h | 1 - codec/encoder/core/inc/extern.h | 2 +- codec/encoder/core/inc/param_svc.h | 4 +- codec/encoder/core/src/encoder_ext.cpp | 36 +++++--- codec/encoder/plus/src/welsEncoderExt.cpp | 101 ++++++++++++++++++++-- 6 files changed, 137 insertions(+), 23 deletions(-) diff --git a/codec/api/svc/codec_app_def.h b/codec/api/svc/codec_app_def.h index 2012d4c7..ea3f9936 100644 --- a/codec/api/svc/codec_app_def.h +++ b/codec/api/svc/codec_app_def.h @@ -76,6 +76,7 @@ typedef enum { 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 @@ typedef enum { 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 @@ typedef struct { 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 @@ typedef struct TagEncParamExt /* rc control */ bool bEnableRc; bool bEnableFrameSkip; // allow skipping frames to keep the bitrate within limits + int iMaxBitrate; // max bitrate desired int iMaxQp; int iMinQp; @@ -300,6 +311,11 @@ typedef struct Source_Picture_s { 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; char *pFileName; diff --git a/codec/api/svc/codec_def.h b/codec/api/svc/codec_def.h index e926b886..de3110e1 100644 --- a/codec/api/svc/codec_def.h +++ b/codec/api/svc/codec_def.h @@ -75,7 +75,6 @@ typedef enum { cmUnsupportedData, } CM_RETURN; - /* nal unit type */ enum ENalUnitType { NAL_UNKNOWN = 0, diff --git a/codec/encoder/core/inc/extern.h b/codec/encoder/core/inc/extern.h index bf4ad592..6da94ea2 100644 --- a/codec/encoder/core/inc/extern.h +++ b/codec/encoder/core/inc/extern.h @@ -107,7 +107,7 @@ int32_t ForceCodingIDR (sWelsEncCtx* pCtx); */ 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); diff --git a/codec/encoder/core/inc/param_svc.h b/codec/encoder/core/inc/param_svc.h index b199c938..77b1fa62 100644 --- a/codec/encoder/core/inc/param_svc.h +++ b/codec/encoder/core/inc/param_svc.h @@ -149,6 +149,7 @@ static void FillDefault (SEncParamExt& param, const bool kbEnableRc) { 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 @@ int32_t ParamBaseTranscode (const SEncParamBase& pCodingParam, const bool kbEnab 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 @@ int32_t ParamTranscode (const SEncParamExt& pCodingParam) { 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 @@ -406,7 +407,6 @@ int32_t ParamTranscode (const SEncParamExt& pCodingParam) { pDlp->iSpatialBitrate = pCodingParam.sSpatialLayers[iIdxSpatial].iSpatialBitrate; // target bitrate for current spatial layer - //multi slice pDlp->sSliceCfg.uiSliceMode = pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.uiSliceMode; pDlp->sSliceCfg.sSliceArgument.uiSliceSizeConstraint diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index 0eb9b057..064ebe67 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -376,7 +376,7 @@ void WelsEncoderApplyFrameRate(SWelsSvcCodingParam* pParam) } -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 @@ void WelsEncoderApplyBitRate(SWelsSvcCodingParam* pParam) SDLayerParam* pLayerParam; const int32_t iNumLayers = pParam->iSpatialLayerNum; 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); + if(iLayer == SPATIAL_LAYER_ALL){ + if(pParam->iMaxBitrate 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;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); + } + }else{ + if(pParam->sSpatialLayers[iLayer].iMaxSpatialBitrate 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; + } + } } /*! diff --git a/codec/encoder/plus/src/welsEncoderExt.cpp b/codec/encoder/plus/src/welsEncoderExt.cpp index 49c64fa0..527402dc 100644 --- a/codec/encoder/plus/src/welsEncoderExt.cpp +++ b/codec/encoder/plus/src/welsEncoderExt.cpp @@ -510,8 +510,10 @@ int CWelsH264SVCEncoder::EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSIn } 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 @@ int CWelsH264SVCEncoder::EncodeFrame (const SSourcePicture* kpSrcPic, SFrameBSIn #ifdef DUMP_SRC_PICTURE DumpSrcPicture (pSrc); #endif // DUMP_SRC_PICTURE - return cmResultSuccess; + return kiEncoderReturn; } @@ -540,7 +542,6 @@ int CWelsH264SVCEncoder::EncodeFrameInternal(const SSourcePicture* pSrcPic, SFr 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,18 +827,80 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) { } break; case ENCODER_OPTION_BITRATE: { // Target bit-rate - int32_t iValue = * ((int32_t*)pOption); + SBitrateInfo*pInfo = (static_cast(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(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 @@ -990,7 +1053,29 @@ int CWelsH264SVCEncoder::GetOption (ENCODER_OPTION eOptionId, void* pOption) { "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(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(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: