diff --git a/codec/build/iOS/enc/welsenc/welsenc.xcodeproj/project.pbxproj b/codec/build/iOS/enc/welsenc/welsenc.xcodeproj/project.pbxproj index 1ebc15a5..5cfc59ed 100644 --- 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 = ""; }; + 0D6970BC1CA5BCFB001D88F8 /* paraset_strategy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = paraset_strategy.cpp; sourceTree = ""; }; + 0D6970BF1CA5BD26001D88F8 /* paraset_strategy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = paraset_strategy.h; sourceTree = ""; }; 0DD32A951B4A478B009181A1 /* wels_task_base.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wels_task_base.cpp; sourceTree = ""; }; 0DD32A971B4A47D0009181A1 /* wels_task_base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wels_task_base.h; sourceTree = ""; }; 0DD32A981B4A4997009181A1 /* wels_task_management.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wels_task_management.cpp; sourceTree = ""; }; @@ -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; }; diff --git a/codec/build/win32/enc/WelsEncCore.vcproj b/codec/build/win32/enc/WelsEncCore.vcproj index 0ebd15a9..b30272d7 100644 --- a/codec/build/win32/enc/WelsEncCore.vcproj +++ b/codec/build/win32/enc/WelsEncCore.vcproj @@ -405,6 +405,10 @@ RelativePath="..\..\..\encoder\core\src\nal_encap.cpp" > + + @@ -618,6 +622,10 @@ RelativePath="..\..\..\encoder\core\inc\parameter_sets.h" > + + diff --git a/codec/encoder/core/inc/au_set.h b/codec/encoder/core/inc/au_set.h index 8478ef8a..4f69b52f 100644 --- 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 @@ int32_t WelsWriteSubsetSpsSyntax (SSubsetSps* pSubsetSps, SBitStringAux* pBitStr * \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 WelsCheckRefFrameLimitationLevelIdcFirst (SLogContext* pLogCtx, SWelsSvc 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__ diff --git a/codec/encoder/core/inc/encoder_context.h b/codec/encoder/core/inc/encoder_context.h index 9ec1c2c0..636ba682 100644 --- 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" @@ -61,7 +62,6 @@ namespace WelsEnc { -class IWelsTaskManage; /* * reference list for each quality layer in SVC */ @@ -236,30 +236,7 @@ typedef struct TagWelsEncCtx { 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__ diff --git a/codec/encoder/core/inc/paraset_strategy.h b/codec/encoder/core/inc/paraset_strategy.h new file mode 100644 index 00000000..77a83570 --- /dev/null +++ b/codec/encoder/core/inc/paraset_strategy.h @@ -0,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 diff --git a/codec/encoder/core/inc/wels_func_ptr_def.h b/codec/encoder/core/inc/wels_func_ptr_def.h index 4724d441..e591f9d2 100644 --- 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 int32_t (*PWelsSpatialWriteMbSyn) (sWelsEncCtx* pCtx, SSlice* pSlice, SM 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; @@ -294,6 +296,8 @@ struct TagWelsFuncPointerList { PWelsSpatialWriteMbSyn pfWelsSpatialWriteMbSyn; PStashMBStatus pfStashMBStatus; PStashPopMBStatus pfStashPopMBStatus; + + IWelsParametersetStrategy* pParametersetStrategy; }; } //end of namespace WelsEnc { diff --git a/codec/encoder/core/src/au_set.cpp b/codec/encoder/core/src/au_set.cpp index eea37b67..b9605db6 100644 --- a/codec/encoder/core/src/au_set.cpp +++ b/codec/encoder/core/src/au_set.cpp @@ -380,29 +380,12 @@ int32_t WelsWriteSubsetSpsSyntax (SSubsetSps* pSubsetSps, SBitStringAux* pBitStr * \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*/); diff --git a/codec/encoder/core/src/encoder.cpp b/codec/encoder/core/src/encoder.cpp index c21f792c..48c89d77 100644 --- 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" @@ -223,6 +224,10 @@ int32_t InitFunctionPointers (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* pParam, InitRefListMgrFunc (pFuncList, pParam->bEnableLongTermReference, bScreenContent); + pFuncList->pParametersetStrategy = IWelsParametersetStrategy::CreateParametersetStrategy (pParam->eSpsPpsIdStrategy, + pParam->bSimulcastAVC, pParam->iSpatialLayerNum); + WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, (NULL == pFuncList->pParametersetStrategy)) + return iReturn; } diff --git a/codec/encoder/core/src/encoder_ext.cpp b/codec/encoder/core/src/encoder_ext.cpp index e069d667..04e2f3ed 100644 --- a/codec/encoder/core/src/encoder_ext.cpp +++ b/codec/encoder/core/src/encoder_ext.cpp @@ -767,12 +767,15 @@ static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingPara ++ 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,152 +959,7 @@ void FreeRefList (SRefList*& pRefList, CMemoryAlign* pMa, const int iMaxNumRefF 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, @@ -1248,7 +1106,7 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p 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 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p } // 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 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p (*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,79 +1280,18 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p && (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); - - - 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); - } - } + iPpsId = (*ppCtx)->pFuncList->pParametersetStrategy->InitPps ((*ppCtx), iSpsId, pSps, pSubsetSps, iPpsId, true, + bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0); + pPps = & ((*ppCtx)->pPPSArray[iPpsId]); // Not using FMO in SVC coding so far, come back if need FMO { @@ -1533,8 +1311,6 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p pDqIdc->iSpsId = iSpsId; pDqIdc->iPpsId = iPpsId; - (*ppCtx)->sPSOVector.bPpsIdMappingIntoSubsetsps[iPpsId] = bUseSubsetSps; - if ((pParam->bSimulcastAVC) || (bUseSubsetSps)) ++ iSpsId; ++ iPpsId; @@ -1547,13 +1323,8 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p ++ 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 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingPa 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; @@ -2309,6 +2080,10 @@ void FreeMemorySvc (sWelsEncCtx** ppCtx) { 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; } @@ -2860,9 +2635,8 @@ void WelsInitCurrentLayer (sWelsEncCtx* pCtx, 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 = @@ -3141,45 +2915,12 @@ static inline void PrefetchReferencePicture (sWelsEncCtx* pCtx, const EVideoFram } } - -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, @@ -3197,8 +2938,9 @@ int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNa 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, @@ -3211,43 +2953,6 @@ int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNa 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 @@ -3262,22 +2967,16 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN 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; /* 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); @@ -3293,11 +2992,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN 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; @@ -3305,7 +3000,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN 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, @@ -3322,16 +3017,11 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN ++ 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); @@ -3545,10 +3235,9 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t iIdx, 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); @@ -3582,10 +3271,8 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t iIdx, 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); @@ -3659,9 +3346,7 @@ int32_t WriteSavcParaset_Listing (sWelsEncCtx* pCtx, const int32_t kiSpatialNum, } // 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++) { @@ -4652,46 +4337,16 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa 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 */ @@ -4704,14 +4359,10 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa //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.. */ diff --git a/codec/encoder/core/src/paraset_strategy.cpp b/codec/encoder/core/src/paraset_strategy.cpp new file mode 100644 index 00000000..be30a4e2 --- /dev/null +++ b/codec/encoder/core/src/paraset_strategy.cpp @@ -0,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.SpsPpsIdStrategy = 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); +} +} diff --git a/codec/encoder/core/src/svc_encode_slice.cpp b/codec/encoder/core/src/svc_encode_slice.cpp index b53e5227..6a6417b6 100644 --- a/codec/encoder/core/src/svc_encode_slice.cpp +++ b/codec/encoder/core/src/svc_encode_slice.cpp @@ -52,7 +52,7 @@ namespace WelsEnc { 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 WriteRefPicMarking (SBitStringAux* pBs, SSliceHeader* pSliceHeader, SNalUni } 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 @@ void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCur 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 WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCur } 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 @@ void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* p 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 @@ int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const 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; diff --git a/codec/encoder/targets.mk b/codec/encoder/targets.mk index b671d12b..21b56931 100644 --- a/codec/encoder/targets.mk +++ b/codec/encoder/targets.mk @@ -11,6 +11,7 @@ ENCODER_CPP_SRCS=\ $(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\ diff --git a/test/api/encode_options_test.cpp b/test/api/encode_options_test.cpp index 923fd776..a13a8355 100644 --- a/test/api/encode_options_test.cpp +++ b/test/api/encode_options_test.cpp @@ -385,7 +385,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_INCREASING_ID) { //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 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_INCREASING_ID) { 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 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING //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 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING 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 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING //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 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING //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 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING3) { //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 diff --git a/test/encoder/EncUT_ParameterSetStrategy.cpp b/test/encoder/EncUT_ParameterSetStrategy.cpp index 78492cf6..8d0f4b15 100644 --- 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;