shithub: openh264

Download patch

ref: 1ac02f3002332d365069c3e6aaae02789f1ca73d
parent: 00747540fbb1c2ec0488886579aa556a71f62aa6
parent: 7188e50acf45189f242b83aa7d5595a3e0145c53
author: sijchen <sijchen@cisco.com>
date: Wed May 18 06:57:39 EDT 2016

fix conflict with master

--- a/codec/build/iOS/enc/welsenc/welsenc.xcodeproj/project.pbxproj
+++ b/codec/build/iOS/enc/welsenc/welsenc.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		0D6970BE1CA5BCFB001D88F8 /* paraset_strategy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0D6970BC1CA5BCFB001D88F8 /* paraset_strategy.cpp */; };
 		0DD32A961B4A478B009181A1 /* wels_task_base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A951B4A478B009181A1 /* wels_task_base.cpp */; };
 		0DD32A991B4A4997009181A1 /* wels_task_management.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A981B4A4997009181A1 /* wels_task_management.cpp */; };
 		0DD32A9C1B4A4E8F009181A1 /* wels_task_encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A9B1B4A4E8F009181A1 /* wels_task_encoder.cpp */; };
@@ -69,6 +70,8 @@
 
 /* Begin PBXFileReference section */
 		04FE0684196FD9370004D7CE /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = ../../../common/inc/version.h; sourceTree = "<group>"; };
+		0D6970BC1CA5BCFB001D88F8 /* paraset_strategy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = paraset_strategy.cpp; sourceTree = "<group>"; };
+		0D6970BF1CA5BD26001D88F8 /* paraset_strategy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = paraset_strategy.h; sourceTree = "<group>"; };
 		0DD32A951B4A478B009181A1 /* wels_task_base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wels_task_base.cpp; sourceTree = "<group>"; };
 		0DD32A971B4A47D0009181A1 /* wels_task_base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wels_task_base.h; sourceTree = "<group>"; };
 		0DD32A981B4A4997009181A1 /* wels_task_management.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wels_task_management.cpp; sourceTree = "<group>"; };
@@ -281,6 +284,7 @@
 				4CE446BD18BC605C0017DF25 /* nal_encap.h */,
 				4CE446BF18BC605C0017DF25 /* param_svc.h */,
 				4CE446C018BC605C0017DF25 /* parameter_sets.h */,
+				0D6970BF1CA5BD26001D88F8 /* paraset_strategy.h */,
 				4CE446C118BC605C0017DF25 /* picture.h */,
 				4CE446C218BC605C0017DF25 /* picture_handle.h */,
 				4CE446C418BC605C0017DF25 /* rc.h */,
@@ -329,6 +333,7 @@
 				4CE446E718BC605C0017DF25 /* md.cpp */,
 				4CE446E918BC605C0017DF25 /* mv_pred.cpp */,
 				4CE446EA18BC605C0017DF25 /* nal_encap.cpp */,
+				0D6970BC1CA5BCFB001D88F8 /* paraset_strategy.cpp */,
 				4CE446EB18BC605C0017DF25 /* picture_handle.cpp */,
 				4CE446ED18BC605C0017DF25 /* ratectl.cpp */,
 				4CE446EE18BC605C0017DF25 /* ref_list_mgr_svc.cpp */,
@@ -475,6 +480,7 @@
 				4C34067218C57D0400DFA14A /* reconstruct_neon.S in Sources */,
 				0DD32A961B4A478B009181A1 /* wels_task_base.cpp in Sources */,
 				F7E9994919EBD1F8009B1021 /* set_mb_syn_cabac.cpp in Sources */,
+				0D6970BE1CA5BCFB001D88F8 /* paraset_strategy.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
--- a/codec/build/win32/enc/WelsEncCore.vcproj
+++ b/codec/build/win32/enc/WelsEncCore.vcproj
@@ -406,6 +406,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\encoder\core\src\paraset_strategy.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\encoder\core\src\picture_handle.cpp"
 				>
 			</File>
@@ -616,6 +620,10 @@
 			</File>
 			<File
 				RelativePath="..\..\..\encoder\core\inc\parameter_sets.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\encoder\core\inc\paraset_strategy.h"
 				>
 			</File>
 			<File
--- a/codec/decoder/core/src/parse_mb_syn_cabac.cpp
+++ b/codec/decoder/core/src/parse_mb_syn_cabac.cpp
@@ -934,7 +934,8 @@
   } else if (iResProperty == CHROMA_DC_U || iResProperty == CHROMA_DC_V) {
     do {
       if (pSignificantMap[j] != 0)
-        sTCoeff[pScanTable[j]] = pCtx->bUseScalingList ? (pSignificantMap[j] * pDeQuantMul[0]) >> 4 :
+        sTCoeff[pScanTable[j]] = pCtx->bUseScalingList ? (int16_t) ((int64_t)pSignificantMap[j] *
+                                 (int64_t)pDeQuantMul[0] >> 4) :
                                  (pSignificantMap[j] * pDeQuantMul[0]);
       ++j;
     } while (j < 16);
@@ -941,7 +942,8 @@
   } else { //luma ac, chroma ac
     do {
       if (pSignificantMap[j] != 0)
-        sTCoeff[pScanTable[j]] = pCtx->bUseScalingList ? (pSignificantMap[j] * pDeQuantMul[pScanTable[j]] >> 4) :
+        sTCoeff[pScanTable[j]] = pCtx->bUseScalingList ? (int16_t) ((int64_t)pSignificantMap[j] *
+                                 (int64_t)pDeQuantMul[pScanTable[j]] >> 4) :
                                  pSignificantMap[j] * pDeQuantMul[pScanTable[j] & 0x07];
       ++j;
     } while (j < 16);
--- a/codec/encoder/core/inc/au_set.h
+++ b/codec/encoder/core/inc/au_set.h
@@ -43,6 +43,7 @@
 #define WELS_ACCESS_UNIT_WRITER_H__
 
 #include "parameter_sets.h"
+#include "paraset_strategy.h"
 #include "param_svc.h"
 #include "utils.h"
 namespace WelsEnc {
@@ -92,7 +93,7 @@
  * \note    Call it in case EWelsNalUnitType is PPS.
  *************************************************************************************
  */
-int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, SParaSetOffset* sPSOVector);
+int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, IWelsParametersetStrategy* pParametersetStrategy);
 
 /*!
  * \brief   initialize pSps based on configurable parameters in svc
@@ -147,21 +148,5 @@
 
 int32_t WelsAdjustLevel (SSpatialLayerConfig* pSpatialLayer);
 
-/*!
- * \brief   check if the current parameter can found a presenting sps
- * \param   pParam          the current encoding paramter in SWelsSvcCodingParam
- * \param   kbUseSubsetSps  bool
- * \param   iDlayerIndex    int, the index of current D layer
- * \param   iDlayerCount    int, the number of total D layer
- * \param pSpsArray         array of all the stored SPSs
- * \param   pSubsetArray    array of all the stored Subset-SPSs
- * \return  0 - successful
- *         -1 - cannot find existing SPS for current encoder parameter
- */
-int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
-                         const int32_t iDlayerCount,  const int32_t iSpsNumInUse,
-                         SWelsSPS* pSpsArray,
-                         SSubsetSps* pSubsetArray,
-                         bool bSVCBaselayer);
 }
 #endif//WELS_ACCESS_UNIT_PARSER_H__
--- a/codec/encoder/core/inc/encoder_context.h
+++ b/codec/encoder/core/inc/encoder_context.h
@@ -45,6 +45,7 @@
 #include "param_svc.h"
 #include "nal_encap.h"
 #include "picture.h"
+#include "paraset_strategy.h"
 #include "dq_map.h"
 #include "stat.h"
 #include "macros.h"
@@ -63,6 +64,7 @@
 
 class IWelsTaskManage;
 class IWelsReferenceStrategy;
+
 /*
  *  reference list for each quality layer in SVC
  */
@@ -238,30 +240,7 @@
   bool bRecFlag;
 #endif
   int64_t            uiLastTimestamp;
-  uint32_t GetNeededSpsNum() {
-    if (0 == sPSOVector.uiNeededSpsNum) {
-      sPSOVector.uiNeededSpsNum = ((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (1));
-      sPSOVector.uiNeededSpsNum *= ((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1));
-    }
-    return sPSOVector.uiNeededSpsNum;
-  }
 
-  uint32_t GetNeededSubsetSpsNum() {
-    if (0 == sPSOVector.uiNeededSubsetSpsNum) {
-      sPSOVector.uiNeededSubsetSpsNum = ((pSvcParam->bSimulcastAVC) ? (0) :
-                                         ((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (pSvcParam->iSpatialLayerNum - 1)));
-    }
-    return sPSOVector.uiNeededSubsetSpsNum;
-  }
-
-  uint32_t GetNeededPpsNum() {
-    if (0 == sPSOVector.uiNeededPpsNum) {
-      sPSOVector.uiNeededPpsNum = ((pSvcParam->eSpsPpsIdStrategy & SPS_PPS_LISTING) ? (MAX_PPS_COUNT) :
-                                   (1 + pSvcParam->iSpatialLayerNum));
-      sPSOVector.uiNeededPpsNum *= ((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1));
-    }
-    return sPSOVector.uiNeededPpsNum;
-  }
 } sWelsEncCtx/*, *PWelsEncCtx*/;
 }
 #endif//sWelsEncCtx_H__
--- /dev/null
+++ b/codec/encoder/core/inc/paraset_strategy.h
@@ -1,0 +1,310 @@
+/*!
+ * \copy
+ *     Copyright (c)  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.
+ *
+ */
+
+#ifndef WELS_PARASET_STRATEGY_H
+#define WELS_PARASET_STRATEGY_H
+
+#include "param_svc.h"
+#include "utils.h"
+
+namespace WelsEnc {
+
+class IWelsParametersetStrategy {
+ public:
+  virtual ~IWelsParametersetStrategy() { }
+
+  static IWelsParametersetStrategy* CreateParametersetStrategy (EParameterSetStrategy eSpsPpsIdStrategy,
+      const bool bSimulcastAVC, const int32_t kiSpatialLayerNum);
+
+  //virtual SParaSetOffset* GetParaSetOffset() = 0;
+
+  virtual int32_t GetPpsIdOffset (const int32_t iPpsId) = 0;
+  virtual int32_t GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId) = 0;
+  virtual int32_t* GetSpsIdOffsetList (const int iParasetType) = 0;
+
+  virtual uint32_t GetAllNeededParasetNum() = 0;
+
+  virtual uint32_t GetNeededSpsNum() = 0;
+  virtual uint32_t GetNeededSubsetSpsNum() = 0;
+  virtual uint32_t GetNeededPpsNum() = 0;
+
+  virtual void LoadPrevious (SExistingParasetList* pExistingParasetList,  SWelsSPS* pSpsArray,
+                             SSubsetSps*       pSubsetArray,
+                             SWelsPPS* pPpsArray) = 0;
+
+  virtual void Update (const uint32_t kuiId, const int iParasetType) = 0;
+  virtual void UpdatePpsList (sWelsEncCtx* pCtx) = 0;
+
+  virtual bool CheckParamCompatibility (SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) = 0;
+
+  virtual uint32_t GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
+                                   const int32_t iDlayerCount,
+                                   uint32_t kuiSpsId,
+                                   SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) = 0;
+
+  virtual uint32_t InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
+                            SWelsSPS* pSps,
+                            SSubsetSps* pSubsetSps,
+                            uint32_t kuiPpsId,
+                            const bool kbDeblockingFilterPresentFlag,
+                            const bool kbUsingSubsetSps,
+                            const bool kbEntropyCodingModeFlag) = 0;
+
+  virtual  void SetUseSubsetFlag (const uint32_t iPpsId, const bool bUseSubsetSps) = 0;
+
+  virtual  void UpdateParaSetNum (sWelsEncCtx* pCtx) = 0;
+
+  virtual  int32_t GetCurrentPpsId (const int32_t iPpsId, const int32_t iIdrLoop) = 0;
+
+  virtual  void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
+                                        sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) = 0;
+  virtual  void LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList) = 0;
+
+  virtual int32_t GetSpsIdx (const int32_t iIdx) = 0;
+};
+
+
+class  CWelsParametersetIdConstant : public IWelsParametersetStrategy {
+ public:
+
+  CWelsParametersetIdConstant (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum);
+  virtual ~ CWelsParametersetIdConstant();
+
+  virtual int32_t GetPpsIdOffset (const int32_t iPpsId);
+  virtual int32_t GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId);
+  int32_t* GetSpsIdOffsetList (const int iParasetType);
+
+  uint32_t GetAllNeededParasetNum();
+
+  virtual uint32_t GetNeededSpsNum();
+  virtual uint32_t GetNeededSubsetSpsNum();
+  virtual uint32_t GetNeededPpsNum();
+
+  virtual void LoadPrevious (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
+                             SSubsetSps*       pSubsetArray,
+                             SWelsPPS* pPpsArray);
+
+  virtual void Update (const uint32_t kuiId, const int iParasetType);
+  virtual void UpdatePpsList (sWelsEncCtx* pCtx) {};
+
+  bool CheckParamCompatibility (SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) {
+    return true;
+  };
+
+  virtual uint32_t GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
+                                   const int32_t iDlayerCount, uint32_t kuiSpsId,
+                                   SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer);
+
+  virtual uint32_t InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
+                            SWelsSPS* pSps,
+                            SSubsetSps* pSubsetSps,
+                            uint32_t kuiPpsId,
+                            const bool kbDeblockingFilterPresentFlag,
+                            const bool kbUsingSubsetSps,
+                            const bool kbEntropyCodingModeFlag);
+
+  virtual void SetUseSubsetFlag (const uint32_t iPpsId, const bool bUseSubsetSps);
+
+  virtual void UpdateParaSetNum (sWelsEncCtx* pCtx) {};
+
+  virtual int32_t GetCurrentPpsId (const int32_t iPpsId, const int32_t iIdrLoop) {
+    return iPpsId;
+  };
+
+  virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
+                                       sWelsEncCtx* pCtx,
+                                       SExistingParasetList* pExistingParasetList) {};
+  virtual void LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList) {};
+
+  virtual int32_t GetSpsIdx (const int32_t iIdx) {
+    return 0;
+  };
+ protected:
+
+  virtual void LoadPreviousSps (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
+                                SSubsetSps*       pSubsetArray) {};
+  virtual void LoadPreviousPps (SExistingParasetList* pExistingParasetList, SWelsPPS* pPpsArray) {};
+
+ protected:
+  SParaSetOffset m_sParaSetOffset;
+  bool m_bSimulcastAVC;
+  int32_t m_iSpatialLayerNum;
+
+  uint32_t m_iBasicNeededSpsNum;
+  uint32_t m_iBasicNeededPpsNum;
+};
+
+/*
+  typedef struct TagParaSetOffsetVariable {
+    int32_t       iParaSetIdDelta[MAX_DQ_LAYER_NUM+1];//mark delta between SPS_ID_in_bs and sps_id_in_encoder, can be minus, for each dq-layer
+    //need not extra +1 due no MGS and FMO case so far
+    bool          bUsedParaSetIdInBs[MAX_PPS_COUNT];      //mark the used SPS_ID with 1
+    uint32_t      uiNextParaSetIdToUseInBs;               //mark the next SPS_ID_in_bs, for all layers
+  } SParaSetOffsetVariable;
+
+  typedef struct TagParaSetOffset {
+    //in PS0 design, "sParaSetOffsetVariable" record the previous paras before current IDR, AND NEED to be stacked and recover across IDR
+    SParaSetOffsetVariable
+    sParaSetOffsetVariable[PARA_SET_TYPE]; //PARA_SET_TYPE=3; paraset_type = 0: AVC_SPS; =1: Subset_SPS; =2: PPS
+    //in PSO design, "bPpsIdMappingIntoSubsetsps" uses the current para of current IDR period
+    bool
+    bPpsIdMappingIntoSubsetsps[MAX_DQ_LAYER_NUM+1];   // need not extra +1 due no MGS and FMO case so far
+
+    int32_t  iPpsIdList[MAX_DQ_LAYER_NUM][MAX_PPS_COUNT]; //index0: max pps types; index1: for differnt IDRs, if only index0=1, index1 can reach MAX_PPS_COUNT
+
+    //#if _DEBUG
+    int32_t  eSpsPpsIdStrategy;
+    //#endif
+
+    uint32_t uiNeededSpsNum;
+    uint32_t uiNeededSubsetSpsNum;
+    uint32_t uiNeededPpsNum;
+
+    uint32_t uiInUseSpsNum;
+    uint32_t uiInUseSubsetSpsNum;
+    uint32_t uiInUsePpsNum;
+  } SParaSetOffset;
+  */
+
+class  CWelsParametersetIdNonConstant : public CWelsParametersetIdConstant {
+ public:
+  CWelsParametersetIdNonConstant (const bool bSimulcastAVC,
+                                  const int32_t kiSpatialLayerNum): CWelsParametersetIdConstant (bSimulcastAVC, kiSpatialLayerNum) {};
+
+  virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
+                                       sWelsEncCtx* pCtx,
+                                       SExistingParasetList* pExistingParasetList);
+  virtual void LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList);
+};
+
+class  CWelsParametersetIdIncreasing : public CWelsParametersetIdNonConstant {
+ public:
+  CWelsParametersetIdIncreasing (const bool bSimulcastAVC,
+                                 const int32_t kiSpatialLayerNum): CWelsParametersetIdNonConstant (bSimulcastAVC, kiSpatialLayerNum) {};
+
+
+  virtual int32_t GetPpsIdOffset (const int32_t iPpsId);
+  virtual int32_t GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId);
+
+  virtual void Update (const uint32_t kuiId, const int iParasetType);
+
+ protected:
+
+  //void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable, const int32_t kiCurEncoderParaSetId,
+  //                              const uint32_t kuiMaxIdInBs);
+
+ private:
+  void DebugPps (const int32_t kiPpsId);
+  void DebugSpsPps (const int32_t iPpsId, const int32_t iSpsId);
+};
+
+
+class  CWelsParametersetSpsListing : public CWelsParametersetIdNonConstant {
+ public:
+  CWelsParametersetSpsListing (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum);
+
+  virtual uint32_t GetNeededSubsetSpsNum();
+
+  virtual void LoadPrevious (SExistingParasetList* pExistingParasetList,  SWelsSPS* pSpsArray,
+                             SSubsetSps*       pSubsetArray,
+                             SWelsPPS* pPpsArray);
+
+  bool CheckParamCompatibility (SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx);
+
+  virtual uint32_t GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
+                                   const int32_t iDlayerCount, uint32_t kuiSpsId,
+                                   SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer);
+
+  virtual void UpdateParaSetNum (sWelsEncCtx* pCtx);
+
+  int32_t GetSpsIdx (const int32_t iIdx) {
+    return iIdx;
+  };
+
+  virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
+                                       sWelsEncCtx* pCtx,
+                                       SExistingParasetList* pExistingParasetList);
+ protected:
+  virtual void LoadPreviousSps (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
+                                SSubsetSps*       pSubsetArray);
+  virtual bool CheckPpsGenerating();
+  virtual int32_t SpsReset (sWelsEncCtx* pCtx, bool kbUseSubsetSps);
+};
+
+class  CWelsParametersetSpsPpsListing : public CWelsParametersetSpsListing {
+ public:
+  CWelsParametersetSpsPpsListing (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum);
+
+  //uint32_t GetNeededPpsNum();
+
+  virtual void UpdatePpsList (sWelsEncCtx* pCtx);
+
+  virtual uint32_t InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
+                            SWelsSPS* pSps,
+                            SSubsetSps* pSubsetSps,
+                            uint32_t kuiPpsId,
+                            const bool kbDeblockingFilterPresentFlag,
+                            const bool kbUsingSubsetSps,
+                            const bool kbEntropyCodingModeFlag);
+
+  virtual void UpdateParaSetNum (sWelsEncCtx* pCtx);
+
+  virtual int32_t GetCurrentPpsId (const int32_t iPpsId, const int32_t iIdrLoop);
+
+  virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
+                                       sWelsEncCtx* pCtx,
+                                       SExistingParasetList* pExistingParasetList);
+  virtual void LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList);
+ protected:
+  virtual void LoadPreviousPps (SExistingParasetList* pExistingParasetList, SWelsPPS* pPpsArray);
+
+  virtual bool CheckPpsGenerating();
+  virtual int32_t SpsReset (sWelsEncCtx* pCtx, bool kbUseSubsetSps);
+};
+
+class CWelsParametersetSpsListingPpsIncreasing : public CWelsParametersetSpsListing {
+ public:
+  CWelsParametersetSpsListingPpsIncreasing (const bool bSimulcastAVC,
+      const int32_t kiSpatialLayerNum): CWelsParametersetSpsListing (bSimulcastAVC, kiSpatialLayerNum) {};
+
+  virtual int32_t GetPpsIdOffset (const int32_t kiPpsId);
+  virtual void Update (const uint32_t kuiId, const int iParasetType);
+};
+
+int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
+                         const int32_t iDlayerCount, const int32_t iSpsNumInUse,
+                         SWelsSPS* pSpsArray,
+                         SSubsetSps* pSubsetArray, bool bSVCBaseLayer);
+
+}
+
+#endif
--- a/codec/encoder/core/inc/wels_func_ptr_def.h
+++ b/codec/encoder/core/inc/wels_func_ptr_def.h
@@ -193,6 +193,8 @@
 typedef void (*PStashMBStatus) (SDynamicSlicingStack* pDss, SSlice* pSlice, int32_t iMbSkipRun);
 typedef int32_t (*PStashPopMBStatus) (SDynamicSlicingStack* pDss, SSlice* pSlice);
 
+class IWelsParametersetStrategy;
+
 struct TagWelsFuncPointerList {
   SExpandPicFunc sExpandPicFunc;
   PFillInterNeighborCacheFunc       pfFillInterNeighborCache;
@@ -288,6 +290,8 @@
   PWelsSpatialWriteMbSyn pfWelsSpatialWriteMbSyn;
   PStashMBStatus pfStashMBStatus;
   PStashPopMBStatus pfStashPopMBStatus;
+
+  IWelsParametersetStrategy* pParametersetStrategy;
 };
 
 }  //end of namespace WelsEnc {
--- a/codec/encoder/core/src/au_set.cpp
+++ b/codec/encoder/core/src/au_set.cpp
@@ -380,29 +380,12 @@
  * \note    Call it in case EWelsNalUnitType is PPS.
  *************************************************************************************
  */
-int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, SParaSetOffset* pPSOVector) {
+int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux,
+                            IWelsParametersetStrategy* pParametersetStrategy) {
   SBitStringAux* pLocalBitStringAux = pBitStringAux;
 
-  const int32_t kiParameterSetType = (pPSOVector != NULL) ? (pPSOVector->bPpsIdMappingIntoSubsetsps[pPps->iPpsId] ?
-                                     PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS) : 0;
-
-  BsWriteUE (pLocalBitStringAux, pPps->iPpsId
-             + ((pPSOVector != NULL) ? (pPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId]) : 0));
-  BsWriteUE (pLocalBitStringAux, pPps->iSpsId
-             + ((pPSOVector != NULL) ? (pPSOVector->sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[pPps->iSpsId]) : 0));
-
-#if _DEBUG
-  //SParaSetOffset use, 110421
-  if ((pPSOVector != NULL) && (INCREASING_ID & pPSOVector->eSpsPpsIdStrategy)) {
-    const int32_t kiTmpSpsIdInBs = pPps->iSpsId +
-                                   pPSOVector->sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[pPps->iSpsId];
-    const int32_t tmp_pps_id_in_bs = pPps->iPpsId +
-                                     pPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId];
-    assert (MAX_SPS_COUNT > kiTmpSpsIdInBs);
-    assert (MAX_PPS_COUNT > tmp_pps_id_in_bs);
-    assert (pPSOVector->sParaSetOffsetVariable[kiParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
-  }
-#endif
+  BsWriteUE (pLocalBitStringAux, pPps->iPpsId + pParametersetStrategy->GetPpsIdOffset (pPps->iPpsId));
+  BsWriteUE (pLocalBitStringAux, pPps->iSpsId + pParametersetStrategy->GetSpsIdOffset (pPps->iPpsId, pPps->iSpsId));
 
   BsWriteOneBit (pLocalBitStringAux, pPps->bEntropyCodingModeFlag);
   BsWriteOneBit (pLocalBitStringAux, false/*pPps->bPicOrderPresentFlag*/);
--- a/codec/encoder/core/src/encoder.cpp
+++ b/codec/encoder/core/src/encoder.cpp
@@ -46,6 +46,7 @@
 #include "deblocking.h"
 #include "ref_list_mgr_svc.h"
 #include "mc.h"
+#include "paraset_strategy.h"
 #include "sample.h"
 
 #include "svc_enc_golomb.h"
@@ -220,6 +221,10 @@
   WelsBlockFuncInit (&pFuncList->pfSetNZCZero, uiCpuFlag);
 
   InitFillNeighborCacheInterFunc (pFuncList, pParam->bEnableBackgroundDetection);
+
+  pFuncList->pParametersetStrategy = IWelsParametersetStrategy::CreateParametersetStrategy (pParam->eSpsPpsIdStrategy,
+                                     pParam->bSimulcastAVC, pParam->iSpatialLayerNum);
+  WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pFuncList->pParametersetStrategy))
 
   return iReturn;
 }
--- a/codec/encoder/core/src/encoder_ext.cpp
+++ b/codec/encoder/core/src/encoder_ext.cpp
@@ -767,12 +767,15 @@
     ++ iDIndex;
   } while (iDIndex < iNumDependencyLayers);
 
+  if (NULL == (*ppCtx)->pFuncList || NULL == (*ppCtx)->pFuncList->pParametersetStrategy) {
+    WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
+             "AcquireLayersNals(), pFuncList and pParametersetStrategy needed to be initialized first!");
+    return 1;
+  }
   // count parasets
   iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) +
                    iCountNumLayers // plus iCountNumLayers for reserved application
-                   + (*ppCtx)->GetNeededSpsNum()
-                   + (*ppCtx)->GetNeededSubsetSpsNum()
-                   + (*ppCtx)->GetNeededPpsNum();
+                   + (*ppCtx)->pFuncList->pParametersetStrategy->GetAllNeededParasetNum();
 
   // to check number of layers / nals / slices dependencies, 12/8/2010
   if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) {
@@ -956,153 +959,8 @@
   pRefList = NULL;
 }
 
-static int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
-                                   const int32_t iDlayerCount, const int32_t kiSpsId,
-                                   SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) {
-  int32_t iRet = 0;
 
-  if (!kbUseSubsetSps) {
-    pSps        = & (pCtx->pSpsArray[kiSpsId]);
-  } else {
-    pSubsetSps  = & (pCtx->pSubsetArray[kiSpsId]);
-    pSps        = &pSubsetSps->pSps;
-  }
 
-  SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
-  SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
-  // Need port pSps/pPps initialization due to spatial scalability changed
-  if (!kbUseSubsetSps) {
-    iRet = WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
-                        pParam->iMaxNumRefFrame,
-                        kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
-                        bSVCBaselayer);
-  } else {
-    iRet = WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
-                              pParam->iMaxNumRefFrame,
-                              kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
-  }
-  return iRet;
-}
-
-static bool CheckMatchedSps (SWelsSPS* const pSps1, SWelsSPS* const pSps2) {
-
-  if ((pSps1->iMbWidth != pSps2->iMbWidth)
-      || (pSps1->iMbHeight != pSps2->iMbHeight)) {
-    return false;
-  }
-
-  if ((pSps1->uiLog2MaxFrameNum != pSps2->uiLog2MaxFrameNum)
-      || (pSps1->iLog2MaxPocLsb != pSps2->iLog2MaxPocLsb)) {
-    return false;
-  }
-
-  if (pSps1->iNumRefFrames != pSps2->iNumRefFrames) {
-    return false;
-  }
-
-  if ((pSps1->bFrameCroppingFlag != pSps2->bFrameCroppingFlag)
-      || (pSps1->sFrameCrop.iCropLeft != pSps2->sFrameCrop.iCropLeft)
-      || (pSps1->sFrameCrop.iCropRight != pSps2->sFrameCrop.iCropRight)
-      || (pSps1->sFrameCrop.iCropTop != pSps2->sFrameCrop.iCropTop)
-      || (pSps1->sFrameCrop.iCropBottom != pSps2->sFrameCrop.iCropBottom)
-     ) {
-    return false;
-  }
-
-  if ((pSps1->uiProfileIdc != pSps2->uiProfileIdc)
-      || (pSps1->bConstraintSet0Flag != pSps2->bConstraintSet0Flag)
-      || (pSps1->bConstraintSet1Flag != pSps2->bConstraintSet1Flag)
-      || (pSps1->bConstraintSet2Flag != pSps2->bConstraintSet2Flag)
-      || (pSps1->bConstraintSet3Flag != pSps2->bConstraintSet3Flag)
-      || (pSps1->iLevelIdc != pSps2->iLevelIdc)) {
-    return false;
-  }
-
-  return true;
-}
-
-static bool CheckMatchedSubsetSps (SSubsetSps* const pSubsetSps1, SSubsetSps* const pSubsetSps2) {
-  if (!CheckMatchedSps (&pSubsetSps1->pSps, &pSubsetSps2->pSps)) {
-    return false;
-  }
-
-  if ((pSubsetSps1->sSpsSvcExt.iExtendedSpatialScalability      != pSubsetSps2->sSpsSvcExt.iExtendedSpatialScalability)
-      || (pSubsetSps1->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag  != pSubsetSps2->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag)
-      || (pSubsetSps1->sSpsSvcExt.bSeqTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bSeqTcoeffLevelPredFlag)
-      || (pSubsetSps1->sSpsSvcExt.bSliceHeaderRestrictionFlag != pSubsetSps2->sSpsSvcExt.bSliceHeaderRestrictionFlag)) {
-    return false;
-  }
-
-  return true;
-}
-
-int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
-                         const int32_t iDlayerCount, const int32_t iSpsNumInUse,
-                         SWelsSPS* pSpsArray,
-                         SSubsetSps* pSubsetArray, bool bSVCBaseLayer) {
-  SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
-
-  assert (iSpsNumInUse <= MAX_SPS_COUNT);
-  if (!kbUseSubsetSps) {
-    SWelsSPS sTmpSps;
-    WelsInitSps (&sTmpSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
-                 pParam->iMaxNumRefFrame,
-                 0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
-                 bSVCBaseLayer);
-    for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
-      if (CheckMatchedSps (&sTmpSps, &pSpsArray[iId])) {
-        return iId;
-      }
-    }
-  } else {
-    SSubsetSps sTmpSubsetSps;
-    WelsInitSubsetSps (&sTmpSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
-                       pParam->iMaxNumRefFrame,
-                       0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
-
-    for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
-      if (CheckMatchedSubsetSps (&sTmpSubsetSps, &pSubsetArray[iId])) {
-        return iId;
-      }
-    }
-  }
-
-  return INVALID_ID;
-}
-
-int32_t FindExistingPps (SWelsSPS* pSps, SSubsetSps* pSubsetSps, const bool kbUseSubsetSps, const int32_t iSpsId,
-                         const bool kbEntropyCodingFlag, const int32_t iPpsNumInUse,
-                         SWelsPPS* pPpsArray) {
-#if !defined(DISABLE_FMO_FEATURE)
-  // feature not supported yet
-  return INVALID_ID;
-#endif//!DISABLE_FMO_FEATURE
-
-  SWelsPPS sTmpPps;
-  WelsInitPps (&sTmpPps,
-               pSps,
-               pSubsetSps,
-               0,
-               true,
-               kbUseSubsetSps,
-               kbEntropyCodingFlag);
-
-  assert (iPpsNumInUse <= MAX_PPS_COUNT);
-  for (int32_t iId = 0; iId < iPpsNumInUse; iId++) {
-    if ((sTmpPps.iSpsId == pPpsArray[iId].iSpsId)
-        && (sTmpPps.bEntropyCodingModeFlag == pPpsArray[iId].bEntropyCodingModeFlag)
-        && (sTmpPps.iPicInitQp == pPpsArray[iId].iPicInitQp)
-        && (sTmpPps.iPicInitQs == pPpsArray[iId].iPicInitQs)
-        && (sTmpPps.uiChromaQpIndexOffset == pPpsArray[iId].uiChromaQpIndexOffset)
-        && (sTmpPps.bDeblockingFilterControlPresentFlag == pPpsArray[iId].bDeblockingFilterControlPresentFlag)
-       ) {
-      return iId;
-    }
-  }
-
-  return INVALID_ID;
-}
-
 static inline int32_t InitSliceList (sWelsEncCtx** ppCtx,
                                      SDqLayer* pDqLayer,
                                      SSlice* pSliceList,
@@ -1248,7 +1106,7 @@
   CMemoryAlign* pMa             = NULL;
   int32_t iDlayerCount          = 0;
   int32_t iDlayerIndex          = 0;
-  uint32_t iSpsId               = 0;
+  int32_t iSpsId               = 0;
   uint32_t iPpsId               = 0;
   uint32_t iNumRef              = 0;
   int32_t iResult               = 0;
@@ -1388,8 +1246,10 @@
   }
 
   // for dynamically malloc for parameter sets memory instead of maximal items for standard to reduce size, 3/18/2010
-  const int32_t kiNeededSpsNum = (*ppCtx)->GetNeededSpsNum();
-  const int32_t kiNeededSubsetSpsNum = (*ppCtx)->GetNeededSubsetSpsNum();
+  WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pFuncList), FreeMemorySvc (ppCtx))
+  WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pFuncList->pParametersetStrategy), FreeMemorySvc (ppCtx))
+  const int32_t kiNeededSpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSpsNum();
+  const int32_t kiNeededSubsetSpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSubsetSpsNum();
   (*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMallocz (kiNeededSpsNum * sizeof (SWelsSPS), "pSpsArray");
   WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
   if (kiNeededSubsetSpsNum > 0) {
@@ -1399,36 +1259,15 @@
     (*ppCtx)->pSubsetArray = NULL;
   }
 
-  if ((SPS_LISTING & pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
-    (*ppCtx)->sPSOVector.uiInUseSpsNum = pExistingParasetList->uiInUseSpsNum;
-    memcpy ((*ppCtx)->pSpsArray, pExistingParasetList->sSps, MAX_SPS_COUNT * sizeof (SWelsSPS));
-
-    if (kiNeededSubsetSpsNum > 0) {
-      (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = pExistingParasetList->uiInUseSubsetSpsNum;
-      memcpy ((*ppCtx)->pSubsetArray, pExistingParasetList->sSubsetSps, MAX_SPS_COUNT * sizeof (SSubsetSps));
-    } else {
-      (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = 0;
-    }
-  }
-
   // PPS
-  const int32_t kiNeededPpsNum = (*ppCtx)->GetNeededPpsNum();
+  const int32_t kiNeededPpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededPpsNum();
   (*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMallocz (kiNeededPpsNum * sizeof (SWelsPPS), "pPPSArray");
   WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
 
-  // copy from existing if the pointer exists
-  if ((SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
-    (*ppCtx)->sPSOVector.uiInUsePpsNum = pExistingParasetList->uiInUsePpsNum;
-    memcpy ((*ppCtx)->pPPSArray, pExistingParasetList->sPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
-  }
+  (*ppCtx)->pFuncList->pParametersetStrategy->LoadPrevious (pExistingParasetList, (*ppCtx)->pSpsArray,
+      (*ppCtx)->pSubsetArray, (*ppCtx)->pPPSArray);
 
 
-  if (INCREASING_ID & pParam->eSpsPpsIdStrategy) {
-    (*ppCtx)->pPSOVector = & ((*ppCtx)->sPSOVector);
-  } else {
-    (*ppCtx)->pPSOVector = NULL;
-  }
-
   (*ppCtx)->pDqIdcMap = (SDqIdc*)pMa->WelsMallocz (iDlayerCount * sizeof (SDqIdc), "pDqIdcMap");
   WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pDqIdcMap), FreeMemorySvc (ppCtx))
 
@@ -1441,80 +1280,19 @@
                          && (iDlayerIndex == BASE_DEPENDENCY_ID);
     pDqIdc->uiSpatialId = iDlayerIndex;
 
-    if (! (SPS_LISTING & pParam->eSpsPpsIdStrategy)) {
-      WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
-                          iDlayerCount, iSpsId, pSps, pSubsetSps, bSvcBaselayer);
+    iSpsId = (*ppCtx)->pFuncList->pParametersetStrategy->GenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
+             iDlayerCount, iSpsId, pSps, pSubsetSps, bSvcBaselayer);
+    WELS_VERIFY_RETURN_IF (ENC_RETURN_UNSUPPORTED_PARA, (0 > iSpsId))
+    if (!bUseSubsetSps) {
+      pSps = & ((*ppCtx)->pSpsArray[iSpsId]);
     } else {
-      //SPS_LISTING_AND_PPS_INCREASING == pParam->eSpsPpsIdStrategy
-      //check if the current param can fit in an existing SPS
-      const int32_t kiFoundSpsId = FindExistingSps ((*ppCtx)->pSvcParam, bUseSubsetSps, iDlayerIndex, iDlayerCount,
-                                   bUseSubsetSps ? ((*ppCtx)->sPSOVector.uiInUseSubsetSpsNum) : ((*ppCtx)->sPSOVector.uiInUseSpsNum),
-                                   (*ppCtx)->pSpsArray,
-                                   (*ppCtx)->pSubsetArray, bSvcBaselayer);
-
-
-      if (INVALID_ID != kiFoundSpsId) {
-        //if yes, set pSps or pSubsetSps to it
-        iSpsId = kiFoundSpsId;
-        if (!bUseSubsetSps) {
-          pSps = & ((*ppCtx)->pSpsArray[kiFoundSpsId]);
-        } else {
-          pSubsetSps = & ((*ppCtx)->pSubsetArray[kiFoundSpsId]);
-        }
-      } else {
-        //if no, generate a new SPS as usual
-        if ((SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) && (MAX_PPS_COUNT <= (*ppCtx)->sPSOVector.uiInUsePpsNum)) {
-          //check if we can generate new SPS or not
-          WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
-                   "InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
-          return ENC_RETURN_UNSUPPORTED_PARA;
-        }
-
-        iSpsId = (!bUseSubsetSps) ? ((*ppCtx)->sPSOVector.uiInUseSpsNum++) : ((*ppCtx)->sPSOVector.uiInUseSubsetSpsNum++);
-        if (iSpsId >= MAX_SPS_COUNT) {
-          if (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) {
-            WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
-                     "InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
-            return ENC_RETURN_UNSUPPORTED_PARA;
-          }
-          // reset current list
-          if (!bUseSubsetSps) {
-            (*ppCtx)->sPSOVector.uiInUseSpsNum = 1;
-            memset ((*ppCtx)->pSpsArray, 0, MAX_SPS_COUNT * sizeof (SWelsSPS));
-          } else {
-            (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = 1;
-            memset ((*ppCtx)->pSubsetArray, 0, MAX_SPS_COUNT * sizeof (SSubsetSps));
-          }
-          iSpsId = 0;
-        }
-
-        WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
-                            iDlayerCount, iSpsId, pSps, pSubsetSps, bSvcBaselayer);
-      }
+      pSubsetSps = & ((*ppCtx)->pSubsetArray[iSpsId]);
     }
 
-    if (! (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy)) {
-      pPps = & (*ppCtx)->pPPSArray[iPpsId];
-      // initialize pPps
-      WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
-    } else {
-      const int32_t kiFoundPpsId = FindExistingPps (pSps, pSubsetSps, bUseSubsetSps, iSpsId,
-                                   pParam->iEntropyCodingModeFlag != 0,
-                                   (*ppCtx)->sPSOVector.uiInUsePpsNum,
-                                   (*ppCtx)->pPPSArray);
+    iPpsId = (*ppCtx)->pFuncList->pParametersetStrategy->InitPps ((*ppCtx), iSpsId, pSps, pSubsetSps, iPpsId, true,
+             bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
+    pPps = & ((*ppCtx)->pPPSArray[iPpsId]);
 
-
-      if (INVALID_ID != kiFoundPpsId) {
-        //if yes, set pPps to it
-        iPpsId = kiFoundPpsId;
-        pPps = & ((*ppCtx)->pPPSArray[kiFoundPpsId]);
-      } else {
-        iPpsId = ((*ppCtx)->sPSOVector.uiInUsePpsNum++);
-        pPps    = & (*ppCtx)->pPPSArray[iPpsId];
-        WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
-      }
-    }
-
     // Not using FMO in SVC coding so far, come back if need FMO
     {
       iResult = InitSlicePEncCtx ((*ppCtx)->ppDqLayerList[iDlayerIndex],
@@ -1533,8 +1311,6 @@
     pDqIdc->iSpsId = iSpsId;
     pDqIdc->iPpsId = iPpsId;
 
-    (*ppCtx)->sPSOVector.bPpsIdMappingIntoSubsetsps[iPpsId] = bUseSubsetSps;
-
     if ((pParam->bSimulcastAVC) || (bUseSubsetSps))
       ++ iSpsId;
     ++ iPpsId;
@@ -1547,13 +1323,8 @@
 
     ++ iDlayerIndex;
   }
-  if (SPS_LISTING & pParam->eSpsPpsIdStrategy) {
-    (*ppCtx)->iSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
-    (*ppCtx)->iSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
-  }
-  if (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) {
-    (*ppCtx)->iPpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
-  }
+
+  (*ppCtx)->pFuncList->pParametersetStrategy->UpdateParaSetNum ((*ppCtx));
   return ENC_RETURN_SUCCESS;
 }
 
@@ -1908,8 +1679,8 @@
     return 1;
   }
 
-  const int32_t kiSpsSize = (*ppCtx)->GetNeededSpsNum() * SPS_BUFFER_SIZE;
-  const int32_t kiPpsSize = (*ppCtx)->GetNeededPpsNum() * PPS_BUFFER_SIZE;
+  const int32_t kiSpsSize = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSpsNum() * SPS_BUFFER_SIZE;
+  const int32_t kiPpsSize = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededPpsNum() * PPS_BUFFER_SIZE;
   iNonVclLayersBsSizeCount = SSEI_BUFFER_SIZE + kiSpsSize + kiPpsSize;
 
   bool    bDynamicSlice = false;
@@ -2316,6 +2087,10 @@
 
     FreeCodingParam (&pCtx->pSvcParam, pMa);
     if (NULL != pCtx->pFuncList) {
+      if (NULL != pCtx->pFuncList->pParametersetStrategy) {
+        WELS_DELETE_OP (pCtx->pFuncList->pParametersetStrategy);
+      }
+
       pMa->WelsFree (pCtx->pFuncList, "SWelsFuncPtrList");
       pCtx->pFuncList = NULL;
     }
@@ -2867,9 +2642,8 @@
   int32_t iCurPpsId = pDqIdc->iPpsId;
   int32_t iCurSpsId = pDqIdc->iSpsId;
 
-  if (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) {
-    iCurPpsId = pCtx->sPSOVector.iPpsIdList[pDqIdc->iPpsId][WELS_ABS (pCtx->uiIdrPicId - 1) % MAX_PPS_COUNT];
-  }
+  iCurPpsId = pCtx->pFuncList->pParametersetStrategy->GetCurrentPpsId (iCurPpsId,
+              WELS_ABS (pCtx->uiIdrPicId - 1) % MAX_PPS_COUNT);
 
   pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId       = iCurPpsId;
   pCurDq->sLayerInfo.pPpsP                              =
@@ -3148,45 +2922,12 @@
   }
 }
 
-
-void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable, const int32_t kiCurEncoderParaSetId,
-                                const uint32_t kuiMaxIdInBs) { //paraset_type = 0: SPS; =1: PPS
-  //SPS_ID in avc_sps and pSubsetSps will be different using this
-  //SPS_ID case example:
-  //1st enter:  next_spsid_in_bs == 0; spsid == 0; delta==0;            //actual spsid_in_bs == 0
-  //1st finish: next_spsid_in_bs == 1;
-  //2nd enter:  next_spsid_in_bs == 1; spsid == 0; delta==1;            //actual spsid_in_bs == 1
-  //2nd finish: next_spsid_in_bs == 2;
-  //31st enter: next_spsid_in_bs == 31; spsid == 0~2; delta==31~29;     //actual spsid_in_bs == 31
-  //31st finish:next_spsid_in_bs == 0;
-  //31st enter: next_spsid_in_bs == 0; spsid == 0~2; delta==-2~0;       //actual spsid_in_bs == 0
-  //31st finish:next_spsid_in_bs == 1;
-
-  const int32_t kiEncId = kiCurEncoderParaSetId;
-  uint32_t uiNextIdInBs = sParaSetOffsetVariable->uiNextParaSetIdToUseInBs;
-
-  //update current layer's pCodingParam
-  sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] = uiNextIdInBs -
-      kiEncId;  //for current parameter set, change its id_delta
-  //write pso pData for next update:
-  sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] = true; //   update current used_id
-
-  //prepare for next update:
-  //   find the next avaibable iId
-  ++uiNextIdInBs;
-  if (uiNextIdInBs >= kuiMaxIdInBs) {
-    uiNextIdInBs = 0;//ensure the SPS_ID wound not exceed MAX_SPS_COUNT
-  }
-  //   update next_id
-  sParaSetOffsetVariable->uiNextParaSetIdToUseInBs = uiNextIdInBs;
-}
-
 int32_t WelsWriteOneSPS (sWelsEncCtx* pCtx, const int32_t kiSpsIdx, int32_t& iNalSize) {
   int iNal = pCtx->pOut->iNalIndex;
   WelsLoadNal (pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST);
 
   WelsWriteSpsNal (&pCtx->pSpsArray[kiSpsIdx], &pCtx->pOut->sBsWrite,
-                   & (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS].iParaSetIdDelta[0]));
+                   pCtx->pFuncList->pParametersetStrategy->GetSpsIdOffsetList (PARA_SET_TYPE_AVCSPS));
   WelsUnloadNal (pCtx->pOut);
 
   int32_t iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
@@ -3204,8 +2945,9 @@
   int32_t iNal = pCtx->pOut->iNalIndex;
   /* generate picture parameter set */
   WelsLoadNal (pCtx->pOut, NAL_UNIT_PPS, NRI_PRI_HIGHEST);
+
   WelsWritePpsSyntax (&pCtx->pPPSArray[kiPpsIdx], &pCtx->pOut->sBsWrite,
-                      ((SPS_PPS_LISTING != pCtx->pSvcParam->eSpsPpsIdStrategy)) ? (& (pCtx->sPSOVector)) : NULL);
+                      pCtx->pFuncList->pParametersetStrategy);
   WelsUnloadNal (pCtx->pOut);
 
   int32_t iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
@@ -3218,44 +2960,7 @@
   return ENC_RETURN_SUCCESS;
 }
 
-void UpdatePpsList (sWelsEncCtx* pCtx) {
-  assert (pCtx->iPpsNum <= MAX_DQ_LAYER_NUM);
 
-  //Generate PPS LIST
-  int32_t iPpsId = 0, iUsePpsNum = pCtx->iPpsNum;
-
-  for (int32_t iIdrRound = 0; iIdrRound < MAX_PPS_COUNT; iIdrRound++) {
-    for (iPpsId = 0; iPpsId < pCtx->iPpsNum; iPpsId++) {
-      pCtx->sPSOVector.iPpsIdList[iPpsId][iIdrRound] = ((iIdrRound * iUsePpsNum + iPpsId) % MAX_PPS_COUNT);
-    }
-  }
-
-  for (iPpsId = iUsePpsNum; iPpsId < MAX_PPS_COUNT; iPpsId++) {
-    memcpy (& (pCtx->pPPSArray[iPpsId]), & (pCtx->pPPSArray[iPpsId % iUsePpsNum]), sizeof (SWelsPPS));
-    pCtx->pPPSArray[iPpsId].iPpsId = iPpsId;
-    pCtx->iPpsNum++;
-  }
-
-  assert (pCtx->iPpsNum == MAX_PPS_COUNT);
-  pCtx->sPSOVector.uiInUsePpsNum = pCtx->iPpsNum;
-
-}
-
-void UpdateSpsPpsIdStrategyWithIncreasingId (SParaSetOffset* pPSOVector, const uint32_t kuiId, const int iParasetType) {
-#if _DEBUG
-  pPSOVector->eSpsPpsIdStrategy = INCREASING_ID;
-  assert (kuiId < MAX_DQ_LAYER_NUM);
-#endif
-
-  ParasetIdAdditionIdAdjust (& (pPSOVector->sParaSetOffsetVariable[iParasetType]),
-                             kuiId,
-                             (iParasetType != PARA_SET_TYPE_PPS) ? MAX_SPS_COUNT : MAX_PPS_COUNT);
-}
-
-void UpdateSpsPpsIdStrategyWithConstantId (SParaSetOffset* pPSOVector, const uint32_t kuiId, const int iParasetType) {
-  memset (pPSOVector, 0, sizeof (SParaSetOffset));
-}
-
 /*!
  * \brief   write all parameter sets introduced in SVC extension
  * \return  writing results, success or error
@@ -3269,7 +2974,7 @@
   int32_t iNalLength    = 0;
   int32_t iReturn = ENC_RETURN_SUCCESS;
 
-  if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal)
+  if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal || NULL == pCtx->pFuncList->pParametersetStrategy)
     return ENC_RETURN_UNEXPECTED;
 
   *pTotalLength = 0;
@@ -3276,15 +2981,9 @@
   /* write all SPS */
   iIdx = 0;
   while (iIdx < pCtx->iSpsNum) {
-    // TODO (Sijia) wrap different operation of eSpsPpsIdStrategy to classes to hide the details
-    if (INCREASING_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
-      UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pSpsArray[0].uiSpsId, PARA_SET_TYPE_AVCSPS);
-    } else if (CONSTANT_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
-      UpdateSpsPpsIdStrategyWithConstantId (& (pCtx->sPSOVector), pCtx->pSpsArray[0].uiSpsId, PARA_SET_TYPE_AVCSPS);
-    }
-
+    pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
     /* generate sequence parameters set */
-    iId = (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy) ? iIdx : 0;
+    iId = pCtx->pFuncList->pParametersetStrategy->GetSpsIdx (iIdx);
 
     WelsWriteOneSPS (pCtx, iId, iNalLength);
 
@@ -3300,12 +2999,8 @@
   while (iIdx < pCtx->iSubsetSpsNum) {
     iNal = pCtx->pOut->iNalIndex;
 
-    if (INCREASING_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
-      UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pSubsetArray[iIdx].pSps.uiSpsId,
-                                              PARA_SET_TYPE_SUBSETSPS);
-    }
+    pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSubsetArray[iIdx].pSps.uiSpsId, PARA_SET_TYPE_SUBSETSPS);
 
-
     iId = iIdx;
 
     /* generate Subset SPS */
@@ -3312,7 +3007,7 @@
     WelsLoadNal (pCtx->pOut, NAL_UNIT_SUBSET_SPS, NRI_PRI_HIGHEST);
 
     WelsWriteSubsetSpsSyntax (&pCtx->pSubsetArray[iId], &pCtx->pOut->sBsWrite,
-                              & (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS].iParaSetIdDelta[0]));
+                              pCtx->pFuncList->pParametersetStrategy->GetSpsIdOffsetList (PARA_SET_TYPE_SUBSETSPS));
     WelsUnloadNal (pCtx->pOut);
 
     iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
@@ -3329,16 +3024,11 @@
     ++ iCountNal;
   }
 
-  /* write all PPS */
-  if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
-    UpdatePpsList (pCtx);
-  }
+  pCtx->pFuncList->pParametersetStrategy->UpdatePpsList (pCtx);
 
   iIdx = 0;
   while (iIdx < pCtx->iPpsNum) {
-    if ((INCREASING_ID & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
-      UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
-    }
+    pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
 
     WelsWriteOnePPS (pCtx, iIdx, iNalLength);
 
@@ -3552,10 +3242,9 @@
   int32_t iNalSize = 0;
   iCountNal        = 0;
 
-  if (INCREASING_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
-    UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
-  } else if (CONSTANT_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
-    UpdateSpsPpsIdStrategyWithConstantId (& (pCtx->sPSOVector), pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
+
+  if (pCtx->pFuncList->pParametersetStrategy) {
+    pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
   }
 
   iReturn          = WelsWriteOneSPS (pCtx, iIdx, iNalSize);
@@ -3589,10 +3278,8 @@
   iNalSize = 0;
   iCountNal        = 0;
 
-  if (INCREASING_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
-    UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
-  } else if (CONSTANT_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
-    UpdateSpsPpsIdStrategyWithConstantId (& (pCtx->sPSOVector), pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
+  if (pCtx->pFuncList->pParametersetStrategy) {
+    pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
   }
 
   iReturn          = WelsWriteOnePPS (pCtx, iIdx, iNalSize);
@@ -3666,9 +3353,7 @@
   }
 
   // write PPS
-  if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
-    UpdatePpsList (pCtx);
-  }
+  pCtx->pFuncList->pParametersetStrategy->UpdatePpsList (pCtx);
 
   //TODO: under new strategy, will PPS be correctly updated?
   for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
@@ -3811,22 +3496,29 @@
     pCtx->iContinualSkipFrames = 0;
     iCurTid = GetTemporalLevel (&pSvcParam->sDependencyLayers[iCurDid], pParamInternal->iCodingIndex,
                                 pSvcParam->uiGopSize);
-    pCtx->uiTemporalId = iCurTid;
-    if (eFrameType == videoFrameTypeIDR) {
-      // write parameter sets bitstream or SEI/SSEI (if any) here
-      // TODO: use function pointer instead
-      if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
-        if (pSvcParam->bSimulcastAVC) {
-          pCtx->iEncoderError = WriteSavcParaset (pCtx, iCurDid, pLayerBsInfo, iLayerNum, iFrameSize);
-          ++ pCtx->uiIdrPicId;
+    //skip this spatial layer
+    if (iCurTid == INVALID_TEMPORAL_ID) {
+      pParamInternal->iCodingIndex ++;
+      eFrameType = videoFrameTypeSkip;
+      pLayerBsInfo->eFrameType = videoFrameTypeSkip;
+    } else {
+      pCtx->uiTemporalId = iCurTid;
+      if (eFrameType == videoFrameTypeIDR) {
+        // write parameter sets bitstream or SEI/SSEI (if any) here
+        // TODO: use function pointer instead
+        if (! (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
+          if (pSvcParam->bSimulcastAVC) {
+            pCtx->iEncoderError = WriteSavcParaset (pCtx, iCurDid, pLayerBsInfo, iLayerNum, iFrameSize);
+            ++ pCtx->uiIdrPicId;
+          } else {
+            pCtx->iEncoderError = WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
+            ++ pCtx->uiIdrPicId;
+          }
         } else {
-          pCtx->iEncoderError = WriteSsvcParaset (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
+          pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
+
           ++ pCtx->uiIdrPicId;
         }
-      } else {
-        pCtx->iEncoderError = WriteSavcParaset_Listing (pCtx, iSpatialNum, pLayerBsInfo, iLayerNum, iFrameSize);
-
-        ++ pCtx->uiIdrPicId;
       }
     }
 
@@ -3931,12 +3623,7 @@
     int32_t  iDecompositionStages = pSvcParam->sDependencyLayers[iCurDid].iDecompositionStages;
     pCtx->pCurDqLayer           = pCtx->ppDqLayerList[iCurDid];
     pCtx->uiDependencyId        =  iCurDid;
-    //skip this spatial layer
-    if (GetTemporalLevel (pParamInternal, pParamInternal->iCodingIndex, pSvcParam->uiGopSize) == INVALID_TEMPORAL_ID) {
-      ++iSpatialIdx;
-      pParamInternal->iCodingIndex ++;
-      continue;
-    }
+
     if (pSvcParam->bSimulcastAVC) {
       eFrameType = PrepareEncodeFrame (pCtx, pLayerBsInfo, iSpatialNum , iCurDid, iCurTid, iLayerNum, iFrameSize,
                                        pFbi->uiTimeStamp);
@@ -4659,46 +4346,16 @@
     SExistingParasetList sExistingParasetList;
     SExistingParasetList* pExistingParasetList = NULL;
 
-    if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy)) {
-      for (int32_t k = 0; k < PARA_SET_TYPE; k++) {
-        memset (((*ppCtx)->sPSOVector.sParaSetOffsetVariable[k].bUsedParaSetIdInBs), 0, MAX_PPS_COUNT * sizeof (bool));
-      }
-      memcpy (sTmpPsoVariable, (*ppCtx)->sPSOVector.sParaSetOffsetVariable,
-              (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
+    if (((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy))) {
+      (*ppCtx)->pFuncList->pParametersetStrategy->OutputCurrentStructure (sTmpPsoVariable, iTmpPpsIdList, (*ppCtx),
+          &sExistingParasetList);
 
       if ((SPS_LISTING & iOldSpsPpsIdStrategy)
           && (SPS_LISTING & pNewParam->eSpsPpsIdStrategy)) {
         pExistingParasetList = &sExistingParasetList;
-        sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
-        memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
-        if (NULL != (*ppCtx)->pSubsetArray) {
-          sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
-          memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
-        } else {
-          sExistingParasetList.uiInUseSubsetSpsNum = 0;
-        }
       }
-
-      if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
-          && (SPS_PPS_LISTING == pNewParam->eSpsPpsIdStrategy)) {
-        pExistingParasetList = &sExistingParasetList;
-        sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
-        sExistingParasetList.uiInUsePpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
-        memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
-        memcpy (sExistingParasetList.sPps, (*ppCtx)->pPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
-
-        if (NULL != (*ppCtx)->pSubsetArray) {
-          sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
-          memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
-        } else {
-          sExistingParasetList.uiInUseSubsetSpsNum = 0;
-        }
-
-        memcpy (iTmpPpsIdList, ((*ppCtx)->sPSOVector.iPpsIdList), MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
-      }
     }
 
-
     WelsUninitEncoderExt (ppCtx);
 
     /* Update new parameters */
@@ -4711,14 +4368,10 @@
     //for sEncoderStatistics
     memcpy ((*ppCtx)->sEncoderStatistics, sTempEncoderStatistics, sizeof (sTempEncoderStatistics));
     //load back the needed structure for eSpsPpsIdStrategy
-    if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy)) {
-      memcpy ((*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable,
-              (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
-    }
-
-    if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
-        && (SPS_PPS_LISTING == pNewParam->eSpsPpsIdStrategy)) {
-      memcpy (((*ppCtx)->sPSOVector.iPpsIdList), iTmpPpsIdList, MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
+    if (((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy))
+        || ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
+            && (SPS_PPS_LISTING == pNewParam->eSpsPpsIdStrategy))) {
+      (*ppCtx)->pFuncList->pParametersetStrategy->LoadPreviousStructure (sTmpPsoVariable, iTmpPpsIdList);
     }
   } else {
     /* maybe adjustment introduced in bitrate or little settings adjustment and so on.. */
--- /dev/null
+++ b/codec/encoder/core/src/paraset_strategy.cpp
@@ -1,0 +1,713 @@
+/*!
+ * \copy
+ *     Copyright (c)  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.
+ *
+ */
+
+#include "au_set.h"
+#include "encoder_context.h"
+#include "paraset_strategy.h"
+
+namespace WelsEnc {
+
+
+IWelsParametersetStrategy*   IWelsParametersetStrategy::CreateParametersetStrategy (
+  EParameterSetStrategy eSpsPpsIdStrategy, bool bSimulcastAVC,
+  const int32_t kiSpatialLayerNum) {
+
+  IWelsParametersetStrategy* pParametersetStrategy = NULL;
+  switch (eSpsPpsIdStrategy) {
+  case INCREASING_ID:
+    pParametersetStrategy = WELS_NEW_OP (CWelsParametersetIdIncreasing (bSimulcastAVC, kiSpatialLayerNum),
+                                         CWelsParametersetIdIncreasing);
+    WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
+    break;
+  case SPS_LISTING:
+    pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsListing (bSimulcastAVC, kiSpatialLayerNum),
+                                         CWelsParametersetSpsListing);
+    WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
+    break;
+  case SPS_LISTING_AND_PPS_INCREASING:
+    pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsListingPpsIncreasing (bSimulcastAVC, kiSpatialLayerNum),
+                                         CWelsParametersetSpsListingPpsIncreasing);
+    WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
+    break;
+  case SPS_PPS_LISTING:
+    pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsPpsListing (bSimulcastAVC, kiSpatialLayerNum),
+                                         CWelsParametersetSpsPpsListing);
+    WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
+    break;
+  case CONSTANT_ID:
+  default:
+    pParametersetStrategy = WELS_NEW_OP (CWelsParametersetIdConstant (bSimulcastAVC, kiSpatialLayerNum),
+                                         CWelsParametersetIdConstant);
+    WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
+    break;
+  }
+
+  return pParametersetStrategy;
+}
+
+
+static int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
+                                   const int32_t iDlayerCount, const int32_t kiSpsId,
+                                   SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) {
+  int32_t iRet = 0;
+
+  if (!kbUseSubsetSps) {
+    pSps        = & (pCtx->pSpsArray[kiSpsId]);
+  } else {
+    pSubsetSps  = & (pCtx->pSubsetArray[kiSpsId]);
+    pSps        = &pSubsetSps->pSps;
+  }
+
+  SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
+  SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
+  // Need port pSps/pPps initialization due to spatial scalability changed
+  if (!kbUseSubsetSps) {
+    iRet = WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
+                        pParam->iMaxNumRefFrame,
+                        kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
+                        bSVCBaselayer);
+  } else {
+    iRet = WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
+                              pParam->iMaxNumRefFrame,
+                              kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
+  }
+  return iRet;
+}
+
+static bool CheckMatchedSps (SWelsSPS* const pSps1, SWelsSPS* const pSps2) {
+
+  if ((pSps1->iMbWidth != pSps2->iMbWidth)
+      || (pSps1->iMbHeight != pSps2->iMbHeight)) {
+    return false;
+  }
+
+  if ((pSps1->uiLog2MaxFrameNum != pSps2->uiLog2MaxFrameNum)
+      || (pSps1->iLog2MaxPocLsb != pSps2->iLog2MaxPocLsb)) {
+    return false;
+  }
+
+  if (pSps1->iNumRefFrames != pSps2->iNumRefFrames) {
+    return false;
+  }
+
+  if ((pSps1->bFrameCroppingFlag != pSps2->bFrameCroppingFlag)
+      || (pSps1->sFrameCrop.iCropLeft != pSps2->sFrameCrop.iCropLeft)
+      || (pSps1->sFrameCrop.iCropRight != pSps2->sFrameCrop.iCropRight)
+      || (pSps1->sFrameCrop.iCropTop != pSps2->sFrameCrop.iCropTop)
+      || (pSps1->sFrameCrop.iCropBottom != pSps2->sFrameCrop.iCropBottom)
+     ) {
+    return false;
+  }
+
+  if ((pSps1->uiProfileIdc != pSps2->uiProfileIdc)
+      || (pSps1->bConstraintSet0Flag != pSps2->bConstraintSet0Flag)
+      || (pSps1->bConstraintSet1Flag != pSps2->bConstraintSet1Flag)
+      || (pSps1->bConstraintSet2Flag != pSps2->bConstraintSet2Flag)
+      || (pSps1->bConstraintSet3Flag != pSps2->bConstraintSet3Flag)
+      || (pSps1->iLevelIdc != pSps2->iLevelIdc)) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool CheckMatchedSubsetSps (SSubsetSps* const pSubsetSps1, SSubsetSps* const pSubsetSps2) {
+  if (!CheckMatchedSps (&pSubsetSps1->pSps, &pSubsetSps2->pSps)) {
+    return false;
+  }
+
+  if ((pSubsetSps1->sSpsSvcExt.iExtendedSpatialScalability      != pSubsetSps2->sSpsSvcExt.iExtendedSpatialScalability)
+      || (pSubsetSps1->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag  != pSubsetSps2->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag)
+      || (pSubsetSps1->sSpsSvcExt.bSeqTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bSeqTcoeffLevelPredFlag)
+      || (pSubsetSps1->sSpsSvcExt.bSliceHeaderRestrictionFlag != pSubsetSps2->sSpsSvcExt.bSliceHeaderRestrictionFlag)) {
+    return false;
+  }
+
+  return true;
+}
+
+/*!
+ * \brief   check if the current parameter can found a presenting sps
+ * \param   pParam          the current encoding paramter in SWelsSvcCodingParam
+ * \param   kbUseSubsetSps  bool
+ * \param   iDlayerIndex    int, the index of current D layer
+ * \param   iDlayerCount    int, the number of total D layer
+ * \param pSpsArray         array of all the stored SPSs
+ * \param   pSubsetArray    array of all the stored Subset-SPSs
+ * \return  0 - successful
+ *         -1 - cannot find existing SPS for current encoder parameter
+ */
+int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
+                         const int32_t iDlayerCount, const int32_t iSpsNumInUse,
+                         SWelsSPS* pSpsArray,
+                         SSubsetSps* pSubsetArray, bool bSVCBaseLayer) {
+  SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
+
+  assert (iSpsNumInUse <= MAX_SPS_COUNT);
+  if (!kbUseSubsetSps) {
+    SWelsSPS sTmpSps;
+    WelsInitSps (&sTmpSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
+                 pParam->iMaxNumRefFrame,
+                 0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
+                 bSVCBaseLayer);
+    for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
+      if (CheckMatchedSps (&sTmpSps, &pSpsArray[iId])) {
+        return iId;
+      }
+    }
+  } else {
+    SSubsetSps sTmpSubsetSps;
+    WelsInitSubsetSps (&sTmpSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
+                       pParam->iMaxNumRefFrame,
+                       0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
+
+    for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
+      if (CheckMatchedSubsetSps (&sTmpSubsetSps, &pSubsetArray[iId])) {
+        return iId;
+      }
+    }
+  }
+
+  return INVALID_ID;
+}
+
+CWelsParametersetIdConstant::CWelsParametersetIdConstant (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum) {
+  memset (&m_sParaSetOffset, 0, sizeof (m_sParaSetOffset));
+
+  m_bSimulcastAVC = bSimulcastAVC;
+  m_iSpatialLayerNum = kiSpatialLayerNum;
+
+  m_iBasicNeededSpsNum = 1;
+  m_iBasicNeededPpsNum = (1 + m_iSpatialLayerNum);
+}
+
+CWelsParametersetIdConstant::~CWelsParametersetIdConstant() {
+}
+
+int32_t CWelsParametersetIdConstant::GetPpsIdOffset (const int32_t iPpsId) {
+  return 0;
+};
+int32_t CWelsParametersetIdConstant::GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId) {
+  return 0;
+};
+
+int32_t* CWelsParametersetIdConstant::GetSpsIdOffsetList (const int iParasetType) {
+  return & (m_sParaSetOffset.sParaSetOffsetVariable[iParasetType].iParaSetIdDelta[0]);
+}
+
+uint32_t CWelsParametersetIdConstant::GetAllNeededParasetNum() {
+  return (GetNeededSpsNum()
+          + GetNeededSubsetSpsNum()
+          + GetNeededPpsNum());
+}
+
+uint32_t CWelsParametersetIdConstant::GetNeededSpsNum() {
+  if (0 >= m_sParaSetOffset.uiNeededSpsNum) {
+    m_sParaSetOffset.uiNeededSpsNum = m_iBasicNeededSpsNum * ((m_bSimulcastAVC) ? (m_iSpatialLayerNum) : (1));
+  }
+  return m_sParaSetOffset.uiNeededSpsNum;
+}
+
+
+uint32_t CWelsParametersetIdConstant::GetNeededSubsetSpsNum() {
+  if (0 >= m_sParaSetOffset.uiNeededSubsetSpsNum) {
+    m_sParaSetOffset.uiNeededSubsetSpsNum = (m_bSimulcastAVC ? 0 : (m_iSpatialLayerNum - 1));
+  }
+  return m_sParaSetOffset.uiNeededSubsetSpsNum;
+}
+
+uint32_t CWelsParametersetIdConstant::GetNeededPpsNum() {
+  if (0 == m_sParaSetOffset.uiNeededPpsNum) {
+    m_sParaSetOffset.uiNeededPpsNum = m_iBasicNeededPpsNum * ((m_bSimulcastAVC) ? (m_iSpatialLayerNum) :
+                                      (1));
+  }
+  return m_sParaSetOffset.uiNeededPpsNum;
+}
+
+void CWelsParametersetIdConstant::LoadPrevious (SExistingParasetList* pExistingParasetList,  SWelsSPS* pSpsArray,
+    SSubsetSps*       pSubsetArray, SWelsPPS* pPpsArray) {
+  return;
+}
+
+void CWelsParametersetIdConstant::Update (const uint32_t kuiId, const int iParasetType) {
+  memset (&m_sParaSetOffset, 0, sizeof (SParaSetOffset));
+}
+
+uint32_t CWelsParametersetIdConstant::GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps,
+    const int32_t iDlayerIndex,
+    const int32_t iDlayerCount, uint32_t kuiSpsId,
+    SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) {
+  WelsGenerateNewSps (pCtx, kbUseSubsetSps, iDlayerIndex,
+                      iDlayerCount, kuiSpsId,
+                      pSps, pSubsetSps, bSVCBaselayer);
+  return kuiSpsId;
+}
+
+
+uint32_t CWelsParametersetIdConstant::InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
+    SWelsSPS* pSps,
+    SSubsetSps* pSubsetSps,
+    uint32_t kuiPpsId,
+    const bool kbDeblockingFilterPresentFlag,
+    const bool kbUsingSubsetSps,
+    const bool kbEntropyCodingModeFlag) {
+  WelsInitPps (& pCtx->pPPSArray[kuiPpsId], pSps, pSubsetSps, kuiPpsId, true, kbUsingSubsetSps, kbEntropyCodingModeFlag);
+  SetUseSubsetFlag (kuiPpsId, kbUsingSubsetSps);
+  return kuiPpsId;
+}
+
+void CWelsParametersetIdConstant::SetUseSubsetFlag (const uint32_t iPpsId, const bool bUseSubsetSps) {
+  m_sParaSetOffset.bPpsIdMappingIntoSubsetsps[iPpsId] = bUseSubsetSps;
+}
+
+void CWelsParametersetIdNonConstant::OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
+    int32_t* pPpsIdList, sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) {
+  for (int32_t k = 0; k < PARA_SET_TYPE; k++) {
+    memset ((m_sParaSetOffset.sParaSetOffsetVariable[k].bUsedParaSetIdInBs), 0, MAX_PPS_COUNT * sizeof (bool));
+  }
+  memcpy (pParaSetOffsetVariable, m_sParaSetOffset.sParaSetOffsetVariable,
+          (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
+}
+void CWelsParametersetIdNonConstant::LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
+    int32_t* pPpsIdList) {
+  memcpy (m_sParaSetOffset.sParaSetOffsetVariable, pParaSetOffsetVariable,
+          (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
+}
+
+//
+//CWelsParametersetIdIncreasing
+//
+
+void CWelsParametersetIdIncreasing::DebugSpsPps (const int32_t kiPpsId, const int32_t kiSpsId) {
+#if _DEBUG
+  //SParaSetOffset use, 110421
+  //if ( (INCREASING_ID & eSpsPpsIdStrategy)) {
+  const int32_t kiParameterSetType = (m_sParaSetOffset.bPpsIdMappingIntoSubsetsps[kiPpsId] ?
+                                      PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS) ;
+
+  const int32_t kiTmpSpsIdInBs = kiSpsId +
+                                 m_sParaSetOffset.sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[kiSpsId];
+  const int32_t tmp_pps_id_in_bs = kiPpsId +
+                                   m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[kiPpsId];
+  assert (MAX_SPS_COUNT > kiTmpSpsIdInBs);
+  assert (MAX_PPS_COUNT > tmp_pps_id_in_bs);
+  assert (m_sParaSetOffset.sParaSetOffsetVariable[kiParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
+  //}
+#endif
+}
+void CWelsParametersetIdIncreasing::DebugPps (const int32_t kiPpsId) {
+#if _DEBUG
+  const int32_t kiTmpPpsIdInBs = kiPpsId +
+                                 m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[ kiPpsId ];
+  assert (MAX_PPS_COUNT > kiTmpPpsIdInBs);
+
+  //when activated need to sure there is avialable PPS
+  assert (m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].bUsedParaSetIdInBs[kiTmpPpsIdInBs]);
+#endif
+}
+
+void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable,
+                                const int32_t kiCurEncoderParaSetId,
+                                const uint32_t kuiMaxIdInBs) { //paraset_type = 0: SPS; =1: PPS
+  //SPS_ID in avc_sps and pSubsetSps will be different using this
+  //SPS_ID case example:
+  //1st enter:  next_spsid_in_bs == 0; spsid == 0; delta==0;            //actual spsid_in_bs == 0
+  //1st finish: next_spsid_in_bs == 1;
+  //2nd enter:  next_spsid_in_bs == 1; spsid == 0; delta==1;            //actual spsid_in_bs == 1
+  //2nd finish: next_spsid_in_bs == 2;
+  //31st enter: next_spsid_in_bs == 31; spsid == 0~2; delta==31~29;     //actual spsid_in_bs == 31
+  //31st finish:next_spsid_in_bs == 0;
+  //31st enter: next_spsid_in_bs == 0; spsid == 0~2; delta==-2~0;       //actual spsid_in_bs == 0
+  //31st finish:next_spsid_in_bs == 1;
+
+  const int32_t kiEncId = kiCurEncoderParaSetId;
+  uint32_t uiNextIdInBs = sParaSetOffsetVariable->uiNextParaSetIdToUseInBs;
+
+  //update current layer's pCodingParam
+  sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] = uiNextIdInBs -
+      kiEncId;  //for current parameter set, change its id_delta
+  //write pso pData for next update:
+  sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] = true; //   update current used_id
+
+  //prepare for next update:
+  //   find the next avaibable iId
+  ++uiNextIdInBs;
+  if (uiNextIdInBs >= kuiMaxIdInBs) {
+    uiNextIdInBs = 0;//ensure the SPS_ID wound not exceed MAX_SPS_COUNT
+  }
+  //   update next_id
+  sParaSetOffsetVariable->uiNextParaSetIdToUseInBs = uiNextIdInBs;
+}
+
+void CWelsParametersetIdIncreasing::Update (const uint32_t kuiId, const int iParasetType) {
+#if _DEBUG
+  m_sParaSetOffset.eSpsPpsIdStrategy = INCREASING_ID;
+  assert (kuiId < MAX_DQ_LAYER_NUM);
+#endif
+
+  ParasetIdAdditionIdAdjust (& (m_sParaSetOffset.sParaSetOffsetVariable[iParasetType]),
+                             kuiId,
+                             (iParasetType != PARA_SET_TYPE_PPS) ? MAX_SPS_COUNT : MAX_PPS_COUNT);
+}
+//((SPS_PPS_LISTING != pEncCtx->pSvcParam->eSpsPpsIdStrategy) ? (&
+//  (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0])) : NULL)
+
+int32_t CWelsParametersetIdIncreasing::GetPpsIdOffset (const int32_t kiPpsId) {
+#if _DEBUG
+  DebugPps (kiPpsId);
+#endif
+  return (m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[kiPpsId]);
+}
+
+int32_t CWelsParametersetIdIncreasing::GetSpsIdOffset (const int32_t kiPpsId, const int32_t kiSpsId) {
+  const int32_t kiParameterSetType = (m_sParaSetOffset.bPpsIdMappingIntoSubsetsps[kiPpsId] ?
+                                      PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS);
+#if _DEBUG
+  DebugSpsPps (kiPpsId, kiSpsId);
+#endif
+  return (m_sParaSetOffset.sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[kiSpsId]);
+}
+
+//
+//CWelsParametersetSpsListing
+//
+
+CWelsParametersetSpsListing::CWelsParametersetSpsListing (const bool bSimulcastAVC,
+    const int32_t kiSpatialLayerNum) : CWelsParametersetIdNonConstant (bSimulcastAVC, kiSpatialLayerNum) {
+  memset (&m_sParaSetOffset, 0, sizeof (m_sParaSetOffset));
+
+  m_bSimulcastAVC = bSimulcastAVC;
+  m_iSpatialLayerNum = kiSpatialLayerNum;
+
+  m_iBasicNeededSpsNum = MAX_SPS_COUNT;
+  m_iBasicNeededPpsNum = 1;
+}
+
+uint32_t CWelsParametersetSpsListing::GetNeededSubsetSpsNum() {
+  if (0 >= m_sParaSetOffset.uiNeededSubsetSpsNum) {
+    //      sPSOVector.uiNeededSubsetSpsNum = ((pSvcParam->bSimulcastAVC) ? (0) :((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (pSvcParam->iSpatialLayerNum - 1)));
+    m_sParaSetOffset.uiNeededSubsetSpsNum = ((m_bSimulcastAVC) ? (0) :
+                                            (MAX_SPS_COUNT));
+  }
+  return m_sParaSetOffset.uiNeededSubsetSpsNum;
+}
+
+void CWelsParametersetSpsListing::LoadPreviousSps (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
+    SSubsetSps*       pSubsetArray) {
+  //if ((SPS_LISTING & pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
+  m_sParaSetOffset.uiInUseSpsNum = pExistingParasetList->uiInUseSpsNum;
+  memcpy (pSpsArray, pExistingParasetList->sSps, MAX_SPS_COUNT * sizeof (SWelsSPS));
+
+  if (GetNeededSubsetSpsNum() > 0) {
+    m_sParaSetOffset.uiInUseSubsetSpsNum = pExistingParasetList->uiInUseSubsetSpsNum;
+    memcpy (pSubsetArray, pExistingParasetList->sSubsetSps, MAX_SPS_COUNT * sizeof (SSubsetSps));
+  } else {
+    m_sParaSetOffset.uiInUseSubsetSpsNum = 0;
+  }
+  //}
+
+}
+void CWelsParametersetSpsListing::LoadPrevious (SExistingParasetList* pExistingParasetList,  SWelsSPS* pSpsArray,
+    SSubsetSps*       pSubsetArray, SWelsPPS* pPpsArray) {
+  if (NULL == pExistingParasetList) {
+    return;
+  }
+  LoadPreviousSps (pExistingParasetList, pSpsArray, pSubsetArray);
+  LoadPreviousPps (pExistingParasetList, pPpsArray);
+}
+
+bool CWelsParametersetSpsListing::CheckParamCompatibility (SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) {
+  if (pCodingParam->iSpatialLayerNum > 1 && (!pCodingParam->bSimulcastAVC)) {
+    WelsLog (pLogCtx, WELS_LOG_WARNING,
+             "ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with multiple svc SpatialLayers (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID",
+             pCodingParam->eSpsPpsIdStrategy, pCodingParam->iSpatialLayerNum);
+    pCodingParam->eSpsPpsIdStrategy = CONSTANT_ID;
+    return false;
+  }
+  return true;
+}
+
+bool CWelsParametersetSpsListing::CheckPpsGenerating() {
+  return true;
+}
+int32_t CWelsParametersetSpsListing::SpsReset (sWelsEncCtx* pCtx, bool kbUseSubsetSps) {
+
+  // reset current list
+  if (!kbUseSubsetSps) {
+    m_sParaSetOffset.uiInUseSpsNum = 1;
+    memset (pCtx->pSpsArray, 0, MAX_SPS_COUNT * sizeof (SWelsSPS));
+  } else {
+    m_sParaSetOffset.uiInUseSubsetSpsNum = 1;
+    memset (pCtx->pSubsetArray, 0, MAX_SPS_COUNT * sizeof (SSubsetSps));
+  }
+
+  //iSpsId = 0;
+  return 0;
+}
+uint32_t CWelsParametersetSpsListing::GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps,
+    const int32_t iDlayerIndex,
+    const int32_t iDlayerCount, uint32_t kuiSpsId,
+    SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSvcBaselayer) {
+  //check if the current param can fit in an existing SPS
+  const int32_t kiFoundSpsId = FindExistingSps (pCtx->pSvcParam, kbUseSubsetSps, iDlayerIndex, iDlayerCount,
+                               kbUseSubsetSps ? (m_sParaSetOffset.uiInUseSubsetSpsNum) : (m_sParaSetOffset.uiInUseSpsNum),
+                               pCtx->pSpsArray,
+                               pCtx->pSubsetArray, bSvcBaselayer);
+
+
+  if (INVALID_ID != kiFoundSpsId) {
+    //if yes, set pSps or pSubsetSps to it
+    kuiSpsId = kiFoundSpsId;
+    if (!kbUseSubsetSps) {
+      pSps = & (pCtx->pSpsArray[kiFoundSpsId]);
+    } else {
+      pSubsetSps = & (pCtx->pSubsetArray[kiFoundSpsId]);
+    }
+  } else {
+    //if no, generate a new SPS as usual
+    if (!CheckPpsGenerating()) {
+      return -1;
+    }
+
+    kuiSpsId = (!kbUseSubsetSps) ? (m_sParaSetOffset.uiInUseSpsNum++) : (m_sParaSetOffset.uiInUseSubsetSpsNum++);
+    if (kuiSpsId >= MAX_SPS_COUNT) {
+      if (SpsReset (pCtx, kbUseSubsetSps) < 0) {
+        return -1;
+      }
+      kuiSpsId = 0;
+    }
+
+    WelsGenerateNewSps (pCtx, kbUseSubsetSps, iDlayerIndex,
+                        iDlayerCount, kuiSpsId, pSps, pSubsetSps, bSvcBaselayer);
+  }
+  return kuiSpsId;
+}
+
+void CWelsParametersetSpsListing::UpdateParaSetNum (sWelsEncCtx* pCtx) {
+  pCtx->iSpsNum = m_sParaSetOffset.uiInUseSpsNum;
+  pCtx->iSubsetSpsNum = m_sParaSetOffset.uiInUseSubsetSpsNum;
+};
+
+void CWelsParametersetSpsListing::OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
+    int32_t* pPpsIdList, sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) {
+  CWelsParametersetIdNonConstant::OutputCurrentStructure (pParaSetOffsetVariable, pPpsIdList, pCtx, pExistingParasetList);
+  pExistingParasetList->uiInUseSpsNum = m_sParaSetOffset.uiInUseSpsNum;
+
+  memcpy (pExistingParasetList->sSps, pCtx->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
+  if (NULL != pCtx->pSubsetArray) {
+    pExistingParasetList->uiInUseSubsetSpsNum = m_sParaSetOffset.uiInUseSubsetSpsNum;
+    memcpy (pExistingParasetList->sSubsetSps, pCtx->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
+  } else {
+    pExistingParasetList->uiInUseSubsetSpsNum = 0;
+  }
+}
+
+//
+//CWelsParametersetSpsPpsListing
+//
+
+CWelsParametersetSpsPpsListing::CWelsParametersetSpsPpsListing (const bool bSimulcastAVC,
+    const int32_t kiSpatialLayerNum): CWelsParametersetSpsListing (bSimulcastAVC, kiSpatialLayerNum) {
+  memset (&m_sParaSetOffset, 0, sizeof (m_sParaSetOffset));
+
+  m_bSimulcastAVC = bSimulcastAVC;
+  m_iSpatialLayerNum = kiSpatialLayerNum;
+
+  m_iBasicNeededSpsNum = MAX_SPS_COUNT;
+  m_iBasicNeededPpsNum = MAX_PPS_COUNT;
+}
+
+void CWelsParametersetSpsPpsListing::LoadPreviousPps (SExistingParasetList* pExistingParasetList, SWelsPPS* pPpsArray) {
+  // copy from existing if the pointer exists
+  //if ((SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
+  m_sParaSetOffset.uiInUsePpsNum = pExistingParasetList->uiInUsePpsNum;
+  memcpy (pPpsArray, pExistingParasetList->sPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
+  //}
+}
+
+/*  if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
+ UpdatePpsList (pCtx);
+ }*/
+void CWelsParametersetSpsPpsListing::UpdatePpsList (sWelsEncCtx* pCtx) {
+  if (pCtx->iPpsNum >= MAX_PPS_COUNT) {
+    return;
+  }
+  assert (pCtx->iPpsNum <= MAX_DQ_LAYER_NUM);
+
+  //Generate PPS LIST
+  int32_t iPpsId = 0, iUsePpsNum = pCtx->iPpsNum;
+
+  for (int32_t iIdrRound = 0; iIdrRound < MAX_PPS_COUNT; iIdrRound++) {
+    for (iPpsId = 0; iPpsId < pCtx->iPpsNum; iPpsId++) {
+      m_sParaSetOffset.iPpsIdList[iPpsId][iIdrRound] = ((iIdrRound * iUsePpsNum + iPpsId) % MAX_PPS_COUNT);
+    }
+  }
+
+  for (iPpsId = iUsePpsNum; iPpsId < MAX_PPS_COUNT; iPpsId++) {
+    memcpy (& (pCtx->pPPSArray[iPpsId]), & (pCtx->pPPSArray[iPpsId % iUsePpsNum]), sizeof (SWelsPPS));
+    pCtx->pPPSArray[iPpsId].iPpsId = iPpsId;
+    pCtx->iPpsNum++;
+  }
+
+  assert (pCtx->iPpsNum == MAX_PPS_COUNT);
+  m_sParaSetOffset.uiInUsePpsNum = pCtx->iPpsNum;
+}
+
+
+bool CWelsParametersetSpsPpsListing::CheckPpsGenerating() {
+  /*if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (MAX_PPS_COUNT <= pCtx->sPSOVector.uiInUsePpsNum)) {
+    //check if we can generate new SPS or not
+    WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR,
+             "InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
+    return ENC_RETURN_UNSUPPORTED_PARA;
+  }*/
+  if (MAX_PPS_COUNT <= m_sParaSetOffset.uiInUsePpsNum) {
+    return false;
+  }
+
+  return true;
+}
+int32_t CWelsParametersetSpsPpsListing::SpsReset (sWelsEncCtx* pCtx, bool kbUseSubsetSps) {
+  /*        if (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) {
+   WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
+   "InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
+   return ENC_RETURN_UNSUPPORTED_PARA;
+   }*/
+  return -1;
+}
+
+int32_t FindExistingPps (SWelsSPS* pSps, SSubsetSps* pSubsetSps, const bool kbUseSubsetSps, const int32_t iSpsId,
+                         const bool kbEntropyCodingFlag, const int32_t iPpsNumInUse,
+                         SWelsPPS* pPpsArray) {
+#if !defined(DISABLE_FMO_FEATURE)
+  // feature not supported yet
+  return INVALID_ID;
+#endif//!DISABLE_FMO_FEATURE
+
+  SWelsPPS sTmpPps;
+  WelsInitPps (&sTmpPps,
+               pSps,
+               pSubsetSps,
+               0,
+               true,
+               kbUseSubsetSps,
+               kbEntropyCodingFlag);
+
+  assert (iPpsNumInUse <= MAX_PPS_COUNT);
+  for (int32_t iId = 0; iId < iPpsNumInUse; iId++) {
+    if ((sTmpPps.iSpsId == pPpsArray[iId].iSpsId)
+        && (sTmpPps.bEntropyCodingModeFlag == pPpsArray[iId].bEntropyCodingModeFlag)
+        && (sTmpPps.iPicInitQp == pPpsArray[iId].iPicInitQp)
+        && (sTmpPps.iPicInitQs == pPpsArray[iId].iPicInitQs)
+        && (sTmpPps.uiChromaQpIndexOffset == pPpsArray[iId].uiChromaQpIndexOffset)
+        && (sTmpPps.bDeblockingFilterControlPresentFlag == pPpsArray[iId].bDeblockingFilterControlPresentFlag)
+       ) {
+      return iId;
+    }
+  }
+
+  return INVALID_ID;
+}
+
+uint32_t CWelsParametersetSpsPpsListing::InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
+    SWelsSPS* pSps,
+    SSubsetSps* pSubsetSps,
+    uint32_t kuiPpsId,
+    const bool kbDeblockingFilterPresentFlag,
+    const bool kbUsingSubsetSps,
+    const bool kbEntropyCodingModeFlag) {
+  const int32_t kiFoundPpsId = FindExistingPps (pSps, pSubsetSps, kbUsingSubsetSps, kiSpsId,
+                               kbEntropyCodingModeFlag,
+                               m_sParaSetOffset.uiInUsePpsNum,
+                               pCtx->pPPSArray);
+
+
+  if (INVALID_ID != kiFoundPpsId) {
+    //if yes, set pPps to it
+    kuiPpsId = kiFoundPpsId;
+  } else {
+    kuiPpsId = (m_sParaSetOffset.uiInUsePpsNum++);
+    WelsInitPps (& pCtx->pPPSArray[kuiPpsId], pSps, pSubsetSps, kuiPpsId, true, kbUsingSubsetSps, kbEntropyCodingModeFlag);
+  }
+  SetUseSubsetFlag (kuiPpsId, kbUsingSubsetSps);
+  return kuiPpsId;
+}
+
+void CWelsParametersetSpsPpsListing::UpdateParaSetNum (sWelsEncCtx* pCtx) {
+  CWelsParametersetSpsListing::UpdateParaSetNum (pCtx);
+
+  //UpdatePpsList (pCtx);
+  pCtx->iPpsNum = m_sParaSetOffset.uiInUsePpsNum;
+}
+
+int32_t CWelsParametersetSpsPpsListing::GetCurrentPpsId (const int32_t iPpsId, const int32_t iIdrLoop) {
+  return m_sParaSetOffset.iPpsIdList[iPpsId][iIdrLoop];
+}
+
+void CWelsParametersetSpsPpsListing::LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
+    int32_t* pPpsIdList) {
+  memcpy (m_sParaSetOffset.sParaSetOffsetVariable, pParaSetOffsetVariable,
+          (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
+
+  memcpy ((m_sParaSetOffset.iPpsIdList), pPpsIdList, MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
+
+}
+
+void CWelsParametersetSpsPpsListing::OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
+    int32_t* pPpsIdList, sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) {
+  CWelsParametersetSpsListing::OutputCurrentStructure (pParaSetOffsetVariable, pPpsIdList, pCtx, pExistingParasetList);
+
+  pExistingParasetList->uiInUsePpsNum = m_sParaSetOffset.uiInUsePpsNum;
+  memcpy (pExistingParasetList->sPps, pCtx->pPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
+  memcpy (pPpsIdList, (m_sParaSetOffset.iPpsIdList), MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
+}
+
+//
+//CWelsParametersetSpsListingPpsIncreasing
+//
+
+int32_t CWelsParametersetSpsListingPpsIncreasing::GetPpsIdOffset (const int32_t kiPpsId) {
+  //same as CWelsParametersetIdIncreasing::GetPpsIdOffset
+  return (m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[kiPpsId]);
+}
+
+void CWelsParametersetSpsListingPpsIncreasing::Update (const uint32_t kuiId, const int iParasetType) {
+  //same as CWelsParametersetIdIncreasing::Update
+#if _DEBUG
+  assert (kuiId < MAX_DQ_LAYER_NUM);
+#endif
+
+  ParasetIdAdditionIdAdjust (& (m_sParaSetOffset.sParaSetOffsetVariable[iParasetType]),
+                             kuiId,
+                             (iParasetType != PARA_SET_TYPE_PPS) ? MAX_SPS_COUNT : MAX_PPS_COUNT);
+}
+}
--- a/codec/encoder/core/src/svc_encode_slice.cpp
+++ b/codec/encoder/core/src/svc_encode_slice.cpp
@@ -52,7 +52,7 @@
 
 typedef int32_t (*PWelsCodingSliceFunc) (sWelsEncCtx* pCtx, SSlice* pSlice);
 typedef void (*PWelsSliceHeaderWriteFunc) (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
-    int32_t* pPpsIdDelta);
+    IWelsParametersetStrategy* pParametersetStrategy);
 
 void UpdateNonZeroCountCache (SMB* pMb, SMbCache* pMbCache) {
   ST32 (&pMbCache->iNonZeroCoeffCount[9], LD32 (&pMb->pNonZeroCount[ 0]));
@@ -276,7 +276,7 @@
 }
 
 void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
-                           int32_t* pPpsIdDelta) {
+                           IWelsParametersetStrategy* pParametersetStrategy) {
   SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
   SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
   SSliceHeader* pSliceHeader      = &pSlice->sSliceHeaderExt.sSliceHeader;
@@ -285,7 +285,7 @@
   BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice);
   BsWriteUE (pBs, pSliceHeader->eSliceType);    /* same type things */
 
-  BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + ((pPpsIdDelta != NULL) ? pPpsIdDelta[pSliceHeader->pPps->iPpsId] : 0));
+  BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pParametersetStrategy->GetPpsIdOffset (pSliceHeader->pPps->iPpsId));
 
   BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
 
@@ -342,7 +342,7 @@
 }
 
 void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
-                              int32_t* pPpsIdDelta) {
+                              IWelsParametersetStrategy* pParametersetStrategy) {
   SWelsSPS* pSps           = pCurLayer->sLayerInfo.pSpsP;
   SWelsPPS* pPps           = pCurLayer->sLayerInfo.pPpsP;
   SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP;
@@ -353,7 +353,8 @@
   BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice);
   BsWriteUE (pBs, pSliceHeader->eSliceType);    /* same type things */
 
-  BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + ((pPpsIdDelta != NULL) ? pPpsIdDelta[pSliceHeader->pPps->iPpsId] : 0));
+  BsWriteUE (pBs, pSliceHeader->pPps->iPpsId +
+             pParametersetStrategy->GetPpsIdOffset (pSliceHeader->pPps->iPpsId));
 
   BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
 
@@ -926,20 +927,7 @@
   WelsSliceHeaderExtInit (pEncCtx, pCurLayer, pCurSlice);
 
   g_pWelsWriteSliceHeader[pCurSlice->bSliceHeaderExtFlag] (pEncCtx, pBs, pCurLayer, pCurSlice,
-      ((SPS_PPS_LISTING != pEncCtx->pSvcParam->eSpsPpsIdStrategy) ? (&
-          (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0])) : NULL));
-
-#if _DEBUG
-  if (INCREASING_ID & pEncCtx->sPSOVector.eSpsPpsIdStrategy) {
-    const int32_t kiEncoderPpsId    = pCurSlice->sSliceHeaderExt.sSliceHeader.pPps->iPpsId;
-    const int32_t kiTmpPpsIdInBs = kiEncoderPpsId +
-                                   pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[ kiEncoderPpsId ];
-    assert (MAX_PPS_COUNT > kiTmpPpsIdInBs);
-
-    //when activated need to sure there is avialable PPS
-    assert (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].bUsedParaSetIdInBs[kiTmpPpsIdInBs]);
-  }
-#endif
+      pEncCtx->pFuncList->pParametersetStrategy);
 
   pCurSlice->uiLastMbQp = pCurLayer->sLayerInfo.pPpsP->iPicInitQp + pCurSlice->sSliceHeaderExt.sSliceHeader.iSliceQpDelta;
 
--- a/codec/encoder/targets.mk
+++ b/codec/encoder/targets.mk
@@ -11,6 +11,7 @@
 	$(ENCODER_SRCDIR)/core/src/md.cpp\
 	$(ENCODER_SRCDIR)/core/src/mv_pred.cpp\
 	$(ENCODER_SRCDIR)/core/src/nal_encap.cpp\
+	$(ENCODER_SRCDIR)/core/src/paraset_strategy.cpp\
 	$(ENCODER_SRCDIR)/core/src/picture_handle.cpp\
 	$(ENCODER_SRCDIR)/core/src/ratectl.cpp\
 	$(ENCODER_SRCDIR)/core/src/ref_list_mgr_svc.cpp\
--- a/codec/processing/src/downsample/downsample.cpp
+++ b/codec/processing/src/downsample/downsample.cpp
@@ -34,8 +34,9 @@
 #include "cpu.h"
 
 WELSVP_NAMESPACE_BEGIN
+#define MAX_SAMPLE_WIDTH 1920
+#define MAX_SAMPLE_HEIGHT 1088
 
-
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 CDownsampling::CDownsampling (int32_t iCpuFlag) {
@@ -43,11 +44,37 @@
   m_eMethod   = METHOD_DOWNSAMPLE;
   WelsMemset (&m_pfDownsample, 0, sizeof (m_pfDownsample));
   InitDownsampleFuncs (m_pfDownsample, m_iCPUFlag);
+  m_bNoSampleBuffer = AllocateSampleBuffer();
 }
 
 CDownsampling::~CDownsampling() {
+  FreeSampleBuffer();
 }
+bool CDownsampling::AllocateSampleBuffer() {
+  for (int32_t i = 0; i < 2; i++) {
+    m_pSampleBuffer[i][0] = (uint8_t*)WelsMalloc (MAX_SAMPLE_WIDTH * MAX_SAMPLE_HEIGHT);
+    if (!m_pSampleBuffer[i][0])
+      goto FREE_RET;
+    m_pSampleBuffer[i][1] = (uint8_t*)WelsMalloc (MAX_SAMPLE_WIDTH * MAX_SAMPLE_HEIGHT / 4);
+    if (!m_pSampleBuffer[i][1])
+      goto FREE_RET;
+    m_pSampleBuffer[i][2] = (uint8_t*)WelsMalloc (MAX_SAMPLE_WIDTH * MAX_SAMPLE_HEIGHT / 4);
+    if (!m_pSampleBuffer[i][2])
+      goto FREE_RET;
+  }
+  return false;
+FREE_RET:
+  FreeSampleBuffer();
+  return true;
 
+}
+void CDownsampling::FreeSampleBuffer() {
+  for (int32_t i = 0; i < 2; i++) {
+    WelsFree (m_pSampleBuffer[i][0]);
+    WelsFree (m_pSampleBuffer[i][1]);
+    WelsFree (m_pSampleBuffer[i][2]);
+  }
+}
 void CDownsampling::InitDownsampleFuncs (SDownsampleFuncs& sDownsampleFunc,  int32_t iCpuFlag) {
   sDownsampleFunc.pfHalfAverage[0] = DyadicBilinearDownsampler_c;
   sDownsampleFunc.pfHalfAverage[1] = DyadicBilinearDownsampler_c;
@@ -123,49 +150,132 @@
   if (iSrcWidthY <= iDstWidthY || iSrcHeightY <= iDstHeightY) {
     return RET_INVALIDPARAM;
   }
+  if (iSrcWidthY > MAX_SAMPLE_WIDTH || iSrcHeightY > MAX_SAMPLE_HEIGHT || m_bNoSampleBuffer) {
+    if ((iSrcWidthY >> 1) == iDstWidthY && (iSrcHeightY >> 1) == iDstHeightY) {
+      // use half average functions
+      uint8_t iAlignIndex = GetAlignedIndex (iSrcWidthY);
+      m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0],
+          (uint8_t*)pSrcPixMap->pPixel[0], pSrcPixMap->iStride[0], iSrcWidthY, iSrcHeightY);
 
-  if ((iSrcWidthY >> 1) == iDstWidthY && (iSrcHeightY >> 1) == iDstHeightY) {
-    // use half average functions
-    uint8_t iAlignIndex = GetAlignedIndex (iSrcWidthY);
-    m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0],
-        (uint8_t*)pSrcPixMap->pPixel[0], pSrcPixMap->iStride[0], iSrcWidthY, iSrcHeightY);
+      iAlignIndex = GetAlignedIndex (iSrcWidthUV);
+      m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1],
+          (uint8_t*)pSrcPixMap->pPixel[1], pSrcPixMap->iStride[1], iSrcWidthUV, iSrcHeightUV);
+      m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2],
+          (uint8_t*)pSrcPixMap->pPixel[2], pSrcPixMap->iStride[2], iSrcWidthUV, iSrcHeightUV);
+    } else if ((iSrcWidthY >> 2) == iDstWidthY && (iSrcHeightY >> 2) == iDstHeightY) {
 
-    iAlignIndex = GetAlignedIndex (iSrcWidthUV);
-    m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1],
-        (uint8_t*)pSrcPixMap->pPixel[1], pSrcPixMap->iStride[1], iSrcWidthUV, iSrcHeightUV);
-    m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2],
-        (uint8_t*)pSrcPixMap->pPixel[2], pSrcPixMap->iStride[2], iSrcWidthUV, iSrcHeightUV);
-  } else if ((iSrcWidthY >> 2) == iDstWidthY && (iSrcHeightY >> 2) == iDstHeightY) {
+      m_pfDownsample.pfQuarterDownsampler ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0],
+                                           (uint8_t*)pSrcPixMap->pPixel[0], pSrcPixMap->iStride[0], iSrcWidthY, iSrcHeightY);
 
-    m_pfDownsample.pfQuarterDownsampler ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0],
-                                         (uint8_t*)pSrcPixMap->pPixel[0], pSrcPixMap->iStride[0], iSrcWidthY, iSrcHeightY);
+      m_pfDownsample.pfQuarterDownsampler ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1],
+                                           (uint8_t*)pSrcPixMap->pPixel[1], pSrcPixMap->iStride[1], iSrcWidthUV, iSrcHeightUV);
 
-    m_pfDownsample.pfQuarterDownsampler ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1],
-                                         (uint8_t*)pSrcPixMap->pPixel[1], pSrcPixMap->iStride[1], iSrcWidthUV, iSrcHeightUV);
+      m_pfDownsample.pfQuarterDownsampler ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2],
+                                           (uint8_t*)pSrcPixMap->pPixel[2], pSrcPixMap->iStride[2], iSrcWidthUV, iSrcHeightUV);
 
-    m_pfDownsample.pfQuarterDownsampler ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2],
-                                         (uint8_t*)pSrcPixMap->pPixel[2], pSrcPixMap->iStride[2], iSrcWidthUV, iSrcHeightUV);
+    } else if ((iSrcWidthY / 3) == iDstWidthY && (iSrcHeightY / 3) == iDstHeightY) {
 
-  } else if ((iSrcWidthY / 3) == iDstWidthY && (iSrcHeightY / 3) == iDstHeightY) {
+      m_pfDownsample.pfOneThirdDownsampler ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0],
+                                            (uint8_t*)pSrcPixMap->pPixel[0], pSrcPixMap->iStride[0], iSrcWidthY, iDstHeightY);
 
-    m_pfDownsample.pfOneThirdDownsampler ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0],
-                                          (uint8_t*)pSrcPixMap->pPixel[0], pSrcPixMap->iStride[0], iSrcWidthY, iDstHeightY);
+      m_pfDownsample.pfOneThirdDownsampler ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1],
+                                            (uint8_t*)pSrcPixMap->pPixel[1], pSrcPixMap->iStride[1], iSrcWidthUV, iDstHeightUV);
 
-    m_pfDownsample.pfOneThirdDownsampler ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1],
-                                          (uint8_t*)pSrcPixMap->pPixel[1], pSrcPixMap->iStride[1], iSrcWidthUV, iDstHeightUV);
+      m_pfDownsample.pfOneThirdDownsampler ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2],
+                                            (uint8_t*)pSrcPixMap->pPixel[2], pSrcPixMap->iStride[2], iSrcWidthUV, iDstHeightUV);
 
-    m_pfDownsample.pfOneThirdDownsampler ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2],
-                                          (uint8_t*)pSrcPixMap->pPixel[2], pSrcPixMap->iStride[2], iSrcWidthUV, iDstHeightUV);
+    } else {
+      m_pfDownsample.pfGeneralRatioLuma ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0], iDstWidthY, iDstHeightY,
+                                         (uint8_t*)pSrcPixMap->pPixel[0], pSrcPixMap->iStride[0], iSrcWidthY, iSrcHeightY);
 
+      m_pfDownsample.pfGeneralRatioChroma ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1], iDstWidthUV, iDstHeightUV,
+                                           (uint8_t*)pSrcPixMap->pPixel[1], pSrcPixMap->iStride[1], iSrcWidthUV, iSrcHeightUV);
+
+      m_pfDownsample.pfGeneralRatioChroma ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2], iDstWidthUV, iDstHeightUV,
+                                           (uint8_t*)pSrcPixMap->pPixel[2], pSrcPixMap->iStride[2], iSrcWidthUV, iSrcHeightUV);
+    }
   } else {
-    m_pfDownsample.pfGeneralRatioLuma ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0], iDstWidthY, iDstHeightY,
-                                       (uint8_t*)pSrcPixMap->pPixel[0], pSrcPixMap->iStride[0], iSrcWidthY, iSrcHeightY);
 
-    m_pfDownsample.pfGeneralRatioChroma ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1], iDstWidthUV, iDstHeightUV,
-                                         (uint8_t*)pSrcPixMap->pPixel[1], pSrcPixMap->iStride[1], iSrcWidthUV, iSrcHeightUV);
+    int32_t iIdx = 0;
+    int32_t iHalfSrcWidth = iSrcWidthY >> 1;
+    int32_t iHalfSrcHeight = iSrcHeightY >> 1;
+    uint8_t* pSrcY = (uint8_t*)pSrcPixMap->pPixel[0];
+    uint8_t* pSrcU = (uint8_t*)pSrcPixMap->pPixel[1];
+    uint8_t* pSrcV = (uint8_t*)pSrcPixMap->pPixel[2];
+    int32_t iSrcStrideY = pSrcPixMap->iStride[0];
+    int32_t iSrcStrideU = pSrcPixMap->iStride[1];
+    int32_t iSrcStrideV = pSrcPixMap->iStride[2];
 
-    m_pfDownsample.pfGeneralRatioChroma ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2], iDstWidthUV, iDstHeightUV,
-                                         (uint8_t*)pSrcPixMap->pPixel[2], pSrcPixMap->iStride[2], iSrcWidthUV, iSrcHeightUV);
+    int32_t iDstStrideY = pDstPixMap->iStride[0];
+    int32_t iDstStrideU = pDstPixMap->iStride[1];
+    int32_t iDstStrideV = pDstPixMap->iStride[2];
+
+    uint8_t* pDstY = (uint8_t*)m_pSampleBuffer[iIdx][0];
+    uint8_t* pDstU = (uint8_t*)m_pSampleBuffer[iIdx][1];
+    uint8_t* pDstV = (uint8_t*)m_pSampleBuffer[iIdx][2];
+    iIdx++;
+    do {
+      if ((iHalfSrcWidth == iDstWidthY) && (iHalfSrcHeight == iDstHeightY)) { //end
+        // use half average functions
+        uint8_t iAlignIndex = GetAlignedIndex (iSrcWidthY);
+        m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0],
+            (uint8_t*)pSrcY, iSrcStrideY, iSrcWidthY, iSrcHeightY);
+
+        iAlignIndex = GetAlignedIndex (iSrcWidthUV);
+        m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1],
+            (uint8_t*)pSrcU, iSrcStrideU, iSrcWidthUV, iSrcHeightUV);
+        m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2],
+            (uint8_t*)pSrcV, iSrcStrideV, iSrcWidthUV, iSrcHeightUV);
+        break;
+      } else if (((iHalfSrcWidth >> 1) >= iDstWidthY) && ((iHalfSrcHeight >> 1) >= iDstHeightY)) {
+        // use half average functions
+        iDstStrideY = iHalfSrcWidth;
+        iDstStrideU = iHalfSrcWidth >> 1;
+        iDstStrideV = iHalfSrcWidth >> 1;
+        uint8_t iAlignIndex = GetAlignedIndex (iSrcWidthY);
+        m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstY, iDstStrideY,
+            (uint8_t*)pSrcY, iSrcStrideY, iSrcWidthY, iSrcHeightY);
+
+        iAlignIndex = GetAlignedIndex (iSrcWidthUV);
+        m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstU, iDstStrideU,
+            (uint8_t*)pSrcU, iSrcStrideU, iSrcWidthUV, iSrcHeightUV);
+        m_pfDownsample.pfHalfAverage[iAlignIndex] ((uint8_t*)pDstV, iDstStrideV,
+            (uint8_t*)pSrcV, iSrcStrideV, iSrcWidthUV, iSrcHeightUV);
+
+        pSrcY = (uint8_t*)pDstY;
+        pSrcU = (uint8_t*)pDstU;
+        pSrcV = (uint8_t*)pDstV;
+
+
+        iSrcWidthY = iHalfSrcWidth;
+        iSrcWidthUV = iHalfSrcWidth >> 1;
+        iSrcHeightY = iHalfSrcHeight;
+        iSrcHeightUV = iHalfSrcHeight >> 1;
+
+        iSrcStrideY = iSrcWidthY;
+        iSrcStrideU = iSrcWidthUV;
+        iSrcStrideV = iSrcWidthUV;
+
+        iHalfSrcWidth >>= 1;
+        iHalfSrcHeight >>= 1;
+
+        iIdx = iIdx % 2;
+        pDstY = (uint8_t*)m_pSampleBuffer[iIdx][0];
+        pDstU = (uint8_t*)m_pSampleBuffer[iIdx][1];
+        pDstV = (uint8_t*)m_pSampleBuffer[iIdx][2];
+        iIdx++;
+      } else {
+        m_pfDownsample.pfGeneralRatioLuma ((uint8_t*)pDstPixMap->pPixel[0], pDstPixMap->iStride[0], iDstWidthY, iDstHeightY,
+                                           (uint8_t*)pSrcY, iSrcStrideY, iSrcWidthY, iSrcHeightY);
+
+        m_pfDownsample.pfGeneralRatioChroma ((uint8_t*)pDstPixMap->pPixel[1], pDstPixMap->iStride[1], iDstWidthUV, iDstHeightUV,
+                                             (uint8_t*)pSrcU, iSrcStrideU,  iSrcWidthUV, iSrcHeightUV);
+
+        m_pfDownsample.pfGeneralRatioChroma ((uint8_t*)pDstPixMap->pPixel[2], pDstPixMap->iStride[2], iDstWidthUV, iDstHeightUV,
+                                             (uint8_t*)pSrcV, iSrcStrideV, iSrcWidthUV, iSrcHeightUV);
+        break;
+      }
+    } while (true);
   }
   return RET_SUCCESS;
 }
--- a/codec/processing/src/downsample/downsample.h
+++ b/codec/processing/src/downsample/downsample.h
@@ -170,10 +170,13 @@
   void InitDownsampleFuncs (SDownsampleFuncs& sDownsampleFunc, int32_t iCpuFlag);
 
   int32_t GetAlignedIndex (const int32_t kiSrcWidth);
-
+  bool AllocateSampleBuffer();
+  void FreeSampleBuffer();
  private:
   SDownsampleFuncs m_pfDownsample;
   int32_t  m_iCPUFlag;
+  uint8_t  *m_pSampleBuffer[2][3];
+  bool     m_bNoSampleBuffer;
 };
 
 WELSVP_NAMESPACE_END
--- a/test/api/encode_options_test.cpp
+++ b/test/api/encode_options_test.cpp
@@ -385,7 +385,7 @@
   //prepare output if needed
   FILE* fEnc =  NULL;
 #ifdef DEBUG_FILE_SAVE_INCREASING_ID
-  fEnc = fopen ("enc_i.264", "wb");
+  fEnc = fopen ("enc_INCREASING_ID.264", "wb");
 #endif
 
   // Test part#1
@@ -440,7 +440,7 @@
   ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam3: rv = " << rv;
 
 #ifdef DEBUG_FILE_SAVE_INCREASING_ID
-  fEnc = fopen ("enc3.264", "wb");
+  fEnc = fopen ("enc_INCREASING_ID2.264", "wb");
 #endif
   iEncFrameNum = 0;
   EncDecOneFrame (sParam3.iPicWidth, sParam3.iPicHeight, iEncFrameNum++, fEnc);
@@ -495,7 +495,7 @@
   //prepare output if needed
   FILE* fEnc =  NULL;
 #ifdef DEBUG_FILE_SAVE2
-  fEnc = fopen ("enc2.264", "wb");
+  fEnc = fopen ("enc_SPS_LISTING_AND_PPS_INCREASING1.264", "wb");
 #endif
 
   // Test part#1
@@ -550,7 +550,7 @@
   ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam3: rv = " << rv;
 
 #ifdef DEBUG_FILE_SAVE2
-  fEnc = fopen ("enc3.264", "wb");
+  fEnc = fopen ("enc_SPS_LISTING_AND_PPS_INCREASING11.264", "wb");
 #endif
   iEncFrameNum = 0;
   EncDecOneFrame (sParam3.iPicWidth, sParam3.iPicHeight, iEncFrameNum++, fEnc);
@@ -598,7 +598,7 @@
   //prepare output if needed
   FILE* fEnc =  NULL;
 #ifdef DEBUG_FILE_SAVE5
-  fEnc = fopen ("encID2.264", "wb");
+  fEnc = fopen ("enc_SPS_LISTING_AND_PPS_INCREASING2.264", "wb");
 #endif
 
   // step#1: pParam1
@@ -647,7 +647,7 @@
   //prepare output if needed
   FILE* fEnc =  NULL;
 #ifdef DEBUG_FILE_SAVE2
-  fEnc = fopen ("enc4.264", "wb");
+  fEnc = fopen ("enc_SPS_LISTING_AND_PPS_INCREASING3.264", "wb");
 #endif
 
   // step#1: pParam1
@@ -853,7 +853,7 @@
   //prepare output if needed
   FILE* fEnc =  NULL;
 #ifdef DEBUG_FILE_SAVE5
-  fEnc = fopen ("enc4.264", "wb");
+  fEnc = fopen ("enc_LISTING3.264", "wb");
 #endif
 
   // step#1: ordinary encoding
--- a/test/encoder/EncUT_ParameterSetStrategy.cpp
+++ b/test/encoder/EncUT_ParameterSetStrategy.cpp
@@ -5,6 +5,7 @@
 #include "param_svc.h"
 #include "parameter_sets.h"
 #include "wels_const.h"
+#include "paraset_strategy.h"
 
 using namespace WelsEnc;