fix conflict with master

This commit is contained in:
sijchen 2016-05-18 10:57:39 -07:00
commit 1ac02f3002
17 changed files with 1300 additions and 549 deletions

View File

@ -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;
};

View File

@ -405,6 +405,10 @@
RelativePath="..\..\..\encoder\core\src\nal_encap.cpp"
>
</File>
<File
RelativePath="..\..\..\encoder\core\src\paraset_strategy.cpp"
>
</File>
<File
RelativePath="..\..\..\encoder\core\src\picture_handle.cpp"
>
@ -618,6 +622,10 @@
RelativePath="..\..\..\encoder\core\inc\parameter_sets.h"
>
</File>
<File
RelativePath="..\..\..\encoder\core\inc\paraset_strategy.h"
>
</File>
<File
RelativePath="..\..\..\encoder\core\inc\picture.h"
>

View File

@ -934,14 +934,16 @@ int32_t ParseResidualBlockCabac (PWelsNeighAvail pNeighAvail, uint8_t* pNonZeroC
} 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);
} 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);

View File

@ -43,6 +43,7 @@
#define WELS_ACCESS_UNIT_WRITER_H__
#include "parameter_sets.h"
#include "paraset_strategy.h"
#include "param_svc.h"
#include "utils.h"
namespace WelsEnc {
@ -92,7 +93,7 @@ int32_t WelsWriteSubsetSpsSyntax (SSubsetSps* pSubsetSps, SBitStringAux* pBitStr
* \note Call it in case EWelsNalUnitType is PPS.
*************************************************************************************
*/
int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, SParaSetOffset* sPSOVector);
int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, IWelsParametersetStrategy* pParametersetStrategy);
/*!
* \brief initialize pSps based on configurable parameters in svc
@ -147,21 +148,5 @@ int32_t WelsCheckRefFrameLimitationLevelIdcFirst (SLogContext* pLogCtx, SWelsSvc
int32_t WelsAdjustLevel (SSpatialLayerConfig* pSpatialLayer);
/*!
* \brief check if the current parameter can found a presenting sps
* \param pParam the current encoding paramter in SWelsSvcCodingParam
* \param kbUseSubsetSps bool
* \param iDlayerIndex int, the index of current D layer
* \param iDlayerCount int, the number of total D layer
* \param pSpsArray array of all the stored SPSs
* \param pSubsetArray array of all the stored Subset-SPSs
* \return 0 - successful
* -1 - cannot find existing SPS for current encoder parameter
*/
int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, const int32_t iSpsNumInUse,
SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray,
bool bSVCBaselayer);
}
#endif//WELS_ACCESS_UNIT_PARSER_H__

View File

@ -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 @@ namespace WelsEnc {
class IWelsTaskManage;
class IWelsReferenceStrategy;
/*
* reference list for each quality layer in SVC
*/
@ -238,30 +240,7 @@ typedef struct TagWelsEncCtx {
bool bRecFlag;
#endif
int64_t uiLastTimestamp;
uint32_t GetNeededSpsNum() {
if (0 == sPSOVector.uiNeededSpsNum) {
sPSOVector.uiNeededSpsNum = ((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (1));
sPSOVector.uiNeededSpsNum *= ((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1));
}
return sPSOVector.uiNeededSpsNum;
}
uint32_t GetNeededSubsetSpsNum() {
if (0 == sPSOVector.uiNeededSubsetSpsNum) {
sPSOVector.uiNeededSubsetSpsNum = ((pSvcParam->bSimulcastAVC) ? (0) :
((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (pSvcParam->iSpatialLayerNum - 1)));
}
return sPSOVector.uiNeededSubsetSpsNum;
}
uint32_t GetNeededPpsNum() {
if (0 == sPSOVector.uiNeededPpsNum) {
sPSOVector.uiNeededPpsNum = ((pSvcParam->eSpsPpsIdStrategy & SPS_PPS_LISTING) ? (MAX_PPS_COUNT) :
(1 + pSvcParam->iSpatialLayerNum));
sPSOVector.uiNeededPpsNum *= ((pSvcParam->bSimulcastAVC) ? (pSvcParam->iSpatialLayerNum) : (1));
}
return sPSOVector.uiNeededPpsNum;
}
} sWelsEncCtx/*, *PWelsEncCtx*/;
}
#endif//sWelsEncCtx_H__

View File

@ -0,0 +1,310 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef WELS_PARASET_STRATEGY_H
#define WELS_PARASET_STRATEGY_H
#include "param_svc.h"
#include "utils.h"
namespace WelsEnc {
class IWelsParametersetStrategy {
public:
virtual ~IWelsParametersetStrategy() { }
static IWelsParametersetStrategy* CreateParametersetStrategy (EParameterSetStrategy eSpsPpsIdStrategy,
const bool bSimulcastAVC, const int32_t kiSpatialLayerNum);
//virtual SParaSetOffset* GetParaSetOffset() = 0;
virtual int32_t GetPpsIdOffset (const int32_t iPpsId) = 0;
virtual int32_t GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId) = 0;
virtual int32_t* GetSpsIdOffsetList (const int iParasetType) = 0;
virtual uint32_t GetAllNeededParasetNum() = 0;
virtual uint32_t GetNeededSpsNum() = 0;
virtual uint32_t GetNeededSubsetSpsNum() = 0;
virtual uint32_t GetNeededPpsNum() = 0;
virtual void LoadPrevious (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray,
SWelsPPS* pPpsArray) = 0;
virtual void Update (const uint32_t kuiId, const int iParasetType) = 0;
virtual void UpdatePpsList (sWelsEncCtx* pCtx) = 0;
virtual bool CheckParamCompatibility (SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) = 0;
virtual uint32_t GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount,
uint32_t kuiSpsId,
SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) = 0;
virtual uint32_t InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
SWelsSPS* pSps,
SSubsetSps* pSubsetSps,
uint32_t kuiPpsId,
const bool kbDeblockingFilterPresentFlag,
const bool kbUsingSubsetSps,
const bool kbEntropyCodingModeFlag) = 0;
virtual void SetUseSubsetFlag (const uint32_t iPpsId, const bool bUseSubsetSps) = 0;
virtual void UpdateParaSetNum (sWelsEncCtx* pCtx) = 0;
virtual int32_t GetCurrentPpsId (const int32_t iPpsId, const int32_t iIdrLoop) = 0;
virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) = 0;
virtual void LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList) = 0;
virtual int32_t GetSpsIdx (const int32_t iIdx) = 0;
};
class CWelsParametersetIdConstant : public IWelsParametersetStrategy {
public:
CWelsParametersetIdConstant (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum);
virtual ~ CWelsParametersetIdConstant();
virtual int32_t GetPpsIdOffset (const int32_t iPpsId);
virtual int32_t GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId);
int32_t* GetSpsIdOffsetList (const int iParasetType);
uint32_t GetAllNeededParasetNum();
virtual uint32_t GetNeededSpsNum();
virtual uint32_t GetNeededSubsetSpsNum();
virtual uint32_t GetNeededPpsNum();
virtual void LoadPrevious (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray,
SWelsPPS* pPpsArray);
virtual void Update (const uint32_t kuiId, const int iParasetType);
virtual void UpdatePpsList (sWelsEncCtx* pCtx) {};
bool CheckParamCompatibility (SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) {
return true;
};
virtual uint32_t GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, uint32_t kuiSpsId,
SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer);
virtual uint32_t InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
SWelsSPS* pSps,
SSubsetSps* pSubsetSps,
uint32_t kuiPpsId,
const bool kbDeblockingFilterPresentFlag,
const bool kbUsingSubsetSps,
const bool kbEntropyCodingModeFlag);
virtual void SetUseSubsetFlag (const uint32_t iPpsId, const bool bUseSubsetSps);
virtual void UpdateParaSetNum (sWelsEncCtx* pCtx) {};
virtual int32_t GetCurrentPpsId (const int32_t iPpsId, const int32_t iIdrLoop) {
return iPpsId;
};
virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
sWelsEncCtx* pCtx,
SExistingParasetList* pExistingParasetList) {};
virtual void LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList) {};
virtual int32_t GetSpsIdx (const int32_t iIdx) {
return 0;
};
protected:
virtual void LoadPreviousSps (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray) {};
virtual void LoadPreviousPps (SExistingParasetList* pExistingParasetList, SWelsPPS* pPpsArray) {};
protected:
SParaSetOffset m_sParaSetOffset;
bool m_bSimulcastAVC;
int32_t m_iSpatialLayerNum;
uint32_t m_iBasicNeededSpsNum;
uint32_t m_iBasicNeededPpsNum;
};
/*
typedef struct TagParaSetOffsetVariable {
int32_t iParaSetIdDelta[MAX_DQ_LAYER_NUM+1];//mark delta between SPS_ID_in_bs and sps_id_in_encoder, can be minus, for each dq-layer
//need not extra +1 due no MGS and FMO case so far
bool bUsedParaSetIdInBs[MAX_PPS_COUNT]; //mark the used SPS_ID with 1
uint32_t uiNextParaSetIdToUseInBs; //mark the next SPS_ID_in_bs, for all layers
} SParaSetOffsetVariable;
typedef struct TagParaSetOffset {
//in PS0 design, "sParaSetOffsetVariable" record the previous paras before current IDR, AND NEED to be stacked and recover across IDR
SParaSetOffsetVariable
sParaSetOffsetVariable[PARA_SET_TYPE]; //PARA_SET_TYPE=3; paraset_type = 0: AVC_SPS; =1: Subset_SPS; =2: PPS
//in PSO design, "bPpsIdMappingIntoSubsetsps" uses the current para of current IDR period
bool
bPpsIdMappingIntoSubsetsps[MAX_DQ_LAYER_NUM+1]; // need not extra +1 due no MGS and FMO case so far
int32_t iPpsIdList[MAX_DQ_LAYER_NUM][MAX_PPS_COUNT]; //index0: max pps types; index1: for differnt IDRs, if only index0=1, index1 can reach MAX_PPS_COUNT
//#if _DEBUG
int32_t eSpsPpsIdStrategy;
//#endif
uint32_t uiNeededSpsNum;
uint32_t uiNeededSubsetSpsNum;
uint32_t uiNeededPpsNum;
uint32_t uiInUseSpsNum;
uint32_t uiInUseSubsetSpsNum;
uint32_t uiInUsePpsNum;
} SParaSetOffset;
*/
class CWelsParametersetIdNonConstant : public CWelsParametersetIdConstant {
public:
CWelsParametersetIdNonConstant (const bool bSimulcastAVC,
const int32_t kiSpatialLayerNum): CWelsParametersetIdConstant (bSimulcastAVC, kiSpatialLayerNum) {};
virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
sWelsEncCtx* pCtx,
SExistingParasetList* pExistingParasetList);
virtual void LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList);
};
class CWelsParametersetIdIncreasing : public CWelsParametersetIdNonConstant {
public:
CWelsParametersetIdIncreasing (const bool bSimulcastAVC,
const int32_t kiSpatialLayerNum): CWelsParametersetIdNonConstant (bSimulcastAVC, kiSpatialLayerNum) {};
virtual int32_t GetPpsIdOffset (const int32_t iPpsId);
virtual int32_t GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId);
virtual void Update (const uint32_t kuiId, const int iParasetType);
protected:
//void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable, const int32_t kiCurEncoderParaSetId,
// const uint32_t kuiMaxIdInBs);
private:
void DebugPps (const int32_t kiPpsId);
void DebugSpsPps (const int32_t iPpsId, const int32_t iSpsId);
};
class CWelsParametersetSpsListing : public CWelsParametersetIdNonConstant {
public:
CWelsParametersetSpsListing (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum);
virtual uint32_t GetNeededSubsetSpsNum();
virtual void LoadPrevious (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray,
SWelsPPS* pPpsArray);
bool CheckParamCompatibility (SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx);
virtual uint32_t GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, uint32_t kuiSpsId,
SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer);
virtual void UpdateParaSetNum (sWelsEncCtx* pCtx);
int32_t GetSpsIdx (const int32_t iIdx) {
return iIdx;
};
virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
sWelsEncCtx* pCtx,
SExistingParasetList* pExistingParasetList);
protected:
virtual void LoadPreviousSps (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray);
virtual bool CheckPpsGenerating();
virtual int32_t SpsReset (sWelsEncCtx* pCtx, bool kbUseSubsetSps);
};
class CWelsParametersetSpsPpsListing : public CWelsParametersetSpsListing {
public:
CWelsParametersetSpsPpsListing (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum);
//uint32_t GetNeededPpsNum();
virtual void UpdatePpsList (sWelsEncCtx* pCtx);
virtual uint32_t InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
SWelsSPS* pSps,
SSubsetSps* pSubsetSps,
uint32_t kuiPpsId,
const bool kbDeblockingFilterPresentFlag,
const bool kbUsingSubsetSps,
const bool kbEntropyCodingModeFlag);
virtual void UpdateParaSetNum (sWelsEncCtx* pCtx);
virtual int32_t GetCurrentPpsId (const int32_t iPpsId, const int32_t iIdrLoop);
virtual void OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList,
sWelsEncCtx* pCtx,
SExistingParasetList* pExistingParasetList);
virtual void LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable, int32_t* pPpsIdList);
protected:
virtual void LoadPreviousPps (SExistingParasetList* pExistingParasetList, SWelsPPS* pPpsArray);
virtual bool CheckPpsGenerating();
virtual int32_t SpsReset (sWelsEncCtx* pCtx, bool kbUseSubsetSps);
};
class CWelsParametersetSpsListingPpsIncreasing : public CWelsParametersetSpsListing {
public:
CWelsParametersetSpsListingPpsIncreasing (const bool bSimulcastAVC,
const int32_t kiSpatialLayerNum): CWelsParametersetSpsListing (bSimulcastAVC, kiSpatialLayerNum) {};
virtual int32_t GetPpsIdOffset (const int32_t kiPpsId);
virtual void Update (const uint32_t kuiId, const int iParasetType);
};
int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, const int32_t iSpsNumInUse,
SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray, bool bSVCBaseLayer);
}
#endif

View File

@ -193,6 +193,8 @@ typedef int32_t (*PWelsSpatialWriteMbSyn) (sWelsEncCtx* pCtx, SSlice* pSlice, SM
typedef void (*PStashMBStatus) (SDynamicSlicingStack* pDss, SSlice* pSlice, int32_t iMbSkipRun);
typedef int32_t (*PStashPopMBStatus) (SDynamicSlicingStack* pDss, SSlice* pSlice);
class IWelsParametersetStrategy;
struct TagWelsFuncPointerList {
SExpandPicFunc sExpandPicFunc;
PFillInterNeighborCacheFunc pfFillInterNeighborCache;
@ -288,6 +290,8 @@ struct TagWelsFuncPointerList {
PWelsSpatialWriteMbSyn pfWelsSpatialWriteMbSyn;
PStashMBStatus pfStashMBStatus;
PStashPopMBStatus pfStashPopMBStatus;
IWelsParametersetStrategy* pParametersetStrategy;
};
} //end of namespace WelsEnc {

View File

@ -380,29 +380,12 @@ int32_t WelsWriteSubsetSpsSyntax (SSubsetSps* pSubsetSps, SBitStringAux* pBitStr
* \note Call it in case EWelsNalUnitType is PPS.
*************************************************************************************
*/
int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, SParaSetOffset* pPSOVector) {
int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux,
IWelsParametersetStrategy* pParametersetStrategy) {
SBitStringAux* pLocalBitStringAux = pBitStringAux;
const int32_t kiParameterSetType = (pPSOVector != NULL) ? (pPSOVector->bPpsIdMappingIntoSubsetsps[pPps->iPpsId] ?
PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS) : 0;
BsWriteUE (pLocalBitStringAux, pPps->iPpsId
+ ((pPSOVector != NULL) ? (pPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId]) : 0));
BsWriteUE (pLocalBitStringAux, pPps->iSpsId
+ ((pPSOVector != NULL) ? (pPSOVector->sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[pPps->iSpsId]) : 0));
#if _DEBUG
//SParaSetOffset use, 110421
if ((pPSOVector != NULL) && (INCREASING_ID & pPSOVector->eSpsPpsIdStrategy)) {
const int32_t kiTmpSpsIdInBs = pPps->iSpsId +
pPSOVector->sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[pPps->iSpsId];
const int32_t tmp_pps_id_in_bs = pPps->iPpsId +
pPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId];
assert (MAX_SPS_COUNT > kiTmpSpsIdInBs);
assert (MAX_PPS_COUNT > tmp_pps_id_in_bs);
assert (pPSOVector->sParaSetOffsetVariable[kiParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
}
#endif
BsWriteUE (pLocalBitStringAux, pPps->iPpsId + pParametersetStrategy->GetPpsIdOffset (pPps->iPpsId));
BsWriteUE (pLocalBitStringAux, pPps->iSpsId + pParametersetStrategy->GetSpsIdOffset (pPps->iPpsId, pPps->iSpsId));
BsWriteOneBit (pLocalBitStringAux, pPps->bEntropyCodingModeFlag);
BsWriteOneBit (pLocalBitStringAux, false/*pPps->bPicOrderPresentFlag*/);

View File

@ -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"
@ -221,6 +222,10 @@ int32_t InitFunctionPointers (sWelsEncCtx* pEncCtx, SWelsSvcCodingParam* pParam,
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;
}

View File

@ -767,12 +767,15 @@ static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingPara
++ iDIndex;
} while (iDIndex < iNumDependencyLayers);
if (NULL == (*ppCtx)->pFuncList || NULL == (*ppCtx)->pFuncList->pParametersetStrategy) {
WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
"AcquireLayersNals(), pFuncList and pParametersetStrategy needed to be initialized first!");
return 1;
}
// count parasets
iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) +
iCountNumLayers // plus iCountNumLayers for reserved application
+ (*ppCtx)->GetNeededSpsNum()
+ (*ppCtx)->GetNeededSubsetSpsNum()
+ (*ppCtx)->GetNeededPpsNum();
+ (*ppCtx)->pFuncList->pParametersetStrategy->GetAllNeededParasetNum();
// to check number of layers / nals / slices dependencies, 12/8/2010
if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) {
@ -956,152 +959,7 @@ void FreeRefList (SRefList*& pRefList, CMemoryAlign* pMa, const int iMaxNumRefF
pRefList = NULL;
}
static int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, const int32_t kiSpsId,
SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) {
int32_t iRet = 0;
if (!kbUseSubsetSps) {
pSps = & (pCtx->pSpsArray[kiSpsId]);
} else {
pSubsetSps = & (pCtx->pSubsetArray[kiSpsId]);
pSps = &pSubsetSps->pSps;
}
SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
// Need port pSps/pPps initialization due to spatial scalability changed
if (!kbUseSubsetSps) {
iRet = WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
bSVCBaselayer);
} else {
iRet = WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
}
return iRet;
}
static bool CheckMatchedSps (SWelsSPS* const pSps1, SWelsSPS* const pSps2) {
if ((pSps1->iMbWidth != pSps2->iMbWidth)
|| (pSps1->iMbHeight != pSps2->iMbHeight)) {
return false;
}
if ((pSps1->uiLog2MaxFrameNum != pSps2->uiLog2MaxFrameNum)
|| (pSps1->iLog2MaxPocLsb != pSps2->iLog2MaxPocLsb)) {
return false;
}
if (pSps1->iNumRefFrames != pSps2->iNumRefFrames) {
return false;
}
if ((pSps1->bFrameCroppingFlag != pSps2->bFrameCroppingFlag)
|| (pSps1->sFrameCrop.iCropLeft != pSps2->sFrameCrop.iCropLeft)
|| (pSps1->sFrameCrop.iCropRight != pSps2->sFrameCrop.iCropRight)
|| (pSps1->sFrameCrop.iCropTop != pSps2->sFrameCrop.iCropTop)
|| (pSps1->sFrameCrop.iCropBottom != pSps2->sFrameCrop.iCropBottom)
) {
return false;
}
if ((pSps1->uiProfileIdc != pSps2->uiProfileIdc)
|| (pSps1->bConstraintSet0Flag != pSps2->bConstraintSet0Flag)
|| (pSps1->bConstraintSet1Flag != pSps2->bConstraintSet1Flag)
|| (pSps1->bConstraintSet2Flag != pSps2->bConstraintSet2Flag)
|| (pSps1->bConstraintSet3Flag != pSps2->bConstraintSet3Flag)
|| (pSps1->iLevelIdc != pSps2->iLevelIdc)) {
return false;
}
return true;
}
static bool CheckMatchedSubsetSps (SSubsetSps* const pSubsetSps1, SSubsetSps* const pSubsetSps2) {
if (!CheckMatchedSps (&pSubsetSps1->pSps, &pSubsetSps2->pSps)) {
return false;
}
if ((pSubsetSps1->sSpsSvcExt.iExtendedSpatialScalability != pSubsetSps2->sSpsSvcExt.iExtendedSpatialScalability)
|| (pSubsetSps1->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag)
|| (pSubsetSps1->sSpsSvcExt.bSeqTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bSeqTcoeffLevelPredFlag)
|| (pSubsetSps1->sSpsSvcExt.bSliceHeaderRestrictionFlag != pSubsetSps2->sSpsSvcExt.bSliceHeaderRestrictionFlag)) {
return false;
}
return true;
}
int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, const int32_t iSpsNumInUse,
SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray, bool bSVCBaseLayer) {
SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
assert (iSpsNumInUse <= MAX_SPS_COUNT);
if (!kbUseSubsetSps) {
SWelsSPS sTmpSps;
WelsInitSps (&sTmpSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
bSVCBaseLayer);
for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
if (CheckMatchedSps (&sTmpSps, &pSpsArray[iId])) {
return iId;
}
}
} else {
SSubsetSps sTmpSubsetSps;
WelsInitSubsetSps (&sTmpSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
if (CheckMatchedSubsetSps (&sTmpSubsetSps, &pSubsetArray[iId])) {
return iId;
}
}
}
return INVALID_ID;
}
int32_t FindExistingPps (SWelsSPS* pSps, SSubsetSps* pSubsetSps, const bool kbUseSubsetSps, const int32_t iSpsId,
const bool kbEntropyCodingFlag, const int32_t iPpsNumInUse,
SWelsPPS* pPpsArray) {
#if !defined(DISABLE_FMO_FEATURE)
// feature not supported yet
return INVALID_ID;
#endif//!DISABLE_FMO_FEATURE
SWelsPPS sTmpPps;
WelsInitPps (&sTmpPps,
pSps,
pSubsetSps,
0,
true,
kbUseSubsetSps,
kbEntropyCodingFlag);
assert (iPpsNumInUse <= MAX_PPS_COUNT);
for (int32_t iId = 0; iId < iPpsNumInUse; iId++) {
if ((sTmpPps.iSpsId == pPpsArray[iId].iSpsId)
&& (sTmpPps.bEntropyCodingModeFlag == pPpsArray[iId].bEntropyCodingModeFlag)
&& (sTmpPps.iPicInitQp == pPpsArray[iId].iPicInitQp)
&& (sTmpPps.iPicInitQs == pPpsArray[iId].iPicInitQs)
&& (sTmpPps.uiChromaQpIndexOffset == pPpsArray[iId].uiChromaQpIndexOffset)
&& (sTmpPps.bDeblockingFilterControlPresentFlag == pPpsArray[iId].bDeblockingFilterControlPresentFlag)
) {
return iId;
}
}
return INVALID_ID;
}
static inline int32_t InitSliceList (sWelsEncCtx** ppCtx,
SDqLayer* pDqLayer,
@ -1248,7 +1106,7 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
CMemoryAlign* pMa = NULL;
int32_t iDlayerCount = 0;
int32_t iDlayerIndex = 0;
uint32_t iSpsId = 0;
int32_t iSpsId = 0;
uint32_t iPpsId = 0;
uint32_t iNumRef = 0;
int32_t iResult = 0;
@ -1388,8 +1246,10 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
}
// for dynamically malloc for parameter sets memory instead of maximal items for standard to reduce size, 3/18/2010
const int32_t kiNeededSpsNum = (*ppCtx)->GetNeededSpsNum();
const int32_t kiNeededSubsetSpsNum = (*ppCtx)->GetNeededSubsetSpsNum();
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pFuncList), FreeMemorySvc (ppCtx))
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pFuncList->pParametersetStrategy), FreeMemorySvc (ppCtx))
const int32_t kiNeededSpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSpsNum();
const int32_t kiNeededSubsetSpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSubsetSpsNum();
(*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMallocz (kiNeededSpsNum * sizeof (SWelsSPS), "pSpsArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
if (kiNeededSubsetSpsNum > 0) {
@ -1399,36 +1259,15 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
(*ppCtx)->pSubsetArray = NULL;
}
if ((SPS_LISTING & pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
(*ppCtx)->sPSOVector.uiInUseSpsNum = pExistingParasetList->uiInUseSpsNum;
memcpy ((*ppCtx)->pSpsArray, pExistingParasetList->sSps, MAX_SPS_COUNT * sizeof (SWelsSPS));
if (kiNeededSubsetSpsNum > 0) {
(*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = pExistingParasetList->uiInUseSubsetSpsNum;
memcpy ((*ppCtx)->pSubsetArray, pExistingParasetList->sSubsetSps, MAX_SPS_COUNT * sizeof (SSubsetSps));
} else {
(*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = 0;
}
}
// PPS
const int32_t kiNeededPpsNum = (*ppCtx)->GetNeededPpsNum();
const int32_t kiNeededPpsNum = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededPpsNum();
(*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMallocz (kiNeededPpsNum * sizeof (SWelsPPS), "pPPSArray");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
// copy from existing if the pointer exists
if ((SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
(*ppCtx)->sPSOVector.uiInUsePpsNum = pExistingParasetList->uiInUsePpsNum;
memcpy ((*ppCtx)->pPPSArray, pExistingParasetList->sPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
}
(*ppCtx)->pFuncList->pParametersetStrategy->LoadPrevious (pExistingParasetList, (*ppCtx)->pSpsArray,
(*ppCtx)->pSubsetArray, (*ppCtx)->pPPSArray);
if (INCREASING_ID & pParam->eSpsPpsIdStrategy) {
(*ppCtx)->pPSOVector = & ((*ppCtx)->sPSOVector);
} else {
(*ppCtx)->pPSOVector = NULL;
}
(*ppCtx)->pDqIdcMap = (SDqIdc*)pMa->WelsMallocz (iDlayerCount * sizeof (SDqIdc), "pDqIdcMap");
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pDqIdcMap), FreeMemorySvc (ppCtx))
@ -1441,79 +1280,18 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
&& (iDlayerIndex == BASE_DEPENDENCY_ID);
pDqIdc->uiSpatialId = iDlayerIndex;
if (! (SPS_LISTING & pParam->eSpsPpsIdStrategy)) {
WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
iDlayerCount, iSpsId, pSps, pSubsetSps, bSvcBaselayer);
iSpsId = (*ppCtx)->pFuncList->pParametersetStrategy->GenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
iDlayerCount, iSpsId, pSps, pSubsetSps, bSvcBaselayer);
WELS_VERIFY_RETURN_IF (ENC_RETURN_UNSUPPORTED_PARA, (0 > iSpsId))
if (!bUseSubsetSps) {
pSps = & ((*ppCtx)->pSpsArray[iSpsId]);
} else {
//SPS_LISTING_AND_PPS_INCREASING == pParam->eSpsPpsIdStrategy
//check if the current param can fit in an existing SPS
const int32_t kiFoundSpsId = FindExistingSps ((*ppCtx)->pSvcParam, bUseSubsetSps, iDlayerIndex, iDlayerCount,
bUseSubsetSps ? ((*ppCtx)->sPSOVector.uiInUseSubsetSpsNum) : ((*ppCtx)->sPSOVector.uiInUseSpsNum),
(*ppCtx)->pSpsArray,
(*ppCtx)->pSubsetArray, bSvcBaselayer);
if (INVALID_ID != kiFoundSpsId) {
//if yes, set pSps or pSubsetSps to it
iSpsId = kiFoundSpsId;
if (!bUseSubsetSps) {
pSps = & ((*ppCtx)->pSpsArray[kiFoundSpsId]);
} else {
pSubsetSps = & ((*ppCtx)->pSubsetArray[kiFoundSpsId]);
}
} else {
//if no, generate a new SPS as usual
if ((SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) && (MAX_PPS_COUNT <= (*ppCtx)->sPSOVector.uiInUsePpsNum)) {
//check if we can generate new SPS or not
WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
"InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
return ENC_RETURN_UNSUPPORTED_PARA;
}
iSpsId = (!bUseSubsetSps) ? ((*ppCtx)->sPSOVector.uiInUseSpsNum++) : ((*ppCtx)->sPSOVector.uiInUseSubsetSpsNum++);
if (iSpsId >= MAX_SPS_COUNT) {
if (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) {
WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
"InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
return ENC_RETURN_UNSUPPORTED_PARA;
}
// reset current list
if (!bUseSubsetSps) {
(*ppCtx)->sPSOVector.uiInUseSpsNum = 1;
memset ((*ppCtx)->pSpsArray, 0, MAX_SPS_COUNT * sizeof (SWelsSPS));
} else {
(*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = 1;
memset ((*ppCtx)->pSubsetArray, 0, MAX_SPS_COUNT * sizeof (SSubsetSps));
}
iSpsId = 0;
}
WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
iDlayerCount, iSpsId, pSps, pSubsetSps, bSvcBaselayer);
}
pSubsetSps = & ((*ppCtx)->pSubsetArray[iSpsId]);
}
if (! (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy)) {
pPps = & (*ppCtx)->pPPSArray[iPpsId];
// initialize pPps
WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
} else {
const int32_t kiFoundPpsId = FindExistingPps (pSps, pSubsetSps, bUseSubsetSps, iSpsId,
pParam->iEntropyCodingModeFlag != 0,
(*ppCtx)->sPSOVector.uiInUsePpsNum,
(*ppCtx)->pPPSArray);
if (INVALID_ID != kiFoundPpsId) {
//if yes, set pPps to it
iPpsId = kiFoundPpsId;
pPps = & ((*ppCtx)->pPPSArray[kiFoundPpsId]);
} else {
iPpsId = ((*ppCtx)->sPSOVector.uiInUsePpsNum++);
pPps = & (*ppCtx)->pPPSArray[iPpsId];
WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
}
}
iPpsId = (*ppCtx)->pFuncList->pParametersetStrategy->InitPps ((*ppCtx), iSpsId, pSps, pSubsetSps, iPpsId, true,
bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
pPps = & ((*ppCtx)->pPPSArray[iPpsId]);
// Not using FMO in SVC coding so far, come back if need FMO
{
@ -1533,8 +1311,6 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
pDqIdc->iSpsId = iSpsId;
pDqIdc->iPpsId = iPpsId;
(*ppCtx)->sPSOVector.bPpsIdMappingIntoSubsetsps[iPpsId] = bUseSubsetSps;
if ((pParam->bSimulcastAVC) || (bUseSubsetSps))
++ iSpsId;
++ iPpsId;
@ -1547,13 +1323,8 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* p
++ iDlayerIndex;
}
if (SPS_LISTING & pParam->eSpsPpsIdStrategy) {
(*ppCtx)->iSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
(*ppCtx)->iSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
}
if (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) {
(*ppCtx)->iPpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
}
(*ppCtx)->pFuncList->pParametersetStrategy->UpdateParaSetNum ((*ppCtx));
return ENC_RETURN_SUCCESS;
}
@ -1908,8 +1679,8 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingPa
return 1;
}
const int32_t kiSpsSize = (*ppCtx)->GetNeededSpsNum() * SPS_BUFFER_SIZE;
const int32_t kiPpsSize = (*ppCtx)->GetNeededPpsNum() * PPS_BUFFER_SIZE;
const int32_t kiSpsSize = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededSpsNum() * SPS_BUFFER_SIZE;
const int32_t kiPpsSize = (*ppCtx)->pFuncList->pParametersetStrategy->GetNeededPpsNum() * PPS_BUFFER_SIZE;
iNonVclLayersBsSizeCount = SSEI_BUFFER_SIZE + kiSpsSize + kiPpsSize;
bool bDynamicSlice = false;
@ -2316,6 +2087,10 @@ void FreeMemorySvc (sWelsEncCtx** ppCtx) {
FreeCodingParam (&pCtx->pSvcParam, pMa);
if (NULL != pCtx->pFuncList) {
if (NULL != pCtx->pFuncList->pParametersetStrategy) {
WELS_DELETE_OP (pCtx->pFuncList->pParametersetStrategy);
}
pMa->WelsFree (pCtx->pFuncList, "SWelsFuncPtrList");
pCtx->pFuncList = NULL;
}
@ -2867,9 +2642,8 @@ void WelsInitCurrentLayer (sWelsEncCtx* pCtx,
int32_t iCurPpsId = pDqIdc->iPpsId;
int32_t iCurSpsId = pDqIdc->iSpsId;
if (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) {
iCurPpsId = pCtx->sPSOVector.iPpsIdList[pDqIdc->iPpsId][WELS_ABS (pCtx->uiIdrPicId - 1) % MAX_PPS_COUNT];
}
iCurPpsId = pCtx->pFuncList->pParametersetStrategy->GetCurrentPpsId (iCurPpsId,
WELS_ABS (pCtx->uiIdrPicId - 1) % MAX_PPS_COUNT);
pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId = iCurPpsId;
pCurDq->sLayerInfo.pPpsP =
@ -3148,45 +2922,12 @@ static inline void PrefetchReferencePicture (sWelsEncCtx* pCtx, const EVideoFram
}
}
void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable, const int32_t kiCurEncoderParaSetId,
const uint32_t kuiMaxIdInBs) { //paraset_type = 0: SPS; =1: PPS
//SPS_ID in avc_sps and pSubsetSps will be different using this
//SPS_ID case example:
//1st enter: next_spsid_in_bs == 0; spsid == 0; delta==0; //actual spsid_in_bs == 0
//1st finish: next_spsid_in_bs == 1;
//2nd enter: next_spsid_in_bs == 1; spsid == 0; delta==1; //actual spsid_in_bs == 1
//2nd finish: next_spsid_in_bs == 2;
//31st enter: next_spsid_in_bs == 31; spsid == 0~2; delta==31~29; //actual spsid_in_bs == 31
//31st finish:next_spsid_in_bs == 0;
//31st enter: next_spsid_in_bs == 0; spsid == 0~2; delta==-2~0; //actual spsid_in_bs == 0
//31st finish:next_spsid_in_bs == 1;
const int32_t kiEncId = kiCurEncoderParaSetId;
uint32_t uiNextIdInBs = sParaSetOffsetVariable->uiNextParaSetIdToUseInBs;
//update current layer's pCodingParam
sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] = uiNextIdInBs -
kiEncId; //for current parameter set, change its id_delta
//write pso pData for next update:
sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] = true; // update current used_id
//prepare for next update:
// find the next avaibable iId
++uiNextIdInBs;
if (uiNextIdInBs >= kuiMaxIdInBs) {
uiNextIdInBs = 0;//ensure the SPS_ID wound not exceed MAX_SPS_COUNT
}
// update next_id
sParaSetOffsetVariable->uiNextParaSetIdToUseInBs = uiNextIdInBs;
}
int32_t WelsWriteOneSPS (sWelsEncCtx* pCtx, const int32_t kiSpsIdx, int32_t& iNalSize) {
int iNal = pCtx->pOut->iNalIndex;
WelsLoadNal (pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST);
WelsWriteSpsNal (&pCtx->pSpsArray[kiSpsIdx], &pCtx->pOut->sBsWrite,
& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS].iParaSetIdDelta[0]));
pCtx->pFuncList->pParametersetStrategy->GetSpsIdOffsetList (PARA_SET_TYPE_AVCSPS));
WelsUnloadNal (pCtx->pOut);
int32_t iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
@ -3204,8 +2945,9 @@ int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNa
int32_t iNal = pCtx->pOut->iNalIndex;
/* generate picture parameter set */
WelsLoadNal (pCtx->pOut, NAL_UNIT_PPS, NRI_PRI_HIGHEST);
WelsWritePpsSyntax (&pCtx->pPPSArray[kiPpsIdx], &pCtx->pOut->sBsWrite,
((SPS_PPS_LISTING != pCtx->pSvcParam->eSpsPpsIdStrategy)) ? (& (pCtx->sPSOVector)) : NULL);
pCtx->pFuncList->pParametersetStrategy);
WelsUnloadNal (pCtx->pOut);
int32_t iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
@ -3218,43 +2960,6 @@ int32_t WelsWriteOnePPS (sWelsEncCtx* pCtx, const int32_t kiPpsIdx, int32_t& iNa
return ENC_RETURN_SUCCESS;
}
void UpdatePpsList (sWelsEncCtx* pCtx) {
assert (pCtx->iPpsNum <= MAX_DQ_LAYER_NUM);
//Generate PPS LIST
int32_t iPpsId = 0, iUsePpsNum = pCtx->iPpsNum;
for (int32_t iIdrRound = 0; iIdrRound < MAX_PPS_COUNT; iIdrRound++) {
for (iPpsId = 0; iPpsId < pCtx->iPpsNum; iPpsId++) {
pCtx->sPSOVector.iPpsIdList[iPpsId][iIdrRound] = ((iIdrRound * iUsePpsNum + iPpsId) % MAX_PPS_COUNT);
}
}
for (iPpsId = iUsePpsNum; iPpsId < MAX_PPS_COUNT; iPpsId++) {
memcpy (& (pCtx->pPPSArray[iPpsId]), & (pCtx->pPPSArray[iPpsId % iUsePpsNum]), sizeof (SWelsPPS));
pCtx->pPPSArray[iPpsId].iPpsId = iPpsId;
pCtx->iPpsNum++;
}
assert (pCtx->iPpsNum == MAX_PPS_COUNT);
pCtx->sPSOVector.uiInUsePpsNum = pCtx->iPpsNum;
}
void UpdateSpsPpsIdStrategyWithIncreasingId (SParaSetOffset* pPSOVector, const uint32_t kuiId, const int iParasetType) {
#if _DEBUG
pPSOVector->eSpsPpsIdStrategy = INCREASING_ID;
assert (kuiId < MAX_DQ_LAYER_NUM);
#endif
ParasetIdAdditionIdAdjust (& (pPSOVector->sParaSetOffsetVariable[iParasetType]),
kuiId,
(iParasetType != PARA_SET_TYPE_PPS) ? MAX_SPS_COUNT : MAX_PPS_COUNT);
}
void UpdateSpsPpsIdStrategyWithConstantId (SParaSetOffset* pPSOVector, const uint32_t kuiId, const int iParasetType) {
memset (pPSOVector, 0, sizeof (SParaSetOffset));
}
/*!
* \brief write all parameter sets introduced in SVC extension
@ -3269,22 +2974,16 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
int32_t iNalLength = 0;
int32_t iReturn = ENC_RETURN_SUCCESS;
if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal)
if (NULL == pCtx || NULL == pNalLen || NULL == pNumNal || NULL == pCtx->pFuncList->pParametersetStrategy)
return ENC_RETURN_UNEXPECTED;
*pTotalLength = 0;
/* write all SPS */
iIdx = 0;
while (iIdx < pCtx->iSpsNum) {
// TODO (Sijia) wrap different operation of eSpsPpsIdStrategy to classes to hide the details
if (INCREASING_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pSpsArray[0].uiSpsId, PARA_SET_TYPE_AVCSPS);
} else if (CONSTANT_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
UpdateSpsPpsIdStrategyWithConstantId (& (pCtx->sPSOVector), pCtx->pSpsArray[0].uiSpsId, PARA_SET_TYPE_AVCSPS);
}
pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
/* generate sequence parameters set */
iId = (SPS_LISTING & pCtx->pSvcParam->eSpsPpsIdStrategy) ? iIdx : 0;
iId = pCtx->pFuncList->pParametersetStrategy->GetSpsIdx (iIdx);
WelsWriteOneSPS (pCtx, iId, iNalLength);
@ -3300,11 +2999,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
while (iIdx < pCtx->iSubsetSpsNum) {
iNal = pCtx->pOut->iNalIndex;
if (INCREASING_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pSubsetArray[iIdx].pSps.uiSpsId,
PARA_SET_TYPE_SUBSETSPS);
}
pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSubsetArray[iIdx].pSps.uiSpsId, PARA_SET_TYPE_SUBSETSPS);
iId = iIdx;
@ -3312,7 +3007,7 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
WelsLoadNal (pCtx->pOut, NAL_UNIT_SUBSET_SPS, NRI_PRI_HIGHEST);
WelsWriteSubsetSpsSyntax (&pCtx->pSubsetArray[iId], &pCtx->pOut->sBsWrite,
& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS].iParaSetIdDelta[0]));
pCtx->pFuncList->pParametersetStrategy->GetSpsIdOffsetList (PARA_SET_TYPE_SUBSETSPS));
WelsUnloadNal (pCtx->pOut);
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
@ -3329,16 +3024,11 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
++ iCountNal;
}
/* write all PPS */
if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
UpdatePpsList (pCtx);
}
pCtx->pFuncList->pParametersetStrategy->UpdatePpsList (pCtx);
iIdx = 0;
while (iIdx < pCtx->iPpsNum) {
if ((INCREASING_ID & pCtx->pSvcParam->eSpsPpsIdStrategy)) {
UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
}
pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
WelsWriteOnePPS (pCtx, iIdx, iNalLength);
@ -3552,10 +3242,9 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t iIdx,
int32_t iNalSize = 0;
iCountNal = 0;
if (INCREASING_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
} else if (CONSTANT_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
UpdateSpsPpsIdStrategyWithConstantId (& (pCtx->sPSOVector), pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
if (pCtx->pFuncList->pParametersetStrategy) {
pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pSpsArray[iIdx].uiSpsId, PARA_SET_TYPE_AVCSPS);
}
iReturn = WelsWriteOneSPS (pCtx, iIdx, iNalSize);
@ -3589,10 +3278,8 @@ int32_t WriteSavcParaset (sWelsEncCtx* pCtx, const int32_t iIdx,
iNalSize = 0;
iCountNal = 0;
if (INCREASING_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
UpdateSpsPpsIdStrategyWithIncreasingId (& (pCtx->sPSOVector), pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
} else if (CONSTANT_ID == pCtx->pSvcParam->eSpsPpsIdStrategy) {
UpdateSpsPpsIdStrategyWithConstantId (& (pCtx->sPSOVector), pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
if (pCtx->pFuncList->pParametersetStrategy) {
pCtx->pFuncList->pParametersetStrategy->Update (pCtx->pPPSArray[iIdx].iPpsId, PARA_SET_TYPE_PPS);
}
iReturn = WelsWriteOnePPS (pCtx, iIdx, iNalSize);
@ -3666,9 +3353,7 @@ int32_t WriteSavcParaset_Listing (sWelsEncCtx* pCtx, const int32_t kiSpatialNum,
}
// write PPS
if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
UpdatePpsList (pCtx);
}
pCtx->pFuncList->pParametersetStrategy->UpdatePpsList (pCtx);
//TODO: under new strategy, will PPS be correctly updated?
for (int32_t iSpatialId = 0; iSpatialId < kiSpatialNum; iSpatialId++) {
@ -3811,22 +3496,29 @@ EVideoFrameType PrepareEncodeFrame (sWelsEncCtx* pCtx, SLayerBSInfo*& pLayerBsIn
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 WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
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 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
SExistingParasetList sExistingParasetList;
SExistingParasetList* pExistingParasetList = NULL;
if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy)) {
for (int32_t k = 0; k < PARA_SET_TYPE; k++) {
memset (((*ppCtx)->sPSOVector.sParaSetOffsetVariable[k].bUsedParaSetIdInBs), 0, MAX_PPS_COUNT * sizeof (bool));
}
memcpy (sTmpPsoVariable, (*ppCtx)->sPSOVector.sParaSetOffsetVariable,
(PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
if (((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy))) {
(*ppCtx)->pFuncList->pParametersetStrategy->OutputCurrentStructure (sTmpPsoVariable, iTmpPpsIdList, (*ppCtx),
&sExistingParasetList);
if ((SPS_LISTING & iOldSpsPpsIdStrategy)
&& (SPS_LISTING & pNewParam->eSpsPpsIdStrategy)) {
pExistingParasetList = &sExistingParasetList;
sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
if (NULL != (*ppCtx)->pSubsetArray) {
sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
} else {
sExistingParasetList.uiInUseSubsetSpsNum = 0;
}
}
if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
&& (SPS_PPS_LISTING == pNewParam->eSpsPpsIdStrategy)) {
pExistingParasetList = &sExistingParasetList;
sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
sExistingParasetList.uiInUsePpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
memcpy (sExistingParasetList.sPps, (*ppCtx)->pPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
if (NULL != (*ppCtx)->pSubsetArray) {
sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
} else {
sExistingParasetList.uiInUseSubsetSpsNum = 0;
}
memcpy (iTmpPpsIdList, ((*ppCtx)->sPSOVector.iPpsIdList), MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
}
}
WelsUninitEncoderExt (ppCtx);
/* Update new parameters */
@ -4711,14 +4368,10 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
//for sEncoderStatistics
memcpy ((*ppCtx)->sEncoderStatistics, sTempEncoderStatistics, sizeof (sTempEncoderStatistics));
//load back the needed structure for eSpsPpsIdStrategy
if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy)) {
memcpy ((*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable,
(PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
}
if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
&& (SPS_PPS_LISTING == pNewParam->eSpsPpsIdStrategy)) {
memcpy (((*ppCtx)->sPSOVector.iPpsIdList), iTmpPpsIdList, MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
if (((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->eSpsPpsIdStrategy))
|| ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
&& (SPS_PPS_LISTING == pNewParam->eSpsPpsIdStrategy))) {
(*ppCtx)->pFuncList->pParametersetStrategy->LoadPreviousStructure (sTmpPsoVariable, iTmpPpsIdList);
}
} else {
/* maybe adjustment introduced in bitrate or little settings adjustment and so on.. */

View File

@ -0,0 +1,713 @@
/*!
* \copy
* Copyright (c) 2013, Cisco Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "au_set.h"
#include "encoder_context.h"
#include "paraset_strategy.h"
namespace WelsEnc {
IWelsParametersetStrategy* IWelsParametersetStrategy::CreateParametersetStrategy (
EParameterSetStrategy eSpsPpsIdStrategy, bool bSimulcastAVC,
const int32_t kiSpatialLayerNum) {
IWelsParametersetStrategy* pParametersetStrategy = NULL;
switch (eSpsPpsIdStrategy) {
case INCREASING_ID:
pParametersetStrategy = WELS_NEW_OP (CWelsParametersetIdIncreasing (bSimulcastAVC, kiSpatialLayerNum),
CWelsParametersetIdIncreasing);
WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
break;
case SPS_LISTING:
pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsListing (bSimulcastAVC, kiSpatialLayerNum),
CWelsParametersetSpsListing);
WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
break;
case SPS_LISTING_AND_PPS_INCREASING:
pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsListingPpsIncreasing (bSimulcastAVC, kiSpatialLayerNum),
CWelsParametersetSpsListingPpsIncreasing);
WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
break;
case SPS_PPS_LISTING:
pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsPpsListing (bSimulcastAVC, kiSpatialLayerNum),
CWelsParametersetSpsPpsListing);
WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
break;
case CONSTANT_ID:
default:
pParametersetStrategy = WELS_NEW_OP (CWelsParametersetIdConstant (bSimulcastAVC, kiSpatialLayerNum),
CWelsParametersetIdConstant);
WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
break;
}
return pParametersetStrategy;
}
static int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, const int32_t kiSpsId,
SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) {
int32_t iRet = 0;
if (!kbUseSubsetSps) {
pSps = & (pCtx->pSpsArray[kiSpsId]);
} else {
pSubsetSps = & (pCtx->pSubsetArray[kiSpsId]);
pSps = &pSubsetSps->pSps;
}
SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
// Need port pSps/pPps initialization due to spatial scalability changed
if (!kbUseSubsetSps) {
iRet = WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
bSVCBaselayer);
} else {
iRet = WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
}
return iRet;
}
static bool CheckMatchedSps (SWelsSPS* const pSps1, SWelsSPS* const pSps2) {
if ((pSps1->iMbWidth != pSps2->iMbWidth)
|| (pSps1->iMbHeight != pSps2->iMbHeight)) {
return false;
}
if ((pSps1->uiLog2MaxFrameNum != pSps2->uiLog2MaxFrameNum)
|| (pSps1->iLog2MaxPocLsb != pSps2->iLog2MaxPocLsb)) {
return false;
}
if (pSps1->iNumRefFrames != pSps2->iNumRefFrames) {
return false;
}
if ((pSps1->bFrameCroppingFlag != pSps2->bFrameCroppingFlag)
|| (pSps1->sFrameCrop.iCropLeft != pSps2->sFrameCrop.iCropLeft)
|| (pSps1->sFrameCrop.iCropRight != pSps2->sFrameCrop.iCropRight)
|| (pSps1->sFrameCrop.iCropTop != pSps2->sFrameCrop.iCropTop)
|| (pSps1->sFrameCrop.iCropBottom != pSps2->sFrameCrop.iCropBottom)
) {
return false;
}
if ((pSps1->uiProfileIdc != pSps2->uiProfileIdc)
|| (pSps1->bConstraintSet0Flag != pSps2->bConstraintSet0Flag)
|| (pSps1->bConstraintSet1Flag != pSps2->bConstraintSet1Flag)
|| (pSps1->bConstraintSet2Flag != pSps2->bConstraintSet2Flag)
|| (pSps1->bConstraintSet3Flag != pSps2->bConstraintSet3Flag)
|| (pSps1->iLevelIdc != pSps2->iLevelIdc)) {
return false;
}
return true;
}
static bool CheckMatchedSubsetSps (SSubsetSps* const pSubsetSps1, SSubsetSps* const pSubsetSps2) {
if (!CheckMatchedSps (&pSubsetSps1->pSps, &pSubsetSps2->pSps)) {
return false;
}
if ((pSubsetSps1->sSpsSvcExt.iExtendedSpatialScalability != pSubsetSps2->sSpsSvcExt.iExtendedSpatialScalability)
|| (pSubsetSps1->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag)
|| (pSubsetSps1->sSpsSvcExt.bSeqTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bSeqTcoeffLevelPredFlag)
|| (pSubsetSps1->sSpsSvcExt.bSliceHeaderRestrictionFlag != pSubsetSps2->sSpsSvcExt.bSliceHeaderRestrictionFlag)) {
return false;
}
return true;
}
/*!
* \brief check if the current parameter can found a presenting sps
* \param pParam the current encoding paramter in SWelsSvcCodingParam
* \param kbUseSubsetSps bool
* \param iDlayerIndex int, the index of current D layer
* \param iDlayerCount int, the number of total D layer
* \param pSpsArray array of all the stored SPSs
* \param pSubsetArray array of all the stored Subset-SPSs
* \return 0 - successful
* -1 - cannot find existing SPS for current encoder parameter
*/
int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
const int32_t iDlayerCount, const int32_t iSpsNumInUse,
SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray, bool bSVCBaseLayer) {
SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
assert (iSpsNumInUse <= MAX_SPS_COUNT);
if (!kbUseSubsetSps) {
SWelsSPS sTmpSps;
WelsInitSps (&sTmpSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
bSVCBaseLayer);
for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
if (CheckMatchedSps (&sTmpSps, &pSpsArray[iId])) {
return iId;
}
}
} else {
SSubsetSps sTmpSubsetSps;
WelsInitSubsetSps (&sTmpSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
pParam->iMaxNumRefFrame,
0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
if (CheckMatchedSubsetSps (&sTmpSubsetSps, &pSubsetArray[iId])) {
return iId;
}
}
}
return INVALID_ID;
}
CWelsParametersetIdConstant::CWelsParametersetIdConstant (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum) {
memset (&m_sParaSetOffset, 0, sizeof (m_sParaSetOffset));
m_bSimulcastAVC = bSimulcastAVC;
m_iSpatialLayerNum = kiSpatialLayerNum;
m_iBasicNeededSpsNum = 1;
m_iBasicNeededPpsNum = (1 + m_iSpatialLayerNum);
}
CWelsParametersetIdConstant::~CWelsParametersetIdConstant() {
}
int32_t CWelsParametersetIdConstant::GetPpsIdOffset (const int32_t iPpsId) {
return 0;
};
int32_t CWelsParametersetIdConstant::GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId) {
return 0;
};
int32_t* CWelsParametersetIdConstant::GetSpsIdOffsetList (const int iParasetType) {
return & (m_sParaSetOffset.sParaSetOffsetVariable[iParasetType].iParaSetIdDelta[0]);
}
uint32_t CWelsParametersetIdConstant::GetAllNeededParasetNum() {
return (GetNeededSpsNum()
+ GetNeededSubsetSpsNum()
+ GetNeededPpsNum());
}
uint32_t CWelsParametersetIdConstant::GetNeededSpsNum() {
if (0 >= m_sParaSetOffset.uiNeededSpsNum) {
m_sParaSetOffset.uiNeededSpsNum = m_iBasicNeededSpsNum * ((m_bSimulcastAVC) ? (m_iSpatialLayerNum) : (1));
}
return m_sParaSetOffset.uiNeededSpsNum;
}
uint32_t CWelsParametersetIdConstant::GetNeededSubsetSpsNum() {
if (0 >= m_sParaSetOffset.uiNeededSubsetSpsNum) {
m_sParaSetOffset.uiNeededSubsetSpsNum = (m_bSimulcastAVC ? 0 : (m_iSpatialLayerNum - 1));
}
return m_sParaSetOffset.uiNeededSubsetSpsNum;
}
uint32_t CWelsParametersetIdConstant::GetNeededPpsNum() {
if (0 == m_sParaSetOffset.uiNeededPpsNum) {
m_sParaSetOffset.uiNeededPpsNum = m_iBasicNeededPpsNum * ((m_bSimulcastAVC) ? (m_iSpatialLayerNum) :
(1));
}
return m_sParaSetOffset.uiNeededPpsNum;
}
void CWelsParametersetIdConstant::LoadPrevious (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
SSubsetSps* pSubsetArray, SWelsPPS* pPpsArray) {
return;
}
void CWelsParametersetIdConstant::Update (const uint32_t kuiId, const int iParasetType) {
memset (&m_sParaSetOffset, 0, sizeof (SParaSetOffset));
}
uint32_t CWelsParametersetIdConstant::GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps,
const int32_t iDlayerIndex,
const int32_t iDlayerCount, uint32_t kuiSpsId,
SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) {
WelsGenerateNewSps (pCtx, kbUseSubsetSps, iDlayerIndex,
iDlayerCount, kuiSpsId,
pSps, pSubsetSps, bSVCBaselayer);
return kuiSpsId;
}
uint32_t CWelsParametersetIdConstant::InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
SWelsSPS* pSps,
SSubsetSps* pSubsetSps,
uint32_t kuiPpsId,
const bool kbDeblockingFilterPresentFlag,
const bool kbUsingSubsetSps,
const bool kbEntropyCodingModeFlag) {
WelsInitPps (& pCtx->pPPSArray[kuiPpsId], pSps, pSubsetSps, kuiPpsId, true, kbUsingSubsetSps, kbEntropyCodingModeFlag);
SetUseSubsetFlag (kuiPpsId, kbUsingSubsetSps);
return kuiPpsId;
}
void CWelsParametersetIdConstant::SetUseSubsetFlag (const uint32_t iPpsId, const bool bUseSubsetSps) {
m_sParaSetOffset.bPpsIdMappingIntoSubsetsps[iPpsId] = bUseSubsetSps;
}
void CWelsParametersetIdNonConstant::OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
int32_t* pPpsIdList, sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) {
for (int32_t k = 0; k < PARA_SET_TYPE; k++) {
memset ((m_sParaSetOffset.sParaSetOffsetVariable[k].bUsedParaSetIdInBs), 0, MAX_PPS_COUNT * sizeof (bool));
}
memcpy (pParaSetOffsetVariable, m_sParaSetOffset.sParaSetOffsetVariable,
(PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
}
void CWelsParametersetIdNonConstant::LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
int32_t* pPpsIdList) {
memcpy (m_sParaSetOffset.sParaSetOffsetVariable, pParaSetOffsetVariable,
(PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
}
//
//CWelsParametersetIdIncreasing
//
void CWelsParametersetIdIncreasing::DebugSpsPps (const int32_t kiPpsId, const int32_t kiSpsId) {
#if _DEBUG
//SParaSetOffset use, 110421
//if ( (INCREASING_ID & eSpsPpsIdStrategy)) {
const int32_t kiParameterSetType = (m_sParaSetOffset.bPpsIdMappingIntoSubsetsps[kiPpsId] ?
PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS) ;
const int32_t kiTmpSpsIdInBs = kiSpsId +
m_sParaSetOffset.sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[kiSpsId];
const int32_t tmp_pps_id_in_bs = kiPpsId +
m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[kiPpsId];
assert (MAX_SPS_COUNT > kiTmpSpsIdInBs);
assert (MAX_PPS_COUNT > tmp_pps_id_in_bs);
assert (m_sParaSetOffset.sParaSetOffsetVariable[kiParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
//}
#endif
}
void CWelsParametersetIdIncreasing::DebugPps (const int32_t kiPpsId) {
#if _DEBUG
const int32_t kiTmpPpsIdInBs = kiPpsId +
m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[ kiPpsId ];
assert (MAX_PPS_COUNT > kiTmpPpsIdInBs);
//when activated need to sure there is avialable PPS
assert (m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].bUsedParaSetIdInBs[kiTmpPpsIdInBs]);
#endif
}
void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable,
const int32_t kiCurEncoderParaSetId,
const uint32_t kuiMaxIdInBs) { //paraset_type = 0: SPS; =1: PPS
//SPS_ID in avc_sps and pSubsetSps will be different using this
//SPS_ID case example:
//1st enter: next_spsid_in_bs == 0; spsid == 0; delta==0; //actual spsid_in_bs == 0
//1st finish: next_spsid_in_bs == 1;
//2nd enter: next_spsid_in_bs == 1; spsid == 0; delta==1; //actual spsid_in_bs == 1
//2nd finish: next_spsid_in_bs == 2;
//31st enter: next_spsid_in_bs == 31; spsid == 0~2; delta==31~29; //actual spsid_in_bs == 31
//31st finish:next_spsid_in_bs == 0;
//31st enter: next_spsid_in_bs == 0; spsid == 0~2; delta==-2~0; //actual spsid_in_bs == 0
//31st finish:next_spsid_in_bs == 1;
const int32_t kiEncId = kiCurEncoderParaSetId;
uint32_t uiNextIdInBs = sParaSetOffsetVariable->uiNextParaSetIdToUseInBs;
//update current layer's pCodingParam
sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] = uiNextIdInBs -
kiEncId; //for current parameter set, change its id_delta
//write pso pData for next update:
sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] = true; // update current used_id
//prepare for next update:
// find the next avaibable iId
++uiNextIdInBs;
if (uiNextIdInBs >= kuiMaxIdInBs) {
uiNextIdInBs = 0;//ensure the SPS_ID wound not exceed MAX_SPS_COUNT
}
// update next_id
sParaSetOffsetVariable->uiNextParaSetIdToUseInBs = uiNextIdInBs;
}
void CWelsParametersetIdIncreasing::Update (const uint32_t kuiId, const int iParasetType) {
#if _DEBUG
m_sParaSetOffset.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);
}
}

View File

@ -52,7 +52,7 @@ namespace WelsEnc {
typedef int32_t (*PWelsCodingSliceFunc) (sWelsEncCtx* pCtx, SSlice* pSlice);
typedef void (*PWelsSliceHeaderWriteFunc) (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
int32_t* pPpsIdDelta);
IWelsParametersetStrategy* pParametersetStrategy);
void UpdateNonZeroCountCache (SMB* pMb, SMbCache* pMbCache) {
ST32 (&pMbCache->iNonZeroCoeffCount[9], LD32 (&pMb->pNonZeroCount[ 0]));
@ -276,7 +276,7 @@ void WriteRefPicMarking (SBitStringAux* pBs, SSliceHeader* pSliceHeader, SNalUni
}
void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
int32_t* pPpsIdDelta) {
IWelsParametersetStrategy* pParametersetStrategy) {
SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
SSliceHeader* pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
@ -285,7 +285,7 @@ void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCur
BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice);
BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */
BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + ((pPpsIdDelta != NULL) ? pPpsIdDelta[pSliceHeader->pPps->iPpsId] : 0));
BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pParametersetStrategy->GetPpsIdOffset (pSliceHeader->pPps->iPpsId));
BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
@ -342,7 +342,7 @@ void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCur
}
void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
int32_t* pPpsIdDelta) {
IWelsParametersetStrategy* pParametersetStrategy) {
SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP;
@ -353,7 +353,8 @@ void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* p
BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice);
BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */
BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + ((pPpsIdDelta != NULL) ? pPpsIdDelta[pSliceHeader->pPps->iPpsId] : 0));
BsWriteUE (pBs, pSliceHeader->pPps->iPpsId +
pParametersetStrategy->GetPpsIdOffset (pSliceHeader->pPps->iPpsId));
BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
@ -926,20 +927,7 @@ int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const
WelsSliceHeaderExtInit (pEncCtx, pCurLayer, pCurSlice);
g_pWelsWriteSliceHeader[pCurSlice->bSliceHeaderExtFlag] (pEncCtx, pBs, pCurLayer, pCurSlice,
((SPS_PPS_LISTING != pEncCtx->pSvcParam->eSpsPpsIdStrategy) ? (&
(pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0])) : NULL));
#if _DEBUG
if (INCREASING_ID & pEncCtx->sPSOVector.eSpsPpsIdStrategy) {
const int32_t kiEncoderPpsId = pCurSlice->sSliceHeaderExt.sSliceHeader.pPps->iPpsId;
const int32_t kiTmpPpsIdInBs = kiEncoderPpsId +
pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[ kiEncoderPpsId ];
assert (MAX_PPS_COUNT > kiTmpPpsIdInBs);
//when activated need to sure there is avialable PPS
assert (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].bUsedParaSetIdInBs[kiTmpPpsIdInBs]);
}
#endif
pEncCtx->pFuncList->pParametersetStrategy);
pCurSlice->uiLastMbQp = pCurLayer->sLayerInfo.pPpsP->iPicInitQp + pCurSlice->sSliceHeaderExt.sSliceHeader.iSliceQpDelta;

View File

@ -11,6 +11,7 @@ ENCODER_CPP_SRCS=\
$(ENCODER_SRCDIR)/core/src/md.cpp\
$(ENCODER_SRCDIR)/core/src/mv_pred.cpp\
$(ENCODER_SRCDIR)/core/src/nal_encap.cpp\
$(ENCODER_SRCDIR)/core/src/paraset_strategy.cpp\
$(ENCODER_SRCDIR)/core/src/picture_handle.cpp\
$(ENCODER_SRCDIR)/core/src/ratectl.cpp\
$(ENCODER_SRCDIR)/core/src/ref_list_mgr_svc.cpp\

View File

@ -34,7 +34,8 @@
#include "cpu.h"
WELSVP_NAMESPACE_BEGIN
#define MAX_SAMPLE_WIDTH 1920
#define MAX_SAMPLE_HEIGHT 1088
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -43,11 +44,37 @@ CDownsampling::CDownsampling (int32_t iCpuFlag) {
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 @@ EResult CDownsampling::Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pDs
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],
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);
} 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[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);
} 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.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);
} 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[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.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;
}

View File

@ -170,10 +170,13 @@ class CDownsampling : public IStrategy {
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

View File

@ -385,7 +385,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_INCREASING_ID) {
//prepare output if needed
FILE* fEnc = NULL;
#ifdef DEBUG_FILE_SAVE_INCREASING_ID
fEnc = fopen ("enc_i.264", "wb");
fEnc = fopen ("enc_INCREASING_ID.264", "wb");
#endif
// Test part#1
@ -440,7 +440,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_INCREASING_ID) {
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam3: rv = " << rv;
#ifdef DEBUG_FILE_SAVE_INCREASING_ID
fEnc = fopen ("enc3.264", "wb");
fEnc = fopen ("enc_INCREASING_ID2.264", "wb");
#endif
iEncFrameNum = 0;
EncDecOneFrame (sParam3.iPicWidth, sParam3.iPicHeight, iEncFrameNum++, fEnc);
@ -495,7 +495,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING
//prepare output if needed
FILE* fEnc = NULL;
#ifdef DEBUG_FILE_SAVE2
fEnc = fopen ("enc2.264", "wb");
fEnc = fopen ("enc_SPS_LISTING_AND_PPS_INCREASING1.264", "wb");
#endif
// Test part#1
@ -550,7 +550,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam3: rv = " << rv;
#ifdef DEBUG_FILE_SAVE2
fEnc = fopen ("enc3.264", "wb");
fEnc = fopen ("enc_SPS_LISTING_AND_PPS_INCREASING11.264", "wb");
#endif
iEncFrameNum = 0;
EncDecOneFrame (sParam3.iPicWidth, sParam3.iPicHeight, iEncFrameNum++, fEnc);
@ -598,7 +598,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING
//prepare output if needed
FILE* fEnc = NULL;
#ifdef DEBUG_FILE_SAVE5
fEnc = fopen ("encID2.264", "wb");
fEnc = fopen ("enc_SPS_LISTING_AND_PPS_INCREASING2.264", "wb");
#endif
// step#1: pParam1
@ -647,7 +647,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING
//prepare output if needed
FILE* fEnc = NULL;
#ifdef DEBUG_FILE_SAVE2
fEnc = fopen ("enc4.264", "wb");
fEnc = fopen ("enc_SPS_LISTING_AND_PPS_INCREASING3.264", "wb");
#endif
// step#1: pParam1
@ -853,7 +853,7 @@ TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING3) {
//prepare output if needed
FILE* fEnc = NULL;
#ifdef DEBUG_FILE_SAVE5
fEnc = fopen ("enc4.264", "wb");
fEnc = fopen ("enc_LISTING3.264", "wb");
#endif
// step#1: ordinary encoding

View File

@ -5,6 +5,7 @@
#include "param_svc.h"
#include "parameter_sets.h"
#include "wels_const.h"
#include "paraset_strategy.h"
using namespace WelsEnc;