Merge pull request #554 from ruil2/encoder_update

add maxbitrate parameter
This commit is contained in:
Licai Guo 2014-03-20 14:57:54 +08:00
commit 9d73d273ff
6 changed files with 137 additions and 23 deletions

View File

@ -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;

View File

@ -75,7 +75,6 @@ typedef enum {
cmUnsupportedData,
} CM_RETURN;
/* nal unit type */
enum ENalUnitType {
NAL_UNKNOWN = 0,

View File

@ -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);

View File

@ -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

View File

@ -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;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;
}
}
}
/*!

View File

@ -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<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
@ -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<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: