shithub: openh264

ref: bd8d97dddbb2a86e506d060788cd662ded2a2aa4
dir: /codec/encoder/core/inc/param_svc.h/

View raw version
/*!
 * \copy
 *     Copyright (c)  2009-2013, Cisco Systems
 *     All rights reserved.
 *
 *     Redistribution and use in source and binary forms, with or without
 *     modification, are permitted provided that the following conditions
 *     are met:
 *
 *        * Redistributions of source code must retain the above copyright
 *          notice, this list of conditions and the following disclaimer.
 *
 *        * Redistributions in binary form must reproduce the above copyright
 *          notice, this list of conditions and the following disclaimer in
 *          the documentation and/or other materials provided with the
 *          distribution.
 *
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *     POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * \file	param_svc.h
 *
 * \brief	Configurable parameters in H.264/SVC Encoder
 *
 * \date	4/20/2009 Created
 *
 *************************************************************************************
 */
#if !defined(WELS_ENCODER_PARAMETER_SVC_H__)
#define WELS_ENCODER_PARAMETER_SVC_H__

#include <string.h>
#include <math.h>
#include "typedefs.h"
#include "codec_def.h"
#include "macros.h"
#include "wels_const.h"
#include "wels_common_basis.h"
#include "rc.h"
#include "svc_enc_slice_segment.h"
#include "as264_common.h"

namespace WelsSVCEnc {

#define   INVALID_TEMPORAL_ID   ((uint8_t)0xff)

extern const uint8_t   g_kuiTemporalIdListTable[MAX_TEMPORAL_LEVEL][MAX_GOP_SIZE + 1];

/*!
* \brief	get Logarithms base 2 of (upper/base)
* \param	base	based scaler
* \param	upper	input upper value
* \return	2 based scaling factor
*/
static inline uint32_t GetLogFactor (float base, float upper) {
const double dLog2factor	= log10 (1.0 * upper / base) / log10 (2.0);
const double dEpsilon		= 0.0001;
const double dRound		= floor (dLog2factor + 0.5);

if (dLog2factor < dRound + dEpsilon && dRound < dLog2factor + dEpsilon) {
  return (uint32_t) (dRound);
}
return UINT_MAX;
}

/*
 *	Dependency Layer Parameter
 */
typedef struct TagDLayerParam {
int32_t		iActualWidth;			// input source picture actual width
int32_t		iActualHeight;			// input source picture actual height
int32_t		iFrameWidth;			// frame width
int32_t		iFrameHeight;			// frame height

int32_t		iSpatialBitrate;

/* temporal settings related */
int32_t		iTemporalResolution;
int32_t		iDecompositionStages;
uint8_t     uiCodingIdx2TemporalId[ (1 << MAX_TEMPORAL_LEVEL) + 1];

uint8_t		uiProfileIdc;			// value of profile IDC (0 for auto-detection)
uint8_t		uiLevelIdc;
int8_t		iHighestTemporalId;
//	uint8_t		uiDependencyId;
int8_t      iDLayerQp;

SSliceConfig sSliceCfg;	// multiple slice options

float		fInputFrameRate;		// input frame rate
float		fOutputFrameRate;		// output frame rate

#ifdef ENABLE_FRAME_DUMP
char		sRecFileName[MAX_FNAME_LEN];	// file to be constructed
#endif//ENABLE_FRAME_DUMP
} SDLayerParam;

/*
 *	Cisco OpenH264 Encoder Parameter Configuration
 */
typedef struct TagWelsSvcCodingParam: SEncParamExt{
SDLayerParam	sDependencyLayers[MAX_DEPENDENCY_LAYER];

/* General */
uint32_t	uiGopSize;			// GOP size (at maximal frame rate: 16)
struct {
  int32_t iLeft;
  int32_t iTop;
  int32_t iWidth;
  int32_t iHeight;
} SUsedPicRect;	// the rect in input picture that encoder actually used

char*       pCurPath; // record current lib path such as:/pData/pData/com.wels.enc/lib/

bool		bDeblockingParallelFlag;	// deblocking filter parallelization control flag

short         iCountThreadsNum;                       //              # derived from disable_multiple_slice_idc (=0 or >1) means;

int8_t		iDecompStages;		// GOP size dependency


 public:
TagWelsSvcCodingParam () {
  FillDefault ();
}
~TagWelsSvcCodingParam()	{}

static void FillDefault (SEncParamExt& param) {
  memset(&param, 0, sizeof(param));
  param.uiIntraPeriod		= 0;			// intra period (multiple of GOP size as desired)
  param.iNumRefFrame		= MIN_REF_PIC_COUNT;	// number of reference frame used

  param.iPicWidth	= 0;    //   actual input picture width
  param.iPicHeight	= 0;	//   actual input picture height

  param.fMaxFrameRate		= MAX_FRAME_RATE;	// maximal frame rate [Hz / fps]
  param.iInputCsp			= videoFormatI420;	// input sequence color space in default
  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;
  param.iMultipleThreadIdc		= 1;

  param.iLTRRefNum				= 0;
  param.iLtrMarkPeriod			= 30;	//the min distance of two int32_t references

  param.bEnableSSEI					= true;
  param.bEnableFrameCroppingFlag	= true;	// enable frame cropping flag: true alwayse in application
  // false: Streaming Video Sharing; true: Video Conferencing Meeting;

  /* Deblocking loop filter */
  param.iLoopFilterDisableIdc		= 0;	// 0: on, 1: off, 2: on except for slice boundaries
  param.iLoopFilterAlphaC0Offset	= 0;	// AlphaOffset: valid range [-6, 6], default 0
  param.iLoopFilterBetaOffset		= 0;	// BetaOffset:	valid range [-6, 6], default 0

  /* Rate Control */
  param.iRCMode			= RC_QUALITY_MODE;
  param.iPaddingFlag	= 0;

  param.bEnableDenoise				= false;	// denoise control
  param.bEnableSceneChangeDetect	= true;		// scene change detection control
  param.bEnableBackgroundDetection	= true;		// background detection control
  param.bEnableAdaptiveQuant		= true;		// adaptive quantization control
  param.bEnableFrameSkip		= true;		// frame skipping
  param.bEnableLongTermReference	= false;	// long term reference control
  param.bEnableSpsPpsIdAddition	= true;		// pSps pPps id addition control
  param.bPrefixNalAddingCtrl		= false;		// prefix NAL adding control
  param.iSpatialLayerNum		= 1;		// number of dependency(Spatial/CGS) layers used to be encoded
  param.iTemporalLayerNum			= 1;		// number of temporal layer specified

  param.iMaxQp = 51;
  param.iMinQp = 0;
  param.iUsageType = CAMERA_VIDEO_REAL_TIME;
  param.uiMaxNalSize = 0;

  for(int32_t iLayer = 0;iLayer< MAX_SPATIAL_LAYER_NUM;iLayer++){
    param.sSpatialLayers[iLayer].uiProfileIdc = PRO_BASELINE;
    param.sSpatialLayers[iLayer].uiLevelIdc = LEVEL_5_0;
    param.sSpatialLayers[iLayer].iDLayerQp = SVC_QUALITY_BASE_QP;
    param.sSpatialLayers[iLayer].fFrameRate = param.fMaxFrameRate;
    param.sSpatialLayers[iLayer].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
    param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceSizeConstraint = 1500;
    param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceNum = 1;

    const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP);
    for (int32_t idx = 0; idx < kiLesserSliceNum; idx++)
      param.sSpatialLayers[iLayer].sSliceCfg.sSliceArgument.uiSliceMbNum[idx] = 960;
  }
}

void FillDefault () {
  FillDefault(*this);
  uiGopSize			= 1;			// GOP size (at maximal frame rate: 16)

  SUsedPicRect.iLeft	=
    SUsedPicRect.iTop	=
      SUsedPicRect.iWidth	=
        SUsedPicRect.iHeight = 0;	// the rect in input picture that encoder actually used

  pCurPath			= NULL; // record current lib path such as:/pData/pData/com.wels.enc/lib/

  bDeblockingParallelFlag = false;	// deblocking filter parallelization control flag

  iCountThreadsNum		= 1;	//		# derived from disable_multiple_slice_idc (=0 or >1) means;

  iDecompStages				= 0;	// GOP size dependency, unknown here and be revised later

  memset(sDependencyLayers,0,sizeof(SDLayerParam)*MAX_DEPENDENCY_LAYER);



  //init multi-slice
   sDependencyLayers[0].sSliceCfg.uiSliceMode = SM_SINGLE_SLICE;
   sDependencyLayers[0].sSliceCfg.sSliceArgument.uiSliceSizeConstraint    = 1500;
   sDependencyLayers[0].sSliceCfg.sSliceArgument.uiSliceNum      = 1;

   const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP);
   for(int32_t idx = 0;idx <kiLesserSliceNum;idx++)
		sDependencyLayers[0].sSliceCfg.sSliceArgument.uiSliceMbNum[idx] = 960;
    sDependencyLayers[0].iDLayerQp = SVC_QUALITY_BASE_QP;


}

int32_t ParamBaseTranscode (const SEncParamBase& pCodingParam) {

  iInputCsp		= pCodingParam.iInputCsp;		// color space of input sequence
  fMaxFrameRate		= WELS_CLIP3 (pCodingParam.fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
  iTargetBitrate	= pCodingParam.iTargetBitrate;
  iUsageType = pCodingParam.iUsageType;
  iPicWidth   = pCodingParam.iPicWidth;
  iPicHeight  = pCodingParam.iPicHeight;

  SUsedPicRect.iLeft = 0;
  SUsedPicRect.iTop  = 0;
  SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1);
  SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1);

  iRCMode = pCodingParam.iRCMode;    // rc mode

  int8_t iIdxSpatial	= 0;
  uint8_t uiProfileIdc		= PRO_BASELINE;

  SDLayerParam* pDlp		= &sDependencyLayers[0];

  while (iIdxSpatial < iSpatialLayerNum) {

    pDlp->uiProfileIdc		= uiProfileIdc;
    sSpatialLayers[iIdxSpatial].fFrameRate	= WELS_CLIP3 (pCodingParam.fMaxFrameRate,
        MIN_FRAME_RATE, MAX_FRAME_RATE);
    pDlp->fInputFrameRate	=
      pDlp->fOutputFrameRate	= WELS_CLIP3 (sSpatialLayers[iIdxSpatial].fFrameRate, MIN_FRAME_RATE,
                                            MAX_FRAME_RATE);
#ifdef ENABLE_FRAME_DUMP
    pDlp->sRecFileName[0]	= '\0';	// file to be constructed
#endif//ENABLE_FRAME_DUMP
   pDlp->iActualWidth = sSpatialLayers[iIdxSpatial].iVideoWidth = iPicWidth;
   pDlp->iFrameWidth = pDlp->iActualWidth;

  pDlp->iActualHeight = sSpatialLayers[iIdxSpatial].iVideoHeight = iPicHeight;
  pDlp->iFrameHeight = pDlp->iActualHeight;

    pDlp->iSpatialBitrate	=
		sSpatialLayers[iIdxSpatial].iSpatialBitrate = pCodingParam.iTargetBitrate;	// target bitrate for current spatial layer

   pDlp->iDLayerQp = SVC_QUALITY_BASE_QP;

    uiProfileIdc	= PRO_SCALABLE_BASELINE;
    ++ pDlp;
    ++ iIdxSpatial;
  }
   SetActualPicResolution();

   return 0;
}
void GetBaseParams (SEncParamBase* pCodingParam) {
  pCodingParam->iUsageType     = iUsageType;
  pCodingParam->iInputCsp      = iInputCsp;
  pCodingParam->iPicWidth      = iPicWidth;
  pCodingParam->iPicHeight     = iPicHeight;
  pCodingParam->iTargetBitrate = iTargetBitrate;
  pCodingParam->iRCMode        = iRCMode;
  pCodingParam->fMaxFrameRate  = fMaxFrameRate;
}
int32_t ParamTranscode (const SEncParamExt& pCodingParam) {
  float fParamMaxFrameRate		= WELS_CLIP3 (pCodingParam.fMaxFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);

  iInputCsp		= pCodingParam.iInputCsp;		// color space of input sequence
  uiFrameToBeCoded	= (uint32_t) -
                      1;		// frame to be encoded (at input frame rate), -1 dependents on length of input sequence
  iUsageType = pCodingParam.iUsageType;
  iPicWidth   = pCodingParam.iPicWidth;
  iPicHeight  = pCodingParam.iPicHeight;

  SUsedPicRect.iLeft = 0;
  SUsedPicRect.iTop  = 0;
  SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1);
  SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1);

  /* Deblocking loop filter */
  iLoopFilterDisableIdc	= pCodingParam.iLoopFilterDisableIdc;	// 0: on, 1: off, 2: on except for slice boundaries,
  if (iLoopFilterDisableIdc == 0) // Loop filter requested to be enabled
    iLoopFilterDisableIdc = 2; // Disable loop filter on slice boundaries since that's not allowed with multithreading
  iLoopFilterAlphaC0Offset = 0;	// AlphaOffset: valid range [-6, 6], default 0
  iLoopFilterBetaOffset	= 0;	// BetaOffset:	valid range [-6, 6], default 0

  bEnableFrameCroppingFlag	= true;

  /* Rate Control */
  iRCMode = pCodingParam.iRCMode;    // rc mode
  iPaddingFlag = pCodingParam.iPaddingFlag;

  iTargetBitrate		= pCodingParam.iTargetBitrate;	// target bitrate
  iMaxBitrate           = pCodingParam.iMaxBitrate;

  uiMaxNalSize          = pCodingParam.uiMaxNalSize;
  /* Denoise Control */
  bEnableDenoise = pCodingParam.bEnableDenoise ? true : false;    // Denoise Control  // only support 0 or 1 now

  /* Scene change detection control */
  bEnableSceneChangeDetect	= true;

  /* Background detection Control */
  bEnableBackgroundDetection = pCodingParam.bEnableBackgroundDetection ? true : false;

  /* Adaptive quantization control */
  bEnableAdaptiveQuant	= pCodingParam.bEnableAdaptiveQuant ? true : false;

  /* Frame skipping */
  bEnableFrameSkip	= pCodingParam.bEnableFrameSkip ? true : false;

  /* Enable int32_t term reference */
  bEnableLongTermReference	= pCodingParam.bEnableLongTermReference ? true : false;
  iLtrMarkPeriod = pCodingParam.iLtrMarkPeriod;

  iMultipleThreadIdc = pCodingParam.iMultipleThreadIdc;

  /* For ssei information */
  bEnableSSEI		= true;

  /* Layer definition */
  iSpatialLayerNum	= (int8_t)WELS_CLIP3 (pCodingParam.iSpatialLayerNum, 1,
                        MAX_DEPENDENCY_LAYER); // number of dependency(Spatial/CGS) layers used to be encoded
  iTemporalLayerNum		= (int8_t)WELS_CLIP3(pCodingParam.iTemporalLayerNum, 1, MAX_TEMPORAL_LEVEL);// number of temporal layer specified

  uiGopSize			= 1 << (iTemporalLayerNum - 1);	// Override GOP size based temporal layer
  iDecompStages		= iTemporalLayerNum - 1;	// WELS_LOG2( uiGopSize );// GOP size dependency
  uiIntraPeriod		= pCodingParam.uiIntraPeriod;// intra period (multiple of GOP size as desired)
  if (uiIntraPeriod == (uint32_t) (-1))
    uiIntraPeriod = 0;
  else if (uiIntraPeriod & (uiGopSize-1))	// none multiple of GOP size
    uiIntraPeriod = ((uiIntraPeriod + uiGopSize - 1) / uiGopSize) * uiGopSize;

  if (iUsageType == SCREEN_CONTENT_REAL_TIME) {
    if (bEnableLongTermReference) {
      iLTRRefNum = WELS_CLIP3(pCodingParam.iLTRRefNum,1,LONG_TERM_REF_NUM_SCREEN);
      iNumRefFrame = WELS_MAX(1, WELS_LOG2 (uiGopSize)) + iLTRRefNum;
    } else {
      iLTRRefNum = 0;
      iNumRefFrame = 1;
    }
  } else {
    iLTRRefNum = bEnableLongTermReference ? WELS_CLIP3(pCodingParam.iLTRRefNum,1,LONG_TERM_REF_NUM) : 0;
    iNumRefFrame		= ((uiGopSize >> 1) > 1) ? ((uiGopSize >> 1) + iLTRRefNum) : (MIN_REF_PIC_COUNT + iLTRRefNum);
    iNumRefFrame		= WELS_CLIP3 (iNumRefFrame, MIN_REF_PIC_COUNT, MAX_REFERENCE_PICTURE_COUNT_NUM);
  }
  iLtrMarkPeriod  = pCodingParam.iLtrMarkPeriod;

  bPrefixNalAddingCtrl	= pCodingParam.bPrefixNalAddingCtrl;

  bEnableSpsPpsIdAddition =
    pCodingParam.bEnableSpsPpsIdAddition;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference.
  //SHOULD enable this feature.

  SDLayerParam* pDlp		= &sDependencyLayers[0];
  float fMaxFr			= .0f;
  uint8_t uiProfileIdc		= PRO_BASELINE;
  int8_t iIdxSpatial	= 0;
  while (iIdxSpatial < iSpatialLayerNum) {
    pDlp->uiProfileIdc		= (pCodingParam.sSpatialLayers[iIdxSpatial].uiProfileIdc == PRO_UNKNOWN)?uiProfileIdc:pCodingParam.sSpatialLayers[iIdxSpatial].uiProfileIdc;
    pDlp->uiLevelIdc        = (pCodingParam.sSpatialLayers[iIdxSpatial].uiLevelIdc == LEVEL_UNKNOWN)?LEVEL_5_0:pCodingParam.sSpatialLayers[iIdxSpatial].uiLevelIdc;

    float fLayerFrameRate	= WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate,
        MIN_FRAME_RATE, fParamMaxFrameRate);
    pDlp->fInputFrameRate	=
      pDlp->fOutputFrameRate	= WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, MAX_FRAME_RATE);
    if (pDlp->fInputFrameRate > fMaxFr + EPSN)
      fMaxFr = pDlp->fInputFrameRate;

#ifdef ENABLE_FRAME_DUMP
    pDlp->sRecFileName[0]	= '\0';	// file to be constructed
#endif//ENABLE_FRAME_DUMP
    pDlp->iFrameWidth		= pCodingParam.sSpatialLayers[iIdxSpatial].iVideoWidth;	// frame width
    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;
    pDlp->sSliceCfg.sSliceArgument.uiSliceSizeConstraint
      = (uint32_t) (pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceSizeConstraint);
    pDlp->sSliceCfg.sSliceArgument.uiSliceNum
      = pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceNum;
    const int32_t kiLesserSliceNum = ((MAX_SLICES_NUM < MAX_SLICES_NUM_TMP) ? MAX_SLICES_NUM : MAX_SLICES_NUM_TMP);
    memcpy (pDlp->sSliceCfg.sSliceArgument.uiSliceMbNum,
            pCodingParam.sSpatialLayers[iIdxSpatial].sSliceCfg.sSliceArgument.uiSliceMbNum,	// confirmed_safe_unsafe_usage
            kiLesserSliceNum * sizeof (uint32_t)) ;

    pDlp->iDLayerQp = pCodingParam.sSpatialLayers[iIdxSpatial].iDLayerQp;

    uiProfileIdc	= PRO_SCALABLE_BASELINE;
    ++ pDlp;
    ++ iIdxSpatial;
  }

  fMaxFrameRate	= fMaxFr;

  SetActualPicResolution();

  return 0;
}

// assuming that the width/height ratio of all spatial layers are the same

void SetActualPicResolution() {
  int32_t iSpatialIdx			= iSpatialLayerNum - 1;
  SDLayerParam* pDlayer		= &sDependencyLayers[iSpatialIdx];

  for (; iSpatialIdx >= 0; iSpatialIdx --) {
    pDlayer	= &sDependencyLayers[iSpatialIdx];

    pDlayer->iActualWidth = pDlayer->iFrameWidth;
    pDlayer->iActualHeight = pDlayer->iFrameHeight;
    pDlayer->iFrameWidth = WELS_ALIGN (pDlayer->iActualWidth, MB_WIDTH_LUMA);
    pDlayer->iFrameHeight = WELS_ALIGN (pDlayer->iActualHeight, MB_HEIGHT_LUMA);
  }
}

/*!
* \brief	determined key coding tables for temporal scalability, uiProfileIdc etc for each spatial layer settings
* \param	SWelsSvcCodingParam, and carried with known GOP size, max, input and output frame rate of each spatial
* \return	NONE (should ensure valid parameter before this procedure)
*/
void DetermineTemporalSettings() {
  const int32_t iDecStages		= WELS_LOG2 (
                                  uiGopSize);	// (int8_t)GetLogFactor(1.0f, 1.0f * pcfg->uiGopSize);	//log2(uiGopSize)
  const uint8_t* pTemporalIdList	= &g_kuiTemporalIdListTable[iDecStages][0];
  SDLayerParam* pDlp				= &sDependencyLayers[0];
  uint8_t uiProfileIdc				= PRO_BASELINE;
  int8_t i						= 0;

  while (i < iSpatialLayerNum) {
    const uint32_t kuiLogFactorInOutRate	= GetLogFactor (pDlp->fOutputFrameRate, pDlp->fInputFrameRate);
    const uint32_t kuiLogFactorMaxInRate	= GetLogFactor (pDlp->fInputFrameRate, fMaxFrameRate);
    int32_t iNotCodedMask = 0;
    int8_t iMaxTemporalId = 0;

    memset (pDlp->uiCodingIdx2TemporalId, INVALID_TEMPORAL_ID, sizeof (pDlp->uiCodingIdx2TemporalId));
    pDlp->uiProfileIdc = uiProfileIdc;	// PRO_BASELINE, PRO_SCALABLE_BASELINE;

    iNotCodedMask	= (1 << (kuiLogFactorInOutRate + kuiLogFactorMaxInRate)) - 1;
    for (uint32_t uiFrameIdx = 0; uiFrameIdx <= uiGopSize; ++ uiFrameIdx) {
      if (0 == (uiFrameIdx & iNotCodedMask)) {
        const int8_t kiTemporalId = pTemporalIdList[uiFrameIdx];
        pDlp->uiCodingIdx2TemporalId[uiFrameIdx] = kiTemporalId;
        if (kiTemporalId > iMaxTemporalId) {
          iMaxTemporalId = kiTemporalId;
        }
      }
    }

    pDlp->iHighestTemporalId	= iMaxTemporalId;
    pDlp->iTemporalResolution	= kuiLogFactorMaxInRate + kuiLogFactorInOutRate;
    pDlp->iDecompositionStages	= iDecStages - kuiLogFactorMaxInRate - kuiLogFactorInOutRate;

    uiProfileIdc	= PRO_SCALABLE_BASELINE;
    ++ pDlp;
    ++ i;
  }
  iDecompStages = (int8_t)iDecStages;
}

} SWelsSvcCodingParam;

static inline int32_t FreeCodingParam (SWelsSvcCodingParam** pParam, CMemoryAlign* pMa) {
if (pParam == NULL || *pParam == NULL || pMa == NULL)
  return 1;
pMa->WelsFree (*pParam, "SWelsSvcCodingParam");
*pParam = NULL;
return 0;
}

static inline int32_t AllocCodingParam (SWelsSvcCodingParam** pParam, CMemoryAlign* pMa) {
  if (pParam == NULL || pMa == NULL)
    return 1;
  if (*pParam != NULL) {
    FreeCodingParam (pParam, pMa);
  }
  SWelsSvcCodingParam* pCodingParam = (SWelsSvcCodingParam*)pMa->WelsMalloc (sizeof (SWelsSvcCodingParam),
                                    "SWelsSvcCodingParam");
  if (NULL == pCodingParam)
    return 1;
  *pParam = pCodingParam;
  return 0;
}

}//end of namespace WelsSVCEnc

#endif//WELS_ENCODER_PARAMETER_SVC_H__