text: /*!
   * \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 "rc.h"
  #include "svc_enc_slice_segment.h"
  #include "as264_common.h"
  
  namespace WelsEnc {
  
  #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) {
  #if defined(_M_X64) && _MSC_VER == 1800
    _set_FMA3_enable(0);
  #endif
    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       iTemporalResolution;
    int32_t       iDecompositionStages;
    uint8_t       uiCodingIdx2TemporalId[ (1 << MAX_TEMPORAL_LEVEL) + 1];
  
    int8_t        iHighestTemporalId;
    float         fInputFrameRate;                // input frame rate
    float         fOutputFrameRate;               // output frame rate
    uint16_t          uiIdrPicId;           // IDR picture id: [0, 65535], this one is used for LTR
    int32_t           iCodingIndex;
    int32_t           iFrameIndex;            // count how many frames elapsed during coding context currently
    bool              bEncCurFrmAsIdrFlag;
    int32_t           iFrameNum;              // current frame number coding
    int32_t           iPOC;                   // frame iPOC
  #ifdef ENABLE_FRAME_DUMP
    char          sRecFileName[MAX_FNAME_LEN];    // file to be constructed
  #endif//ENABLE_FRAME_DUMP
  } SSpatialLayerInternal;
  
  /*
   *  Cisco OpenH264 Encoder Parameter Configuration
   */
  typedef struct TagWelsSvcCodingParam: SEncParamExt {
    SSpatialLayerInternal 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
    int32_t   iBitsVaryPercentage;
  
    int8_t   iDecompStages;          // GOP size dependency
    int32_t  iMaxNumRefFrame;
  
   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          = AUTO_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.iComplexityMode       = LOW_COMPLEXITY;
      param.iTargetBitrate        = UNSPECIFIED_BIT_RATE; // overall target bitrate introduced in RC module
      param.iMaxBitrate           = UNSPECIFIED_BIT_RATE;
      param.iMultipleThreadIdc    = 1;
      param.bUseLoadBalancing = true;
  
      param.iLTRRefNum            = 0;
      param.iLtrMarkPeriod        = 30;   //the min distance of two int32_t references
  
      param.bEnableSSEI           = false;
      param.bSimulcastAVC         = false;
      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.iEntropyCodingModeFlag        = 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.eSpsPpsIdStrategy             = INCREASING_ID;// 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 = QP_MAX_VALUE;
      param.iMinQp = QP_MIN_VALUE;
      param.iUsageType = CAMERA_VIDEO_REAL_TIME;
      param.uiMaxNalSize = 0;
      param.bIsLosslessLink = false;
      for (int32_t iLayer = 0; iLayer < MAX_SPATIAL_LAYER_NUM; iLayer++) {
        param.sSpatialLayers[iLayer].uiProfileIdc = PRO_UNKNOWN;
        param.sSpatialLayers[iLayer].uiLevelIdc = LEVEL_UNKNOWN;
        param.sSpatialLayers[iLayer].iDLayerQp = SVC_QUALITY_BASE_QP;
        param.sSpatialLayers[iLayer].fFrameRate = param.fMaxFrameRate;
  
        param.sSpatialLayers[iLayer].iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
  
        param.sSpatialLayers[iLayer].sSliceArgument.uiSliceMode = SM_SINGLE_SLICE;
        param.sSpatialLayers[iLayer].sSliceArgument.uiSliceNum = 0; //AUTO, using number of CPU cores
        param.sSpatialLayers[iLayer].sSliceArgument.uiSliceSizeConstraint = 1500;
  
        param.sSpatialLayers[iLayer].bAspectRatioPresent = false; // do not write any of the following information to the header
        param.sSpatialLayers[iLayer].eAspectRatio = ASP_UNSPECIFIED;
        param.sSpatialLayers[iLayer].sAspectRatioExtWidth = 0;
        param.sSpatialLayers[iLayer].sAspectRatioExtHeight = 0;
  
        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].sSliceArgument.uiSliceMbNum[idx] = 0; //default, using one row a slice if uiSliceMode is SM_RASTER_MODE
  
        // See codec_app_def.h for more info about members bVideoSignalTypePresent through uiColorMatrix.  The default values
        // used below preserve the previous behavior; i.e., no additional information will be written to the output file.
        param.sSpatialLayers[iLayer].bVideoSignalTypePresent = false;			// do not write any of the following information to the header
        param.sSpatialLayers[iLayer].uiVideoFormat = VF_UNDEF;				// undefined
        param.sSpatialLayers[iLayer].bFullRange = false;						// analog video data range [16, 235]
        param.sSpatialLayers[iLayer].bColorDescriptionPresent = false;		// do not write any of the following three items to the header
        param.sSpatialLayers[iLayer].uiColorPrimaries = CP_UNDEF;				// undefined
        param.sSpatialLayers[iLayer].uiTransferCharacteristics = TRC_UNDEF;	// undefined
        param.sSpatialLayers[iLayer].uiColorMatrix = CM_UNDEF;				// undefined
      }
    }
  
    void FillDefault() {
      FillDefault (*this);
      uiGopSize = 1;                      // GOP size (at maximal frame rate: 16)
      iMaxNumRefFrame = AUTO_REF_PIC_COUNT;
      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
  
      iDecompStages               = 0;    // GOP size dependency, unknown here and be revised later
      iBitsVaryPercentage = 10;
    }
  
    int32_t ParamBaseTranscode (const SEncParamBase& pCodingParam) {
  
      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 << 1));
      SUsedPicRect.iHeight = ((iPicHeight >> 1) * (1 << 1));
  
      iRCMode = pCodingParam.iRCMode;    // rc mode
  
      int8_t iIdxSpatial = 0;
      EProfileIdc uiProfileIdc = PRO_UNKNOWN;
      if (iEntropyCodingModeFlag)
        uiProfileIdc = PRO_MAIN;
      SSpatialLayerInternal* pDlp = &sDependencyLayers[0];
  
      while (iIdxSpatial < iSpatialLayerNum) {
  
        sSpatialLayers->uiProfileIdc              = uiProfileIdc;
        sSpatialLayers->uiLevelIdc                = LEVEL_UNKNOWN;
        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->iActualHeight = sSpatialLayers[iIdxSpatial].iVideoHeight = iPicHeight;
  
        sSpatialLayers->iSpatialBitrate =
          sSpatialLayers[iIdxSpatial].iSpatialBitrate = pCodingParam.iTargetBitrate; // target bitrate for current spatial layer
  
        sSpatialLayers->iMaxSpatialBitrate = UNSPECIFIED_BIT_RATE;
        sSpatialLayers->iDLayerQp = SVC_QUALITY_BASE_QP;
  
        uiProfileIdc = (!bSimulcastAVC) ? PRO_SCALABLE_BASELINE : uiProfileIdc;
        ++ pDlp;
        ++ iIdxSpatial;
      }
      SetActualPicResolution();
  
      return 0;
    }
    void GetBaseParams (SEncParamBase* pCodingParam) {
      pCodingParam->iUsageType     = iUsageType;
      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);
  
      iUsageType = pCodingParam.iUsageType;
      iPicWidth   = pCodingParam.iPicWidth;
      iPicHeight  = pCodingParam.iPicHeight;
      fMaxFrameRate = fParamMaxFrameRate;
      iComplexityMode = pCodingParam.iComplexityMode;
  
      SUsedPicRect.iLeft = 0;
      SUsedPicRect.iTop  = 0;
      SUsedPicRect.iWidth = ((iPicWidth >> 1) << 1);
      SUsedPicRect.iHeight = ((iPicHeight >> 1) << 1);
  
      iMultipleThreadIdc = pCodingParam.iMultipleThreadIdc;
      bUseLoadBalancing = pCodingParam.bUseLoadBalancing;
  
      /* Deblocking loop filter */
      iLoopFilterDisableIdc       = pCodingParam.iLoopFilterDisableIdc;      // 0: on, 1: off, 2: on except for slice boundaries,
      iLoopFilterAlphaC0Offset    = pCodingParam.iLoopFilterAlphaC0Offset;   // AlphaOffset: valid range [-6, 6], default 0
      iLoopFilterBetaOffset       = pCodingParam.iLoopFilterBetaOffset;      // BetaOffset:  valid range [-6, 6], default 0
      iEntropyCodingModeFlag      = pCodingParam.iEntropyCodingModeFlag;
      bEnableFrameCroppingFlag    = pCodingParam.bEnableFrameCroppingFlag;
  
      /* Rate Control */
      iRCMode = pCodingParam.iRCMode;    // rc mode
      bSimulcastAVC = pCodingParam.bSimulcastAVC;
      iPaddingFlag = pCodingParam.iPaddingFlag;
  
      iTargetBitrate      = pCodingParam.iTargetBitrate;  // target bitrate
      iMaxBitrate         = pCodingParam.iMaxBitrate;
      if ((iMaxBitrate != UNSPECIFIED_BIT_RATE) && (iMaxBitrate < iTargetBitrate)) {
        iMaxBitrate  = iTargetBitrate;
      }
      iMaxQp = pCodingParam.iMaxQp;
      iMinQp = pCodingParam.iMinQp;
      uiMaxNalSize          = pCodingParam.uiMaxNalSize;
      /* Denoise Control */
      bEnableDenoise = pCodingParam.bEnableDenoise ? true : false;    // Denoise Control  // only support 0 or 1 now
  
      /* Scene change detection control */
      bEnableSceneChangeDetect   = pCodingParam.bEnableSceneChangeDetect;
  
      /* 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;
      bIsLosslessLink = pCodingParam.bIsLosslessLink;
      if (iUsageType == SCREEN_CONTENT_REAL_TIME && !bIsLosslessLink && bEnableLongTermReference) {
        bEnableLongTermReference = false;
      }
  
      /* For ssei information */
      bEnableSSEI         = pCodingParam.bEnableSSEI;
      bSimulcastAVC       = pCodingParam.bSimulcastAVC;
  
      /* 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 (((pCodingParam.iNumRefFrame != AUTO_REF_PIC_COUNT)
           && !((pCodingParam.iNumRefFrame > MAX_REF_PIC_COUNT) || (pCodingParam.iNumRefFrame < MIN_REF_PIC_COUNT)))
          || ((iNumRefFrame != AUTO_REF_PIC_COUNT) && (pCodingParam.iNumRefFrame == AUTO_REF_PIC_COUNT))) {
        iNumRefFrame  = pCodingParam.iNumRefFrame;
      }
      if ((iNumRefFrame != AUTO_REF_PIC_COUNT) && (iNumRefFrame > iMaxNumRefFrame)) {
        iMaxNumRefFrame = iNumRefFrame;
      }
      iLTRRefNum  = (pCodingParam.bEnableLongTermReference ? pCodingParam.iLTRRefNum : 0);
      iLtrMarkPeriod  = pCodingParam.iLtrMarkPeriod;
  
      bPrefixNalAddingCtrl = pCodingParam.bPrefixNalAddingCtrl;
  
      if ( (CONSTANT_ID == pCodingParam.eSpsPpsIdStrategy)
          || (INCREASING_ID == pCodingParam.eSpsPpsIdStrategy)
          || (SPS_LISTING == pCodingParam.eSpsPpsIdStrategy)
          || (SPS_LISTING_AND_PPS_INCREASING == pCodingParam.eSpsPpsIdStrategy)
          || (SPS_PPS_LISTING == pCodingParam.eSpsPpsIdStrategy)) {
      eSpsPpsIdStrategy =
        pCodingParam.eSpsPpsIdStrategy;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference.
      //SHOULD enable this feature.
      } else {
        // keep the default value
      }
  
      SSpatialLayerInternal* pDlp        = &sDependencyLayers[0];
      SSpatialLayerConfig* pSpatialLayer = &sSpatialLayers[0];
      EProfileIdc uiProfileIdc           = iEntropyCodingModeFlag ? PRO_HIGH : PRO_BASELINE;
      int8_t iIdxSpatial  = 0;
      while (iIdxSpatial < iSpatialLayerNum) {
        pSpatialLayer->uiProfileIdc      = (pCodingParam.sSpatialLayers[iIdxSpatial].uiProfileIdc == PRO_UNKNOWN) ? uiProfileIdc :
                                        pCodingParam.sSpatialLayers[iIdxSpatial].uiProfileIdc;
        pSpatialLayer->uiLevelIdc        = pCodingParam.sSpatialLayers[iIdxSpatial].uiLevelIdc;
  
        float fLayerFrameRate     = WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].fFrameRate,
                                            MIN_FRAME_RATE, fParamMaxFrameRate);
        pDlp->fInputFrameRate     = fParamMaxFrameRate;
        pSpatialLayer->fFrameRate =
          pDlp->fOutputFrameRate  = WELS_CLIP3 (fLayerFrameRate, MIN_FRAME_RATE, fParamMaxFrameRate);
  
  #ifdef ENABLE_FRAME_DUMP
        pDlp->sRecFileName[0]     = '\0'; // file to be constructed
  #endif//ENABLE_FRAME_DUMP
        pSpatialLayer->iVideoWidth = WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].iVideoWidth, 0,
                                     iPicWidth);  // frame width
        pSpatialLayer->iVideoHeight = WELS_CLIP3 (pCodingParam.sSpatialLayers[iIdxSpatial].iVideoHeight, 0,
                                      iPicHeight);// frame height
  
        pSpatialLayer->iSpatialBitrate    =
          pCodingParam.sSpatialLayers[iIdxSpatial].iSpatialBitrate;       // target bitrate for current spatial layer
        pSpatialLayer->iMaxSpatialBitrate =
          pCodingParam.sSpatialLayers[iIdxSpatial].iMaxSpatialBitrate;
  
        if ((iSpatialLayerNum==1) && (iIdxSpatial==0)) {
          if (pSpatialLayer->iVideoWidth == 0) {
            pSpatialLayer->iVideoWidth = iPicWidth;
          }
          if (pSpatialLayer->iVideoHeight == 0) {
            pSpatialLayer->iVideoHeight = iPicHeight;
          }
          if (pSpatialLayer->iSpatialBitrate == 0) {
            pSpatialLayer->iSpatialBitrate = iTargetBitrate;
          }
          if (pSpatialLayer->iMaxSpatialBitrate == 0) {
            pSpatialLayer->iMaxSpatialBitrate = iMaxBitrate;
          }
        }
  
        //multi slice
        pSpatialLayer->sSliceArgument = pCodingParam.sSpatialLayers[iIdxSpatial].sSliceArgument;
  
        memcpy (&(pSpatialLayer->sSliceArgument),
                &(pCodingParam.sSpatialLayers[iIdxSpatial].sSliceArgument), // confirmed_safe_unsafe_usage
                sizeof (SSliceArgument)) ;
  
        pSpatialLayer->iDLayerQp = pCodingParam.sSpatialLayers[iIdxSpatial].iDLayerQp;
  
        // See codec_app_def.h and parameter_sets.h for more info about members bVideoSignalTypePresent through uiColorMatrix.
        pSpatialLayer->bVideoSignalTypePresent =   pCodingParam.sSpatialLayers[iIdxSpatial].bVideoSignalTypePresent;
        pSpatialLayer->uiVideoFormat =             pCodingParam.sSpatialLayers[iIdxSpatial].uiVideoFormat;
        pSpatialLayer->bFullRange =                pCodingParam.sSpatialLayers[iIdxSpatial].bFullRange;
        pSpatialLayer->bColorDescriptionPresent =  pCodingParam.sSpatialLayers[iIdxSpatial].bColorDescriptionPresent;
        pSpatialLayer->uiColorPrimaries =          pCodingParam.sSpatialLayers[iIdxSpatial].uiColorPrimaries;
        pSpatialLayer->uiTransferCharacteristics = pCodingParam.sSpatialLayers[iIdxSpatial].uiTransferCharacteristics;
        pSpatialLayer->uiColorMatrix =             pCodingParam.sSpatialLayers[iIdxSpatial].uiColorMatrix;
  
        pSpatialLayer->bAspectRatioPresent = pCodingParam.sSpatialLayers[iIdxSpatial].bAspectRatioPresent;
        pSpatialLayer->eAspectRatio = pCodingParam.sSpatialLayers[iIdxSpatial].eAspectRatio;
        pSpatialLayer->sAspectRatioExtWidth = pCodingParam.sSpatialLayers[iIdxSpatial].sAspectRatioExtWidth;
        pSpatialLayer->sAspectRatioExtHeight = pCodingParam.sSpatialLayers[iIdxSpatial].sAspectRatioExtHeight;
  
        uiProfileIdc = (!bSimulcastAVC) ? PRO_SCALABLE_BASELINE : uiProfileIdc; //it is used in the D>0 layer if SVC is applied, so set to PRO_SCALABLE_BASELINE
        ++ pDlp;
        ++ pSpatialLayer;
        ++ iIdxSpatial;
      }
  
      SetActualPicResolution();
  
      return 0;
    }
  
  // assuming that the width/height ratio of all spatial layers are the same
  
    void SetActualPicResolution() {
      int32_t iSpatialIdx = iSpatialLayerNum - 1;
      for (; iSpatialIdx >= 0; iSpatialIdx --) {
        SSpatialLayerInternal* pDlayerInternal = &sDependencyLayers[iSpatialIdx];
        SSpatialLayerConfig* pDlayer =  &sSpatialLayers[iSpatialIdx];
  
        pDlayerInternal->iActualWidth = pDlayer->iVideoWidth;
        pDlayerInternal->iActualHeight = pDlayer->iVideoHeight;
        pDlayer->iVideoWidth = WELS_ALIGN (pDlayerInternal->iActualWidth, MB_WIDTH_LUMA);
        pDlayer->iVideoHeight = WELS_ALIGN (pDlayerInternal->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)
    */
    int32_t 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];
      SSpatialLayerInternal* pDlp    = &sDependencyLayers[0];
      SSpatialLayerConfig* pSpatialLayer = &sSpatialLayers[0];
      int8_t i = 0;
  
      while (i < iSpatialLayerNum) {
        const uint32_t kuiLogFactorInOutRate = GetLogFactor (pDlp->fOutputFrameRate, pDlp->fInputFrameRate);
        const uint32_t kuiLogFactorMaxInRate = GetLogFactor (pDlp->fInputFrameRate, fMaxFrameRate);
        if (UINT_MAX == kuiLogFactorInOutRate || UINT_MAX == kuiLogFactorMaxInRate) {
          return ENC_RETURN_INVALIDINPUT;
        }
        int32_t iNotCodedMask = 0;
        int8_t iMaxTemporalId = 0;
  
        memset (pDlp->uiCodingIdx2TemporalId, INVALID_TEMPORAL_ID, sizeof (pDlp->uiCodingIdx2TemporalId));
        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;
        if (pDlp->iDecompositionStages < 0) {
          return ENC_RETURN_INVALIDINPUT;
        }
        ++ pDlp;
        ++ pSpatialLayer;
        ++ i;
      }
      iDecompStages = (int8_t)iDecStages;
      return ENC_RETURN_SUCCESS;
    }
  
  } SWelsSvcCodingParam;
  
  
  typedef struct TagExistingParasetList {
    SWelsSPS            sSps[MAX_SPS_COUNT];
    SSubsetSps          sSubsetSps[MAX_SPS_COUNT];
    SWelsPPS            sPps[MAX_PPS_COUNT];
  
    uint32_t            uiInUseSpsNum;
    uint32_t            uiInUseSubsetSpsNum;
    uint32_t            uiInUsePpsNum;
  } SExistingParasetList;
  
  
  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->WelsMallocz (sizeof (SWelsSvcCodingParam),
                                        "SWelsSvcCodingParam");
    if (NULL == pCodingParam)
      return 1;
    *pParam = pCodingParam;
    return 0;
  }
  
  }//end of namespace WelsEnc
  
  #endif//WELS_ENCODER_PARAMETER_SVC_H__
  