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;