add new SpsPpsStrategy and UT
This commit is contained in:
parent
e9ec603fd7
commit
98ed302990
@ -385,6 +385,17 @@ typedef enum {
|
||||
HIGH_COMPLEXITY ///< high complexity, lowest speed, high quality
|
||||
} ECOMPLEXITY_MODE;
|
||||
|
||||
/**
|
||||
* @brief Enumulate for the stategy of SPS/PPS strategy
|
||||
*/
|
||||
typedef enum {
|
||||
CONSTANT_ID = 0, ///< constant id in SPS/PPS
|
||||
INCREASING_ID = 0x01, ///< SPS/PPS id increases at each IDR
|
||||
SPS_LISTING = 0x02, ///< using SPS in the existing list if possible
|
||||
SPS_LISTING_AND_PPS_INCREASING = 0x03,
|
||||
SPS_PPS_LISTING = 0x06,
|
||||
} EParameterSetStrategy;
|
||||
|
||||
// TODO: Refine the parameters definition.
|
||||
/**
|
||||
* @brief SVC Encoding Parameters
|
||||
@ -421,7 +432,7 @@ typedef struct TagEncParamExt {
|
||||
ECOMPLEXITY_MODE iComplexityMode;
|
||||
unsigned int uiIntraPeriod; ///< period of Intra frame
|
||||
int iNumRefFrame; ///< number of reference frame used
|
||||
bool bEnableSpsPpsIdAddition; ///< false:not adjust ID in SPS/PPS; true: adjust ID in SPS/PPS
|
||||
int iSpsPpsIdStrategy; ///< different stategy in adjust ID in SPS/PPS: 0- constant ID, 1-additional ID, 6-mapping and additional
|
||||
bool bPrefixNalAddingCtrl; ///< false:not use Prefix NAL; true: use Prefix NAL
|
||||
bool bEnableSSEI; ///< false:not use SSEI; true: use SSEI -- TODO: planning to remove the interface of SSEI
|
||||
bool bSimulcastAVC; ///< (when encoding more than 1 spatial layer) false: use SVC syntax for higher layers; true: use Simulcast AVC -- coming soon
|
||||
|
@ -232,8 +232,8 @@ int ParseConfig (CReadConfig& cRdCfg, SSourcePicture* pSrcPic, SEncParamExt& pSv
|
||||
pSvcParam.uiIntraPeriod = atoi (strTag[1].c_str());
|
||||
} else if (strTag[0].compare ("MaxNalSize") == 0) {
|
||||
pSvcParam.uiMaxNalSize = atoi (strTag[1].c_str());
|
||||
} else if (strTag[0].compare ("EnableSpsPpsIDAddition") == 0) {
|
||||
pSvcParam.bEnableSpsPpsIdAddition = atoi (strTag[1].c_str()) ? true : false;
|
||||
} else if (strTag[0].compare ("SpsPpsIDStrategy") == 0) {
|
||||
pSvcParam.iSpsPpsIdStrategy = atoi (strTag[1].c_str());
|
||||
} else if (strTag[0].compare ("EnableScalableSEI") == 0) {
|
||||
pSvcParam.bEnableSSEI = atoi (strTag[1].c_str()) ? true : false;
|
||||
} else if (strTag[0].compare ("EnableFrameCropping") == 0) {
|
||||
@ -421,7 +421,7 @@ int ParseCommandLine (int argc, char** argv, SSourcePicture* pSrcPic, SEncParamE
|
||||
pSvcParam.uiMaxNalSize = atoi (argv[n++]);
|
||||
|
||||
else if (!strcmp (pCommand, "-spsid") && (n < argc))
|
||||
pSvcParam.bEnableSpsPpsIdAddition = atoi (argv[n++]) ? true : false;
|
||||
pSvcParam.iSpsPpsIdStrategy = atoi (argv[n++]);
|
||||
|
||||
else if (!strcmp (pCommand, "-cabac") && (n < argc))
|
||||
pSvcParam.iEntropyCodingModeFlag = atoi (argv[n++]);
|
||||
@ -591,7 +591,7 @@ int FillSpecificParameters (SEncParamExt& sParam) {
|
||||
sParam.bEnableLongTermReference = 0; // long term reference control
|
||||
sParam.iLtrMarkPeriod = 30;
|
||||
sParam.uiIntraPeriod = 320; // period of Intra frame
|
||||
sParam.bEnableSpsPpsIdAddition = 1;
|
||||
sParam.iSpsPpsIdStrategy = INCREASING_ID;
|
||||
sParam.bPrefixNalAddingCtrl = 0;
|
||||
sParam.iComplexityMode = MEDIUM_COMPLEXITY;
|
||||
int iIndexLayer = 0;
|
||||
|
@ -141,8 +141,26 @@ int32_t WelsInitPps (SWelsPPS* pPps,
|
||||
const bool kbDeblockingFilterPresentFlag,
|
||||
const bool kbUsingSubsetSps,
|
||||
const bool kbEntropyCodingModeFlag);
|
||||
|
||||
int32_t WelsCheckRefFrameLimitationNumRefFirst (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam);
|
||||
int32_t WelsCheckRefFrameLimitationLevelIdcFirst (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam);
|
||||
int32_t WelsAdjustLevel( SSpatialLayerConfig* pSpatialLayer);
|
||||
|
||||
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);
|
||||
}
|
||||
#endif//WELS_ACCESS_UNIT_PARSER_H__
|
||||
|
@ -48,7 +48,7 @@ namespace WelsEnc {
|
||||
* \param pEncCtx sWelsEncCtx*
|
||||
* \return successful - 0; otherwise none 0 for failed
|
||||
*/
|
||||
int32_t RequestMemorySvc (sWelsEncCtx** ppCtx);
|
||||
int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingParasetList);
|
||||
|
||||
/*!
|
||||
* \brief free memory in SVC core encoder
|
||||
|
@ -191,6 +191,7 @@ typedef struct TagWelsEncCtx {
|
||||
SSubsetSps* pSubsetArray; // MAX_SPS_COUNT by standard compatible
|
||||
SSubsetSps* pSubsetSps;
|
||||
int32_t iSpsNum; // number of pSps used
|
||||
int32_t iSubsetSpsNum; // number of pSps used
|
||||
int32_t iPpsNum; // number of pPps used
|
||||
|
||||
// Output
|
||||
@ -216,6 +217,7 @@ typedef struct TagWelsEncCtx {
|
||||
pDqIdcMap; // overall DQ map of full scalability in specific frame (All full D/T/Q layers involved) // pDqIdcMap[dq_index] for each SDqIdc pData
|
||||
|
||||
SParaSetOffset sPSOVector;
|
||||
SParaSetOffset* pPSOVector;
|
||||
CMemoryAlign* pMemAlign;
|
||||
|
||||
#if defined(STAT_OUTPUT)
|
||||
|
@ -75,7 +75,8 @@ void GomValidCheck (const int32_t kiMbWidth, const int32_t kiMbHeight, int32_t*
|
||||
* \param para SWelsSvcCodingParam*
|
||||
* \return successful - 0; otherwise none 0 for failed
|
||||
*/
|
||||
int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pPara, SLogContext* pLogCtx);
|
||||
int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pPara, SLogContext* pLogCtx,
|
||||
SExistingParasetList* pExistingParasetList);
|
||||
|
||||
/*!
|
||||
* \brief uninitialize Wels encoder core library
|
||||
|
@ -162,7 +162,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
|
||||
param.bEnableAdaptiveQuant = true; // adaptive quantization control
|
||||
param.bEnableFrameSkip = true; // frame skipping
|
||||
param.bEnableLongTermReference = false; // long term reference control
|
||||
param.bEnableSpsPpsIdAddition = true; // pSps pPps id addition control
|
||||
param.iSpsPpsIdStrategy = INCREASING_ID; // pSps pPps id addition control
|
||||
param.bPrefixNalAddingCtrl = false; // prefix NAL adding control
|
||||
param.iSpatialLayerNum = 1; // number of dependency(Spatial/CGS) layers used to be encoded
|
||||
param.iTemporalLayerNum = 1; // number of temporal layer specified
|
||||
@ -350,8 +350,8 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
|
||||
|
||||
bPrefixNalAddingCtrl = pCodingParam.bPrefixNalAddingCtrl;
|
||||
|
||||
bEnableSpsPpsIdAddition =
|
||||
pCodingParam.bEnableSpsPpsIdAddition;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference.
|
||||
iSpsPpsIdStrategy =
|
||||
pCodingParam.iSpsPpsIdStrategy;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference.
|
||||
//SHOULD enable this feature.
|
||||
|
||||
SSpatialLayerInternal* pDlp = &sDependencyLayers[0];
|
||||
@ -477,6 +477,18 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt {
|
||||
|
||||
} SWelsSvcCodingParam;
|
||||
|
||||
|
||||
typedef struct TagExistingParasetList {
|
||||
SWelsSPS sSps[MAX_SPS_COUNT];
|
||||
SSubsetSps sSubsetSps[MAX_SPS_COUNT];
|
||||
SWelsPPS sPps[MAX_PPS_COUNT];
|
||||
|
||||
uint32_t uiInUseSpsNum;
|
||||
uint32_t uiInUseSubsetSpsNum;
|
||||
uint32_t uiInUsePpsNum;
|
||||
} SExistingParasetList;
|
||||
|
||||
|
||||
static inline int32_t FreeCodingParam (SWelsSvcCodingParam** pParam, CMemoryAlign* pMa) {
|
||||
if (pParam == NULL || *pParam == NULL || pMa == NULL)
|
||||
return 1;
|
||||
|
@ -83,9 +83,15 @@ typedef struct TagParaSetOffset {
|
||||
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
|
||||
bool bEnableSpsPpsIdAddition;
|
||||
int32_t iSpsPpsIdStrategy;
|
||||
#endif
|
||||
|
||||
uint32_t uiInUseSpsNum;
|
||||
uint32_t uiInUseSubsetSpsNum;
|
||||
uint32_t uiInUsePpsNum;
|
||||
} SParaSetOffset;
|
||||
|
||||
|
||||
|
@ -171,6 +171,7 @@
|
||||
|
||||
#define UNAVAILABLE_DQ_ID ((uint8_t)(-1))
|
||||
#define LAYER_NUM_EXCHANGEABLE 2
|
||||
#define INVALID_ID (-1)
|
||||
|
||||
#define NAL_HEADER_ADD_0X30BYTES 50
|
||||
|
||||
|
@ -336,27 +336,27 @@ 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, SParaSetOffset* pPSOVector) {
|
||||
SBitStringAux* pLocalBitStringAux = pBitStringAux;
|
||||
|
||||
bool bUsedSubset = sPSOVector->bPpsIdMappingIntoSubsetsps[pPps->iPpsId];
|
||||
int32_t iParameterSetType = (bUsedSubset ? PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS);
|
||||
const int32_t kiParameterSetType = (pPSOVector != NULL) ? (pPSOVector->bPpsIdMappingIntoSubsetsps[pPps->iPpsId] ?
|
||||
PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS) : 0;
|
||||
|
||||
BsWriteUE (pLocalBitStringAux, pPps->iPpsId +
|
||||
sPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId]);
|
||||
BsWriteUE (pLocalBitStringAux, pPps->iSpsId +
|
||||
sPSOVector->sParaSetOffsetVariable[iParameterSetType].iParaSetIdDelta[pPps->iSpsId]);
|
||||
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 (sPSOVector->bEnableSpsPpsIdAddition) {
|
||||
if ((pPSOVector != NULL) && (INCREASING_ID & pPSOVector->iSpsPpsIdStrategy)) {
|
||||
const int32_t kiTmpSpsIdInBs = pPps->iSpsId +
|
||||
sPSOVector->sParaSetOffsetVariable[iParameterSetType].iParaSetIdDelta[pPps->iSpsId];
|
||||
pPSOVector->sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[pPps->iSpsId];
|
||||
const int32_t tmp_pps_id_in_bs = pPps->iPpsId +
|
||||
sPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[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 (sPSOVector->sParaSetOffsetVariable[iParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
|
||||
assert (pPSOVector->sParaSetOffsetVariable[kiParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -323,6 +323,12 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa
|
||||
pCodingParam->bDeblockingParallelFlag = true;
|
||||
}
|
||||
|
||||
if (pCodingParam->iSpatialLayerNum > 1 && (SPS_LISTING & pCodingParam->iSpsPpsIdStrategy)) {
|
||||
WelsLog (pLogCtx, WELS_LOG_INFO,
|
||||
"ParamValidationExt(), iSpsPpsIdStrategy adjusted to CONSTANT_ID");
|
||||
pCodingParam->iSpsPpsIdStrategy = CONSTANT_ID;
|
||||
}
|
||||
|
||||
for (i = 0; i < pCodingParam->iSpatialLayerNum; ++ i) {
|
||||
SSpatialLayerConfig* pSpatialLayer = &pCodingParam->sSpatialLayers[i];
|
||||
const int32_t kiPicWidth = pSpatialLayer->iVideoWidth;
|
||||
@ -665,8 +671,12 @@ static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingPara
|
||||
++ iDIndex;
|
||||
} while (iDIndex < iNumDependencyLayers);
|
||||
|
||||
// count parasets
|
||||
iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) +
|
||||
iCountNumLayers; // plus iCountNumLayers for reserved application
|
||||
iCountNumLayers // plus iCountNumLayers for reserved application
|
||||
+ ((SPS_LISTING & pParam->iSpsPpsIdStrategy) ? MAX_SPS_COUNT : 0) //for Sps
|
||||
+ (((SPS_LISTING & pParam->iSpsPpsIdStrategy) && (iNumDependencyLayers > 1)) ? MAX_SPS_COUNT : 0) //for SubsetSps
|
||||
+ ((SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy) ? MAX_PPS_COUNT : 0);
|
||||
|
||||
// to check number of layers / nals / slices dependencies, 12/8/2010
|
||||
if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) {
|
||||
@ -847,7 +857,7 @@ void FreeMbCache (SMbCache* pMbCache, CMemoryAlign* pMa) {
|
||||
}
|
||||
}
|
||||
|
||||
int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
|
||||
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) {
|
||||
int32_t iRet = 0;
|
||||
@ -866,9 +876,6 @@ int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const
|
||||
iRet = WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
|
||||
pParam->iMaxNumRefFrame,
|
||||
kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
iRet = WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
|
||||
pParam->iMaxNumRefFrame,
|
||||
@ -877,12 +884,131 @@ int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const
|
||||
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) {
|
||||
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);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief initialize ppDqLayerList and slicepEncCtx_list due to count number of layers available
|
||||
* \pParam pCtx sWelsEncCtx*
|
||||
* \return 0 - successful; otherwise failed
|
||||
*/
|
||||
static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) {
|
||||
static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingParasetList) {
|
||||
SWelsSvcCodingParam* pParam = NULL;
|
||||
SWelsSPS* pSps = NULL;
|
||||
SSubsetSps* pSubsetSps = NULL;
|
||||
@ -1045,15 +1171,52 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) {
|
||||
}
|
||||
|
||||
// for dynamically malloc for parameter sets memory instead of maximal items for standard to reduce size, 3/18/2010
|
||||
(*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (iDlayerCount * sizeof (SWelsPPS), "pPPSArray");
|
||||
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
|
||||
|
||||
// SPS
|
||||
if (! (SPS_LISTING & pParam->iSpsPpsIdStrategy)) {
|
||||
(*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (sizeof (SWelsSPS), "pSpsArray");
|
||||
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
|
||||
if (iDlayerCount > 1) {
|
||||
(*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMalloc ((iDlayerCount - 1) * sizeof (SSubsetSps), "pSubsetArray");
|
||||
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc (ppCtx))
|
||||
}
|
||||
} else {
|
||||
// pParam->iSpsPpsIdStrategy == SPS_LISTING_AND_PPS_INCREASING
|
||||
// new memory
|
||||
(*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SWelsSPS), "pSpsArray");
|
||||
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
|
||||
|
||||
(*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SSubsetSps), "pSubsetArray");
|
||||
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc (ppCtx))
|
||||
|
||||
// copy from existing if the pointer exists
|
||||
if (NULL != pExistingParasetList) {
|
||||
(*ppCtx)->sPSOVector.uiInUseSpsNum = pExistingParasetList->uiInUseSpsNum;
|
||||
(*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = pExistingParasetList->uiInUseSubsetSpsNum;
|
||||
memcpy ((*ppCtx)->pSpsArray, pExistingParasetList->sSps, MAX_SPS_COUNT * sizeof (SWelsSPS));
|
||||
memcpy ((*ppCtx)->pSubsetArray, pExistingParasetList->sSubsetSps, MAX_SPS_COUNT * sizeof (SSubsetSps));
|
||||
}
|
||||
}
|
||||
// PPS
|
||||
if (! (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy)) {
|
||||
(*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (iDlayerCount * sizeof (SWelsPPS), "pPPSArray");
|
||||
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
|
||||
} else {
|
||||
(*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (MAX_PPS_COUNT * sizeof (SWelsPPS), "pPPSArray");
|
||||
WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
|
||||
|
||||
|
||||
// copy from existing if the pointer exists
|
||||
if (NULL != pExistingParasetList) {
|
||||
(*ppCtx)->sPSOVector.uiInUsePpsNum = pExistingParasetList->uiInUsePpsNum;
|
||||
memcpy ((*ppCtx)->pPPSArray, pExistingParasetList->sPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
|
||||
}
|
||||
}
|
||||
|
||||
if (INCREASING_ID & pParam->iSpsPpsIdStrategy) {
|
||||
(*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))
|
||||
@ -1066,12 +1229,79 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) {
|
||||
|
||||
pDqIdc->uiSpatialId = iDlayerIndex;
|
||||
|
||||
if (! (SPS_LISTING & pParam->iSpsPpsIdStrategy)) {
|
||||
WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
|
||||
iDlayerCount, iSpsId, pSps, pSubsetSps);
|
||||
} else {
|
||||
//SPS_LISTING_AND_PPS_INCREASING == pParam->iSpsPpsIdStrategy
|
||||
//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);
|
||||
|
||||
|
||||
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->iSpsPpsIdStrategy) && (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->iSpsPpsIdStrategy) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (! (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Not using FMO in SVC coding so far, come back if need FMO
|
||||
{
|
||||
@ -1085,7 +1315,7 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) {
|
||||
if (iResult) {
|
||||
WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "InitDqLayers(), InitSlicePEncCtx failed(%d)!", iResult);
|
||||
FreeMemorySvc (ppCtx);
|
||||
return 1;
|
||||
return iResult;
|
||||
}
|
||||
(*ppCtx)->ppDqLayerList[iDlayerIndex]->pSliceEncCtx = & (*ppCtx)->pSliceCtxList[iDlayerIndex];
|
||||
}
|
||||
@ -1097,12 +1327,23 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) {
|
||||
if (bUseSubsetSps)
|
||||
++ iSpsId;
|
||||
++ iPpsId;
|
||||
if (bUseSubsetSps) {
|
||||
++ (*ppCtx)->iSubsetSpsNum;
|
||||
} else {
|
||||
++ (*ppCtx)->iSpsNum;
|
||||
}
|
||||
++ (*ppCtx)->iPpsNum;
|
||||
|
||||
++ iDlayerIndex;
|
||||
}
|
||||
return 0;
|
||||
if (SPS_LISTING & pParam->iSpsPpsIdStrategy) {
|
||||
(*ppCtx)->iSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
|
||||
(*ppCtx)->iSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
|
||||
}
|
||||
if (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy) {
|
||||
(*ppCtx)->iPpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
|
||||
}
|
||||
return ENC_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t AllocStrideTables (sWelsEncCtx** ppCtx, const int32_t kiNumSpatialLayers) {
|
||||
@ -1411,7 +1652,7 @@ void GetMvMvdRange (SWelsSvcCodingParam* pParam, int32_t& iMvRange, int32_t& iMv
|
||||
|
||||
iMvdRange = WELS_MIN (iMvdRange, iFixMvdRange);
|
||||
}
|
||||
int32_t RequestMemorySvc (sWelsEncCtx** ppCtx) {
|
||||
int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingParasetList) {
|
||||
SWelsSvcCodingParam* pParam = (*ppCtx)->pSvcParam;
|
||||
CMemoryAlign* pMa = (*ppCtx)->pMemAlign;
|
||||
SSpatialLayerConfig* pFinalSpatial = NULL;
|
||||
@ -1616,7 +1857,7 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx) {
|
||||
|
||||
//End of pVaa memory allocation
|
||||
|
||||
iResult = InitDqLayers (ppCtx);
|
||||
iResult = InitDqLayers (ppCtx, pExistingParasetList);
|
||||
if (iResult) {
|
||||
WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc(), InitDqLayers failed(%d)!", iResult);
|
||||
FreeMemorySvc (ppCtx);
|
||||
@ -2130,7 +2371,8 @@ int32_t GetMultipleThreadIdc (SLogContext* pLogCtx, SWelsSvcCodingParam* pCoding
|
||||
* \pParam pParam SWelsSvcCodingParam*
|
||||
* \return successful - 0; otherwise none 0 for failed
|
||||
*/
|
||||
int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) {
|
||||
int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx,
|
||||
SExistingParasetList* pExistingParasetList) {
|
||||
sWelsEncCtx* pCtx = NULL;
|
||||
int32_t iRet = 0;
|
||||
int16_t iSliceNum = 1; // number of slices used
|
||||
@ -2189,7 +2431,7 @@ int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPar
|
||||
|
||||
pCtx->iActiveThreadsNum = pCodingParam->iCountThreadsNum;
|
||||
pCtx->iMaxSliceCount = iSliceNum;
|
||||
iRet = RequestMemorySvc (&pCtx);
|
||||
iRet = RequestMemorySvc (&pCtx, pExistingParasetList);
|
||||
if (iRet != 0) {
|
||||
WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), RequestMemorySvc failed return %d.", iRet);
|
||||
FreeMemorySvc (&pCtx);
|
||||
@ -2553,18 +2795,26 @@ void WelsInitCurrentLayer (sWelsEncCtx* pCtx,
|
||||
iSliceCount = GetCurrentSliceNum (pCurDq->pSliceEncCtx);
|
||||
assert (iSliceCount > 0);
|
||||
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId = pDqIdc->iPpsId;
|
||||
int32_t iCurPpsId = pDqIdc->iPpsId;
|
||||
int32_t iCurSpsId = pDqIdc->iSpsId;
|
||||
|
||||
if (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy) {
|
||||
iCurPpsId = pCtx->sPSOVector.iPpsIdList[pDqIdc->iPpsId][WELS_ABS (pCtx->uiIdrPicId - 1) % MAX_PPS_COUNT];
|
||||
}
|
||||
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId = iCurPpsId;
|
||||
pCurDq->sLayerInfo.pPpsP =
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps = &pCtx->pPPSArray[pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId];
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId = pDqIdc->iSpsId;
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps = &pCtx->pPPSArray[iCurPpsId];
|
||||
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId = iCurSpsId;
|
||||
if (kbUseSubsetSpsFlag) {
|
||||
pCurDq->sLayerInfo.pSubsetSpsP = &pCtx->pSubsetArray[pDqIdc->iSpsId];
|
||||
pCurDq->sLayerInfo.pSubsetSpsP = &pCtx->pSubsetArray[iCurSpsId];
|
||||
pCurDq->sLayerInfo.pSpsP =
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCurDq->sLayerInfo.pSubsetSpsP->pSps;
|
||||
} else {
|
||||
pCurDq->sLayerInfo.pSubsetSpsP = NULL;
|
||||
pCurDq->sLayerInfo.pSpsP =
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCtx->pSpsArray[pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId];
|
||||
pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCtx->pSpsArray[iCurSpsId];
|
||||
}
|
||||
|
||||
pSlice = pBaseSlice;
|
||||
@ -2865,29 +3115,60 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
|
||||
/* write all SPS */
|
||||
iIdx = 0;
|
||||
while (iIdx < pCtx->iSpsNum) {
|
||||
SDqIdc* pDqIdc = &pCtx->pDqIdcMap[iIdx];
|
||||
const int32_t kiDid = pDqIdc->uiSpatialId;
|
||||
const bool kbUsingSubsetSps = (kiDid > BASE_DEPENDENCY_ID);
|
||||
|
||||
iNal = pCtx->pOut->iNalIndex;
|
||||
|
||||
if (pCtx->pSvcParam->bEnableSpsPpsIdAddition) {
|
||||
if (INCREASING_ID == pCtx->pSvcParam->iSpsPpsIdStrategy) {
|
||||
#if _DEBUG
|
||||
pCtx->sPSOVector.bEnableSpsPpsIdAddition = 1;
|
||||
assert (kiDid < MAX_DEPENDENCY_LAYER);
|
||||
pCtx->sPSOVector.iSpsPpsIdStrategy = INCREASING_ID;
|
||||
assert (iIdx < MAX_DQ_LAYER_NUM);
|
||||
#endif
|
||||
|
||||
ParasetIdAdditionIdAdjust (& (pCtx->sPSOVector.sParaSetOffsetVariable[kbUsingSubsetSps ? PARA_SET_TYPE_SUBSETSPS :
|
||||
PARA_SET_TYPE_AVCSPS]),
|
||||
(kbUsingSubsetSps) ? (pCtx->pSubsetArray[iIdx - 1].pSps.uiSpsId) : (pCtx->pSpsArray[0].uiSpsId),
|
||||
ParasetIdAdditionIdAdjust (& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS]),
|
||||
pCtx->pSpsArray[0].uiSpsId,
|
||||
MAX_SPS_COUNT);
|
||||
} else {
|
||||
} else if (CONSTANT_ID == pCtx->pSvcParam->iSpsPpsIdStrategy) {
|
||||
memset (& (pCtx->sPSOVector), 0, sizeof (pCtx->sPSOVector));
|
||||
}
|
||||
|
||||
if (kbUsingSubsetSps) {
|
||||
iId = iIdx - 1;
|
||||
/* generate sequence parameters set */
|
||||
iId = (SPS_LISTING & pCtx->pSvcParam->iSpsPpsIdStrategy) ? iIdx : 0;
|
||||
|
||||
WelsLoadNal (pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST);
|
||||
WelsWriteSpsNal (&pCtx->pSpsArray[iId], &pCtx->pOut->sBsWrite,
|
||||
& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS].iParaSetIdDelta[0]));
|
||||
WelsUnloadNal (pCtx->pOut);
|
||||
|
||||
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
|
||||
pCtx->iFrameBsSize - pCtx->iPosBsBuffer,//available buffer to be written, so need to substract the used length
|
||||
pCtx->pFrameBs + pCtx->iPosBsBuffer,
|
||||
&iNalLength);
|
||||
WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
|
||||
pNalLen[iCountNal] = iNalLength;
|
||||
|
||||
pCtx->iPosBsBuffer += iNalLength;
|
||||
iSize += iNalLength;
|
||||
|
||||
++ iIdx;
|
||||
++ iCountNal;
|
||||
}
|
||||
|
||||
/* write all Subset SPS */
|
||||
iIdx = 0;
|
||||
while (iIdx < pCtx->iSubsetSpsNum) {
|
||||
iNal = pCtx->pOut->iNalIndex;
|
||||
|
||||
if (INCREASING_ID == pCtx->pSvcParam->iSpsPpsIdStrategy) {
|
||||
#if _DEBUG
|
||||
pCtx->sPSOVector.iSpsPpsIdStrategy = INCREASING_ID;
|
||||
assert (iIdx < MAX_DQ_LAYER_NUM);
|
||||
#endif
|
||||
|
||||
ParasetIdAdditionIdAdjust (& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS]),
|
||||
pCtx->pSubsetArray[iIdx].pSps.uiSpsId,
|
||||
MAX_SPS_COUNT);
|
||||
}
|
||||
|
||||
iId = iIdx;
|
||||
|
||||
/* generate Subset SPS */
|
||||
WelsLoadNal (pCtx->pOut, NAL_UNIT_SUBSET_SPS, NRI_PRI_HIGHEST);
|
||||
@ -2895,15 +3176,6 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
|
||||
WelsWriteSubsetSpsSyntax (&pCtx->pSubsetArray[iId], &pCtx->pOut->sBsWrite,
|
||||
& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS].iParaSetIdDelta[0]));
|
||||
WelsUnloadNal (pCtx->pOut);
|
||||
} else {
|
||||
iId = 0;
|
||||
|
||||
/* generate sequence parameters set */
|
||||
WelsLoadNal (pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST);
|
||||
WelsWriteSpsNal (&pCtx->pSpsArray[0], &pCtx->pOut->sBsWrite,
|
||||
& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS].iParaSetIdDelta[0]));
|
||||
WelsUnloadNal (pCtx->pOut);
|
||||
}
|
||||
|
||||
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
|
||||
pCtx->iFrameBsSize - pCtx->iPosBsBuffer,//available buffer to be written, so need to substract the used length
|
||||
@ -2921,8 +3193,30 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
|
||||
|
||||
/* write all PPS */
|
||||
iIdx = 0;
|
||||
if ((SPS_PPS_LISTING == pCtx->pSvcParam->iSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
|
||||
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;
|
||||
}
|
||||
|
||||
while (iIdx < pCtx->iPpsNum) {
|
||||
if (pCtx->pSvcParam->bEnableSpsPpsIdAddition) {
|
||||
if ((INCREASING_ID & pCtx->pSvcParam->iSpsPpsIdStrategy)) {
|
||||
//para_set_type = 2: PPS, use MAX_PPS_COUNT
|
||||
ParasetIdAdditionIdAdjust (&pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS], pCtx->pPPSArray[iIdx].iPpsId,
|
||||
MAX_PPS_COUNT);
|
||||
@ -2931,7 +3225,8 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN
|
||||
iNal = pCtx->pOut->iNalIndex;
|
||||
/* generate picture parameter set */
|
||||
WelsLoadNal (pCtx->pOut, NAL_UNIT_PPS, NRI_PRI_HIGHEST);
|
||||
WelsWritePpsSyntax (&pCtx->pPPSArray[iIdx], &pCtx->pOut->sBsWrite, & (pCtx->sPSOVector));
|
||||
WelsWritePpsSyntax (&pCtx->pPPSArray[iIdx], &pCtx->pOut->sBsWrite,
|
||||
((SPS_PPS_LISTING != pCtx->pSvcParam->iSpsPpsIdStrategy)) ? (& (pCtx->sPSOVector)) : NULL);
|
||||
WelsUnloadNal (pCtx->pOut);
|
||||
|
||||
iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
|
||||
@ -3237,7 +3532,6 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour
|
||||
iDidList[iSpatialIdx] = iCurDid;
|
||||
|
||||
// Encoding this picture might mulitiple sQualityStat layers potentially be encoded as followed
|
||||
|
||||
switch (pParam->sSliceCfg.uiSliceMode) {
|
||||
case SM_FIXEDSLCNUM_SLICE:
|
||||
case SM_AUTO_SLICE: {
|
||||
@ -3829,7 +4123,8 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
|
||||
(pOldParam->iLTRRefNum != pNewParam->iLTRRefNum) ||
|
||||
(pOldParam->iMultipleThreadIdc != pNewParam->iMultipleThreadIdc) ||
|
||||
(pOldParam->bEnableBackgroundDetection != pNewParam->bEnableBackgroundDetection) ||
|
||||
(pOldParam->bEnableAdaptiveQuant != pNewParam->bEnableAdaptiveQuant);
|
||||
(pOldParam->bEnableAdaptiveQuant != pNewParam->bEnableAdaptiveQuant) ||
|
||||
(pOldParam->iSpsPpsIdStrategy != pNewParam->iSpsPpsIdStrategy);
|
||||
if (pNewParam->iMaxNumRefFrame > pOldParam->iMaxNumRefFrame) {
|
||||
bNeedReset = true;
|
||||
}
|
||||
@ -3876,35 +4171,75 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
|
||||
}
|
||||
|
||||
if (bNeedReset) {
|
||||
SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE];
|
||||
uint16_t uiTmpIdrPicId;//this is for LTR!
|
||||
SLogContext sLogCtx = (*ppCtx)->sLogCtx;
|
||||
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
|
||||
uiTmpIdrPicId = (*ppCtx)->uiIdrPicId;
|
||||
|
||||
int32_t iOldSpsPpsIdStrategy = pOldParam->iSpsPpsIdStrategy;
|
||||
SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE];
|
||||
int32_t iTmpPpsIdList[MAX_DQ_LAYER_NUM * MAX_PPS_COUNT];
|
||||
uint16_t uiTmpIdrPicId = (*ppCtx)->uiIdrPicId;//this is for LTR!
|
||||
|
||||
SEncoderStatistics sTempEncoderStatistics = (*ppCtx)->sEncoderStatistics;
|
||||
|
||||
SExistingParasetList sExistingParasetList;
|
||||
SExistingParasetList* pExistingParasetList = NULL;
|
||||
|
||||
if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->iSpsPpsIdStrategy)) {
|
||||
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 ((SPS_LISTING & iOldSpsPpsIdStrategy)
|
||||
&& (SPS_LISTING & pNewParam->iSpsPpsIdStrategy)) {
|
||||
pExistingParasetList = &sExistingParasetList;
|
||||
sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
|
||||
sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
|
||||
memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
|
||||
memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
|
||||
}
|
||||
|
||||
if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
|
||||
&& (SPS_PPS_LISTING == pNewParam->iSpsPpsIdStrategy)) {
|
||||
pExistingParasetList = &sExistingParasetList;
|
||||
sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
|
||||
sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
|
||||
sExistingParasetList.uiInUsePpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
|
||||
memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
|
||||
memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
|
||||
memcpy (sExistingParasetList.sPps, (*ppCtx)->pPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
|
||||
|
||||
memcpy (iTmpPpsIdList, ((*ppCtx)->sPSOVector.iPpsIdList), MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WelsUninitEncoderExt (ppCtx);
|
||||
|
||||
/* Update new parameters */
|
||||
if (WelsInitEncoderExt (ppCtx, pNewParam, &sLogCtx))
|
||||
if (WelsInitEncoderExt (ppCtx, pNewParam, &sLogCtx, pExistingParasetList))
|
||||
return 1;
|
||||
|
||||
// reset the scaled spatial picture size
|
||||
(*ppCtx)->pVpp->WelsPreprocessReset (*ppCtx);
|
||||
//if WelsInitEncoderExt succeed
|
||||
|
||||
//load back the needed structure
|
||||
//for FLEXIBLE_PARASET_ID
|
||||
memcpy ((*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable,
|
||||
(PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
|
||||
//for LTR
|
||||
(*ppCtx)->uiIdrPicId = uiTmpIdrPicId;
|
||||
|
||||
//for sEncoderStatistics
|
||||
(*ppCtx)->sEncoderStatistics = sTempEncoderStatistics;
|
||||
|
||||
//load back the needed structure for iSpsPpsIdStrategy
|
||||
if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->iSpsPpsIdStrategy)) {
|
||||
memcpy ((*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable,
|
||||
(PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
|
||||
}
|
||||
|
||||
if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
|
||||
&& (SPS_PPS_LISTING == pNewParam->iSpsPpsIdStrategy)) {
|
||||
memcpy (((*ppCtx)->sPSOVector.iPpsIdList), iTmpPpsIdList, MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
|
||||
}
|
||||
} else {
|
||||
/* maybe adjustment introduced in bitrate or little settings adjustment and so on.. */
|
||||
pNewParam->iNumRefFrame = WELS_CLIP3 (pNewParam->iNumRefFrame, MIN_REF_PIC_COUNT,
|
||||
@ -3919,7 +4254,7 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa
|
||||
pOldParam->fMaxFrameRate = pNewParam->fMaxFrameRate; // maximal frame rate [Hz / fps]
|
||||
pOldParam->iComplexityMode = pNewParam->iComplexityMode; // color space of input sequence
|
||||
pOldParam->uiIntraPeriod = pNewParam->uiIntraPeriod; // intra period (multiple of GOP size as desired)
|
||||
pOldParam->bEnableSpsPpsIdAddition = pNewParam->bEnableSpsPpsIdAddition;
|
||||
pOldParam->iSpsPpsIdStrategy = pNewParam->iSpsPpsIdStrategy;
|
||||
pOldParam->bPrefixNalAddingCtrl = pNewParam->bPrefixNalAddingCtrl;
|
||||
pOldParam->iNumRefFrame = pNewParam->iNumRefFrame; // number of reference frame used
|
||||
pOldParam->uiGopSize = pNewParam->uiGopSize;
|
||||
|
@ -237,7 +237,8 @@ void WriteRefPicMarking (SBitStringAux* pBs, SSliceHeader* pSliceHeader, SNalUni
|
||||
}
|
||||
}
|
||||
|
||||
void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) {
|
||||
void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
|
||||
int32_t* pPpsIdDelta) {
|
||||
SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
|
||||
SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
|
||||
SSliceHeader* pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
|
||||
@ -246,7 +247,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[pSliceHeader->pPps->iPpsId]);
|
||||
BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + ((pPpsIdDelta != NULL) ? pPpsIdDelta[pSliceHeader->pPps->iPpsId] : 0));
|
||||
|
||||
BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
|
||||
|
||||
@ -301,7 +302,8 @@ void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCur
|
||||
}
|
||||
}
|
||||
|
||||
void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) {
|
||||
void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
|
||||
int32_t* pPpsIdDelta) {
|
||||
SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
|
||||
SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
|
||||
SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP;
|
||||
@ -312,7 +314,7 @@ 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[pSliceHeader->pPps->iPpsId]);
|
||||
BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + ((pPpsIdDelta != NULL) ? pPpsIdDelta[pSliceHeader->pPps->iPpsId] : 0));
|
||||
|
||||
BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
|
||||
|
||||
@ -727,11 +729,12 @@ int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const
|
||||
|
||||
WelsSliceHeaderExtInit (pEncCtx, pCurLayer, pCurSlice);
|
||||
|
||||
|
||||
g_pWelsWriteSliceHeader[pCurSlice->bSliceHeaderExtFlag] (pEncCtx, pBs, pCurLayer, pCurSlice,
|
||||
& (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0]));
|
||||
((SPS_PPS_LISTING != pEncCtx->pSvcParam->iSpsPpsIdStrategy) ? (&
|
||||
(pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0])) : NULL));
|
||||
|
||||
#if _DEBUG
|
||||
if (pEncCtx->sPSOVector.bEnableSpsPpsIdAddition) {
|
||||
if (INCREASING_ID & pEncCtx->sPSOVector.iSpsPpsIdStrategy) {
|
||||
const int32_t kiEncoderPpsId = pCurSlice->sSliceHeaderExt.sSliceHeader.pPps->iPpsId;
|
||||
const int32_t kiTmpPpsIdInBs = kiEncoderPpsId +
|
||||
pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[ kiEncoderPpsId ];
|
||||
|
@ -332,7 +332,7 @@ int CWelsH264SVCEncoder::InitializeInternal (SWelsSvcCodingParam* pCfg) {
|
||||
m_iMaxPicHeight = pCfg->iPicHeight;
|
||||
|
||||
TraceParamInfo (pCfg);
|
||||
if (WelsInitEncoderExt (&m_pEncContext, pCfg, &m_pWelsTrace->m_sLogCtx)) {
|
||||
if (WelsInitEncoderExt (&m_pEncContext, pCfg, &m_pWelsTrace->m_sLogCtx, NULL)) {
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.");
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_DEBUG,
|
||||
"Problematic Input Base Param: iUsageType=%d, Resolution=%dx%d, FR=%f, TLayerNum=%d, DLayerNum=%d",
|
||||
@ -477,6 +477,7 @@ int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR) {
|
||||
}
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
||||
"CWelsH264SVCEncoder::ForceIntraFrame(), bIDR= %d", bIDR);
|
||||
|
||||
ForceCodingIDR (m_pEncContext);
|
||||
|
||||
m_pEncContext->sEncoderStatistics.uiIDRReqNum++;
|
||||
@ -486,8 +487,8 @@ int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR) {
|
||||
void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) {
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
||||
"iUsageType = %d,iPicWidth= %d;iPicHeight= %d;iTargetBitrate= %d;iMaxBitrate= %d;iRCMode= %d;iPaddingFlag= %d;iTemporalLayerNum= %d;iSpatialLayerNum= %d;fFrameRate= %.6ff;uiIntraPeriod= %d;\
|
||||
bEnableSpsPpsIdAddition = %d;bPrefixNalAddingCtrl = %d;bEnableDenoise= %d;bEnableBackgroundDetection= %d;bEnableAdaptiveQuant= %d;bEnableFrameSkip= %d;bEnableLongTermReference= %d;iLtrMarkPeriod= %d;\
|
||||
iComplexityMode = %d;iNumRefFrame = %d;iEntropyCodingModeFlag = %d;uiMaxNalSize = %d;iLTRRefNum = %d;iMultipleThreadIdc = %d;iLoopFilterDisableIdc = %d",
|
||||
iSpsPpsIdStrategy = %d;bPrefixNalAddingCtrl = %d;bEnableDenoise= %d;bEnableBackgroundDetection= %d;bEnableAdaptiveQuant= %d;bEnableFrameSkip= %d;bEnableLongTermReference= %d;iLtrMarkPeriod= %d;\
|
||||
iComplexityMode = %d;iNumRefFrame = %d;iEntropyCodingModeFlag = %d;uiMaxNalSize = %d;iLTRRefNum = %d;iMultipleThreadIdc = %d;iLoopFilterDisableIdc = %d (offset(alpha/beta): %d,%d)",
|
||||
pParam->iUsageType,
|
||||
pParam->iPicWidth,
|
||||
pParam->iPicHeight,
|
||||
@ -499,7 +500,7 @@ void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) {
|
||||
pParam->iSpatialLayerNum,
|
||||
pParam->fMaxFrameRate,
|
||||
pParam->uiIntraPeriod,
|
||||
pParam->bEnableSpsPpsIdAddition,
|
||||
pParam->iSpsPpsIdStrategy,
|
||||
pParam->bPrefixNalAddingCtrl,
|
||||
pParam->bEnableDenoise,
|
||||
pParam->bEnableBackgroundDetection,
|
||||
@ -513,7 +514,9 @@ void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) {
|
||||
pParam->uiMaxNalSize,
|
||||
pParam->iLTRRefNum,
|
||||
pParam->iMultipleThreadIdc,
|
||||
pParam->iLoopFilterDisableIdc
|
||||
pParam->iLoopFilterDisableIdc,
|
||||
pParam->iLoopFilterAlphaC0Offset,
|
||||
pParam->iLoopFilterBetaOffset
|
||||
);
|
||||
int32_t i = 0;
|
||||
int32_t iSpatialLayers = (pParam->iSpatialLayerNum < MAX_SPATIAL_LAYER_NUM) ? (pParam->iSpatialLayerNum) :
|
||||
@ -706,16 +709,26 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
|
||||
#endif//OUTPUT_BIT_STREAM
|
||||
if (sEncodingParam.iSpatialLayerNum < 1
|
||||
|| sEncodingParam.iSpatialLayerNum > MAX_SPATIAL_LAYER_NUM) { // verify number of spatial layer
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
||||
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, iSpatialLayerNum(%d) failed!",
|
||||
sEncodingParam.iSpatialLayerNum);
|
||||
return cmInitParaError;
|
||||
}
|
||||
|
||||
if (sConfig.ParamTranscode (sEncodingParam)) {
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
||||
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ParamTranscode failed!");
|
||||
return cmInitParaError;
|
||||
}
|
||||
if (sConfig.iSpatialLayerNum < 1) {
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
||||
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, iSpatialLayerNum(%d) failed!",
|
||||
sConfig.iSpatialLayerNum);
|
||||
return cmInitParaError;
|
||||
}
|
||||
if (sConfig.DetermineTemporalSettings()) {
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
|
||||
"CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, DetermineTemporalSettings failed!");
|
||||
return cmInitParaError;
|
||||
}
|
||||
|
||||
@ -898,11 +911,17 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) {
|
||||
}
|
||||
break;
|
||||
case ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION: {
|
||||
bool iValue = * ((bool*)pOption);
|
||||
|
||||
m_pEncContext->pSvcParam->bEnableSpsPpsIdAddition = iValue;
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption enable SPS/PPS ID = %d ",
|
||||
m_pEncContext->pSvcParam->bEnableSpsPpsIdAddition);
|
||||
int32_t iValue = * ((int32_t*)pOption);
|
||||
if (((iValue > INCREASING_ID) || (m_pEncContext->pSvcParam->iSpsPpsIdStrategy > INCREASING_ID))
|
||||
&& m_pEncContext->pSvcParam->iSpsPpsIdStrategy != iValue) {
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
|
||||
" CWelsH264SVCEncoder::SetOption iSpsPpsIdStrategy changing in the middle of call is NOT allowed for iSpsPpsIdStrategy>INCREASING_ID: existing setting is %d and the new one is %d",
|
||||
m_pEncContext->pSvcParam->iSpsPpsIdStrategy, iValue);
|
||||
return cmInitParaError;
|
||||
}
|
||||
m_pEncContext->pSvcParam->iSpsPpsIdStrategy = iValue;
|
||||
WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption iSpsPpsIdStrategy = %d ",
|
||||
m_pEncContext->pSvcParam->iSpsPpsIdStrategy);
|
||||
}
|
||||
break;
|
||||
case ENCODER_OPTION_CURRENT_PATH: {
|
||||
|
@ -88,26 +88,25 @@ class EncodeDecodeTestBase : public ::testing::TestWithParam<EncodeDecodeFilePar
|
||||
BaseDecoderTest::TearDown();
|
||||
}
|
||||
|
||||
virtual void prepareParam (int iLayers, int iSlices, int width, int height, float framerate) {
|
||||
memset (¶m_, 0, sizeof (SEncParamExt));
|
||||
param_.iUsageType = CAMERA_VIDEO_REAL_TIME;
|
||||
param_.iPicWidth = width;
|
||||
param_.iPicHeight = height;
|
||||
param_.fMaxFrameRate = framerate;
|
||||
param_.iRCMode = RC_OFF_MODE; //rc off
|
||||
param_.iMultipleThreadIdc = 1; //single thread
|
||||
param_.iSpatialLayerNum = iLayers;
|
||||
param_.iNumRefFrame = AUTO_REF_PIC_COUNT;
|
||||
virtual void prepareParam (int iLayers, int iSlices, int width, int height, float framerate, SEncParamExt* pParam) {
|
||||
memset (pParam, 0, sizeof (SEncParamExt));
|
||||
pParam->iUsageType = CAMERA_VIDEO_REAL_TIME;
|
||||
pParam->iPicWidth = width;
|
||||
pParam->iPicHeight = height;
|
||||
pParam->fMaxFrameRate = framerate;
|
||||
pParam->iRCMode = RC_OFF_MODE; //rc off
|
||||
pParam->iMultipleThreadIdc = 1; //single thread
|
||||
pParam->iSpatialLayerNum = iLayers;
|
||||
pParam->iNumRefFrame = AUTO_REF_PIC_COUNT;
|
||||
for (int i = 0; i < iLayers; i++) {
|
||||
param_.sSpatialLayers[i].iVideoWidth = width >> (iLayers - i - 1);
|
||||
param_.sSpatialLayers[i].iVideoHeight = height >> (iLayers - i - 1);
|
||||
param_.sSpatialLayers[i].fFrameRate = framerate;
|
||||
param_.sSpatialLayers[i].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
|
||||
param_.sSpatialLayers[i].sSliceCfg.sSliceArgument.uiSliceNum = iSlices;
|
||||
pParam->sSpatialLayers[i].iVideoWidth = width >> (iLayers - i - 1);
|
||||
pParam->sSpatialLayers[i].iVideoHeight = height >> (iLayers - i - 1);
|
||||
pParam->sSpatialLayers[i].fFrameRate = framerate;
|
||||
pParam->sSpatialLayers[i].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
|
||||
pParam->sSpatialLayers[i].sSliceCfg.sSliceArgument.uiSliceNum = iSlices;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
virtual void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam) {
|
||||
//for encoder
|
||||
//I420: 1(Y) + 1/4(U) + 1/4(V)
|
||||
@ -147,6 +146,15 @@ class EncodeDecodeTestBase : public ::testing::TestWithParam<EncodeDecodeFilePar
|
||||
len = layerInfo.pNalLengthInByte[iSliceNum];
|
||||
}
|
||||
|
||||
|
||||
virtual int GetRandWidth() {
|
||||
return (WELS_CLIP3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 2, MAX_WIDTH));
|
||||
}
|
||||
|
||||
virtual int GetRandHeight() {
|
||||
return (WELS_CLIP3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 2, MAX_HEIGHT));
|
||||
}
|
||||
|
||||
protected:
|
||||
SEncParamExt param_;
|
||||
BufferedData buf_;
|
||||
@ -171,8 +179,8 @@ class EncodeDecodeTestAPI : public EncodeDecodeTestBase {
|
||||
EncodeDecodeTestBase::TearDown();
|
||||
}
|
||||
|
||||
void prepareParam (int iLayers, int iSlices, int width, int height, float framerate) {
|
||||
EncodeDecodeTestBase::prepareParam (iLayers, iSlices, width, height, framerate);
|
||||
void prepareParam (int iLayers, int iSlices, int width, int height, float framerate, SEncParamExt* pParam) {
|
||||
EncodeDecodeTestBase::prepareParam (iLayers, iSlices, width, height, framerate, pParam);
|
||||
}
|
||||
|
||||
void InitialEncDec (int iWidth, int iHeight);
|
||||
@ -192,6 +200,24 @@ class EncodeDecodeTestAPI : public EncodeDecodeTestBase {
|
||||
else if (1 == iCheckTypeIndex)
|
||||
ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
|
||||
}
|
||||
|
||||
void EncDecOneFrame (const int iWidth, const int iHeight, const int iFrame, FILE* pfEnc) {
|
||||
int iLen = 0, rv;
|
||||
InitialEncDec (iWidth, iHeight);
|
||||
EncodeOneFrame (iFrame);
|
||||
|
||||
//extract target layer data
|
||||
encToDecData (info, iLen);
|
||||
//call decoder
|
||||
unsigned char* pData[3] = { NULL };
|
||||
memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
|
||||
rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, iLen, pData, &dstBufInfo_);
|
||||
EXPECT_TRUE (rv == cmResultSuccess) << " rv = " << rv << " iFrameIdx = " << iFrame;
|
||||
|
||||
if (NULL != pfEnc) {
|
||||
fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, pfEnc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void EncodeDecodeTestAPI::InitialEncDec (int iWidth, int iHeight) {
|
||||
@ -234,7 +260,7 @@ void EncodeDecodeTestAPI::RandomParamExtCombination() {
|
||||
param_.iNumRefFrame = AUTO_REF_PIC_COUNT;
|
||||
param_.iMultipleThreadIdc = rand();
|
||||
|
||||
param_.bEnableSpsPpsIdAddition = (rand() % 2 == 0) ? false : true;
|
||||
param_.iSpsPpsIdStrategy = rand() % 3;
|
||||
param_.bPrefixNalAddingCtrl = (rand() % 2 == 0) ? false : true;
|
||||
param_.bEnableSSEI = (rand() % 2 == 0) ? false : true;
|
||||
param_.iPaddingFlag = rand() % 2;
|
||||
@ -462,7 +488,7 @@ static const EncodeDecodeFileParamBase kFileParamArray[] = {
|
||||
|
||||
TEST_P (EncodeDecodeTestAPI, DecoderVclNal) {
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -498,7 +524,7 @@ TEST_P (EncodeDecodeTestAPI, DecoderVclNal) {
|
||||
|
||||
TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) {
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -535,7 +561,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) {
|
||||
|
||||
TEST_P (EncodeDecodeTestAPI, GetOptionIDR) {
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -554,7 +580,8 @@ TEST_P (EncodeDecodeTestAPI, GetOptionIDR) {
|
||||
int32_t iSpsPpsIdAddition = 0;
|
||||
int iIdx = 0;
|
||||
while (iIdx <= p.numframes) {
|
||||
iSpsPpsIdAddition = rand() % 2;
|
||||
iSpsPpsIdAddition = rand() %
|
||||
2; //the current strategy supports more than 2 modes, but the switch between the modes>2 is not allowed
|
||||
iIDRPeriod = (rand() % 150) + 1;
|
||||
encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
|
||||
encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iSpsPpsIdAddition);
|
||||
@ -776,7 +803,7 @@ int SimulateNALLoss (const unsigned char* pSrc, int& iSrcLen, std::vector<SLost
|
||||
|
||||
TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLIDR) {
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -809,7 +836,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLLTR) {
|
||||
SLTRMarkingFeedback m_LTR_Marking_Feedback;
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -868,7 +895,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionLTR_Engine) {
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
m_LTR_Recover_Request.uiIDRPicId = 0;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -918,7 +945,7 @@ TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_DISABLE) {
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
m_LTR_Recover_Request.uiIDRPicId = 0;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.bEnableLongTermReference = true;
|
||||
param_.iLTRRefNum = 1;
|
||||
encoder_->Uninitialize();
|
||||
@ -985,7 +1012,7 @@ TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_SLICE_COPY) {
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
m_LTR_Recover_Request.uiIDRPicId = 0;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -1036,7 +1063,7 @@ TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_SLICE_COPY) {
|
||||
|
||||
TEST_P (EncodeDecodeTestAPI, InOutTimeStamp) {
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -1086,7 +1113,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_NOPREFIX) {
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
m_LTR_Recover_Request.uiIDRPicId = 0;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.bPrefixNalAddingCtrl = false;
|
||||
param_.iTemporalLayerNum = (rand() % 4) + 1;
|
||||
encoder_->Uninitialize();
|
||||
@ -1155,7 +1182,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_WITH_PREFIX_NOLOSS) {
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
m_LTR_Recover_Request.uiIDRPicId = 0;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.bPrefixNalAddingCtrl = true;
|
||||
param_.iTemporalLayerNum = (rand() % 4) + 1;
|
||||
param_.iSpatialLayerNum = 1;
|
||||
@ -1210,7 +1237,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionTid_SVC_L1_NOLOSS) {
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
m_LTR_Recover_Request.uiIDRPicId = 0;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (2, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (2, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iTemporalLayerNum = (rand() % 4) + 1;
|
||||
param_.iSpatialLayerNum = 2;
|
||||
encoder_->Uninitialize();
|
||||
@ -1266,7 +1293,7 @@ TEST_P (EncodeDecodeTestAPI, SetOption_Trace) {
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
m_LTR_Recover_Request.uiIDRPicId = 0;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iSpatialLayerNum = 1;
|
||||
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
@ -1330,7 +1357,7 @@ TEST_P (EncodeDecodeTestAPI, SetOption_Trace_NULL) {
|
||||
SLTRRecoverRequest m_LTR_Recover_Request;
|
||||
m_LTR_Recover_Request.uiIDRPicId = 0;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iSpatialLayerNum = 1;
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -1393,7 +1420,7 @@ TEST_P (EncodeDecodeTestAPI, SetOptionECIDC_GeneralSliceChange) {
|
||||
uint32_t uiEcIdc;
|
||||
uint32_t uiGet;
|
||||
EncodeDecodeFileParamBase p = GetParam();
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iSpatialLayerNum = 1;
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
@ -1473,7 +1500,7 @@ TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificFrameChange) {
|
||||
uint32_t uiEcIdc;
|
||||
uint32_t uiGet;
|
||||
EncodeDecodeFileParamBase p = kFileParamArray[0];
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iSpatialLayerNum = 1;
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
@ -1612,7 +1639,7 @@ TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificSliceChange_IDRLoss) {
|
||||
uint32_t uiEcIdc = 2; //default set as SLICE_COPY
|
||||
uint32_t uiGet;
|
||||
EncodeDecodeFileParamBase p = kFileParamArray[0];
|
||||
prepareParam (1, 2, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, 2, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iSpatialLayerNum = 1;
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
@ -1745,7 +1772,7 @@ TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificSliceChange_IDRNoLoss) {
|
||||
uint32_t uiEcIdc;
|
||||
uint32_t uiGet;
|
||||
EncodeDecodeFileParamBase p = kFileParamArray[0];
|
||||
prepareParam (1, 2, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, 2, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iSpatialLayerNum = 1;
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
@ -1914,7 +1941,7 @@ TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_I) {
|
||||
EncodeDecodeFileParamBase p = kSVCSwitch[0];
|
||||
p.width = p.width << 2;
|
||||
p.height = p.height << 2;
|
||||
prepareParam (4, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (4, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iTemporalLayerNum = (rand() % 4) + 1;
|
||||
param_.iSpatialLayerNum = 4;
|
||||
encoder_->Uninitialize();
|
||||
@ -1979,7 +2006,7 @@ TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_P) {
|
||||
int iLastDid = 0;
|
||||
p.width = p.width << 2;
|
||||
p.height = p.height << 2;
|
||||
prepareParam (4, p.slicenum, p.width, p.height, p.frameRate);
|
||||
prepareParam (4, p.slicenum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iTemporalLayerNum = (rand() % 4) + 1;
|
||||
param_.iSpatialLayerNum = 4;
|
||||
encoder_->Uninitialize();
|
||||
@ -2065,7 +2092,7 @@ TEST_F (EncodeDecodeTestAPI, SetOptionEncParamExt) {
|
||||
int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
|
||||
int iSliceNum = 1;
|
||||
encoder_->GetDefaultParams (¶m_);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, ¶m_);
|
||||
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
@ -2128,8 +2155,8 @@ class DecodeCrashTestAPI : public EncodeDecodeTestBase {
|
||||
ASSERT_TRUE (ucBuf_ == NULL);
|
||||
}
|
||||
|
||||
void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate) {
|
||||
EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate);
|
||||
void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
|
||||
EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
|
||||
}
|
||||
|
||||
void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam);
|
||||
@ -2203,11 +2230,11 @@ TEST_F (DecodeCrashTestAPI, DecoderCrashTest) {
|
||||
int iSeed = rand() % 3; //3 indicates the length of kParamArray[] used in the following
|
||||
EncodeDecodeParamBase p = kParamArray[iSeed];
|
||||
//Initialize Encoder
|
||||
prepareParam (1, 1, p.width, p.height, p.frameRate);
|
||||
prepareParam (1, 1, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iRCMode = RC_BITRATE_MODE;
|
||||
param_.iTargetBitrate = p.iTarBitrate;
|
||||
param_.uiIntraPeriod = 0;
|
||||
param_.bEnableSpsPpsIdAddition = true;
|
||||
param_.iSpsPpsIdStrategy = INCREASING_ID;
|
||||
param_.bEnableBackgroundDetection = true;
|
||||
param_.bEnableSceneChangeDetect = true;
|
||||
param_.bPrefixNalAddingCtrl = true;
|
||||
@ -2398,7 +2425,7 @@ TEST_F (DecodeParseAPI, ParseOnly_General) {
|
||||
p.height = iHeight_;
|
||||
p.frameRate = kiFrameRate;
|
||||
p.numframes = kiFrameNum;
|
||||
prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate);
|
||||
prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iSpatialLayerNum = kiTotalLayer;
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
@ -2475,7 +2502,7 @@ TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) {
|
||||
p.height = iHeight_;
|
||||
p.frameRate = kiFrameRate;
|
||||
p.numframes = 5;
|
||||
prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate);
|
||||
prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, ¶m_);
|
||||
param_.iSpatialLayerNum = iLayerNum;
|
||||
encoder_->Uninitialize();
|
||||
int rv = encoder_->InitializeExt (¶m_);
|
||||
@ -2525,3 +2552,434 @@ TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) {
|
||||
} //while
|
||||
}
|
||||
|
||||
//#define DEBUG_FILE_SAVE2
|
||||
TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING1) {
|
||||
|
||||
int iWidth = GetRandWidth();
|
||||
int iHeight = GetRandHeight();
|
||||
float fFrameRate = rand() + 0.5f;
|
||||
int iEncFrameNum = 0;
|
||||
int iSpatialLayerNum = 1;
|
||||
int iSliceNum = 1;
|
||||
|
||||
// prepare params
|
||||
SEncParamExt sParam1;
|
||||
SEncParamExt sParam2;
|
||||
SEncParamExt sParam3;
|
||||
encoder_->GetDefaultParams (&sParam1);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
|
||||
sParam1.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
|
||||
//prepare param2
|
||||
memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
|
||||
while (sParam2.iPicWidth == sParam1.iPicWidth) {
|
||||
sParam2.iPicWidth = GetRandWidth();
|
||||
}
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
|
||||
sParam2.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
|
||||
//prepare param3
|
||||
memcpy (&sParam3, &sParam1, sizeof (SEncParamExt));
|
||||
while (sParam3.iPicHeight == sParam1.iPicHeight) {
|
||||
sParam3.iPicHeight = GetRandHeight();
|
||||
}
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, sParam3.iPicWidth, sParam3.iPicHeight, fFrameRate, &sParam3);
|
||||
sParam3.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
|
||||
|
||||
//prepare output if needed
|
||||
FILE* fEnc = NULL;
|
||||
#ifdef DEBUG_FILE_SAVE2
|
||||
fEnc = fopen ("enc2.264", "wb");
|
||||
#endif
|
||||
|
||||
// Test part#1
|
||||
// step#1: pParam1
|
||||
//int TraceLevel = WELS_LOG_INFO;
|
||||
//encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &TraceLevel);
|
||||
int rv = encoder_->InitializeExt (&sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
|
||||
sParam1.iPicHeight;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// new IDR
|
||||
rv = encoder_->ForceIntraFrame (true);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// step#2: pParam2
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam2.iPicWidth << "x" <<
|
||||
sParam2.iPicHeight;
|
||||
EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// new IDR
|
||||
rv = encoder_->ForceIntraFrame (true);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// step#3: back to pParam1
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
|
||||
sParam1.iPicHeight;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// step#4: back to pParam2
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv << sParam2.iPicWidth << sParam2.iPicHeight;
|
||||
EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
#ifdef DEBUG_FILE_SAVE2
|
||||
fclose (fEnc);
|
||||
#endif
|
||||
rv = encoder_->Uninitialize();
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
|
||||
// Test part#2
|
||||
// step#1: pParam1
|
||||
rv = encoder_->InitializeExt (&sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt Failed: rv = " << rv;
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam3);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam3: rv = " << rv;
|
||||
|
||||
#ifdef DEBUG_FILE_SAVE2
|
||||
fEnc = fopen ("enc3.264", "wb");
|
||||
#endif
|
||||
iEncFrameNum = 0;
|
||||
EncDecOneFrame (sParam3.iPicWidth, sParam3.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
|
||||
EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
#ifdef DEBUG_FILE_SAVE2
|
||||
fclose (fEnc);
|
||||
#endif
|
||||
rv = encoder_->Uninitialize();
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
}
|
||||
|
||||
#define DEBUG_FILE_SAVE5
|
||||
TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING2) {
|
||||
//usage 3: 2 Params with different num_ref, encode IDR0, P1, IDR2;
|
||||
//the bs will show two SPS and different PPS
|
||||
|
||||
int iWidth = GetRandWidth();
|
||||
int iHeight = GetRandHeight();
|
||||
float fFrameRate = rand() + 0.5f;
|
||||
int iEncFrameNum = 0;
|
||||
int iSpatialLayerNum = 1;
|
||||
int iSliceNum = 1;
|
||||
|
||||
// prepare params
|
||||
SEncParamExt sParam1;
|
||||
SEncParamExt sParam2;
|
||||
encoder_->GetDefaultParams (&sParam1);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
|
||||
sParam1.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
|
||||
sParam1.iTemporalLayerNum = 1;
|
||||
//prepare param2
|
||||
memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
|
||||
sParam2.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
|
||||
sParam2.iTemporalLayerNum = 3;
|
||||
|
||||
//prepare output if needed
|
||||
FILE* fEnc = NULL;
|
||||
#ifdef DEBUG_FILE_SAVE5
|
||||
fEnc = fopen ("encID2.264", "wb");
|
||||
#endif
|
||||
|
||||
// step#1: pParam1
|
||||
int rv = encoder_->InitializeExt (&sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
|
||||
sParam1.iPicHeight;
|
||||
|
||||
// step#2: pParam2
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
|
||||
|
||||
// step#3: set back to pParam1, with a smaller num_ref, it still uses the previous SPS
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam1: rv = " << rv;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// new IDR, PPS increases
|
||||
rv = encoder_->ForceIntraFrame (true);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
rv = encoder_->Uninitialize();
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
|
||||
#ifdef DEBUG_FILE_SAVE5
|
||||
fclose (fEnc);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING3) {
|
||||
|
||||
int iWidth = GetRandWidth();
|
||||
int iHeight = GetRandHeight();
|
||||
float fFrameRate = rand() + 0.5f;
|
||||
int iEncFrameNum = 0;
|
||||
int iSpatialLayerNum = 1;
|
||||
int iSliceNum = 1;
|
||||
|
||||
// prepare params
|
||||
SEncParamExt sParam1;
|
||||
SEncParamExt sParam2;
|
||||
encoder_->GetDefaultParams (&sParam1);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
|
||||
sParam1.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
|
||||
|
||||
//prepare output if needed
|
||||
FILE* fEnc = NULL;
|
||||
#ifdef DEBUG_FILE_SAVE2
|
||||
fEnc = fopen ("enc4.264", "wb");
|
||||
#endif
|
||||
|
||||
// step#1: pParam1
|
||||
int rv = encoder_->InitializeExt (&sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt Failed: rv = " << rv;
|
||||
|
||||
int max_count = 65; // make it more then twice as MAX_SPS_COUNT
|
||||
std::vector<int> vWidthTable;
|
||||
vWidthTable.push_back (sParam1.iPicWidth);
|
||||
|
||||
std::vector<int>::iterator vWidthTableIt;
|
||||
for (int times = 0; times < max_count; times++) {
|
||||
//prepare param2
|
||||
memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
|
||||
do {
|
||||
sParam2.iPicWidth = GetRandWidth();
|
||||
vWidthTableIt = std::find (vWidthTable.begin(), vWidthTable.end(), sParam2.iPicWidth);
|
||||
} while (vWidthTableIt == vWidthTable.end());
|
||||
vWidthTable.push_back (sParam2.iPicWidth);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
|
||||
sParam2.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
|
||||
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv << ", sParam2.iPicWidth=" <<
|
||||
sParam2.iPicWidth;
|
||||
} // end of setting loop
|
||||
|
||||
EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
#ifdef DEBUG_FILE_SAVE2
|
||||
fclose (fEnc);
|
||||
#endif
|
||||
rv = encoder_->Uninitialize();
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
}
|
||||
|
||||
//#define DEBUG_FILE_SAVE6
|
||||
TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING1) {
|
||||
//usage 1: 1 resolution Params, encode IDR0, P1, IDR2;
|
||||
//the bs will show same SPS and different PPS
|
||||
// PPS: pic_parameter_set_id 1 ( 0)
|
||||
// PPS: seq_parameter_set_id 1 ( 0)
|
||||
// PPS: pic_parameter_set_id 010 ( 1)
|
||||
// PPS: seq_parameter_set_id 1 ( 0)
|
||||
// SH: slice_type 011 ( 2)
|
||||
// SH: pic_parameter_set_id 1 ( 0)
|
||||
// SH: slice_type 1 ( 0)
|
||||
// SH: pic_parameter_set_id 1 ( 0)
|
||||
// SH: slice_type 011 ( 2)
|
||||
// SH: pic_parameter_set_id 010 ( 1)
|
||||
int iWidth = GetRandWidth();
|
||||
int iHeight = GetRandHeight();
|
||||
float fFrameRate = rand() + 0.5f;
|
||||
int iEncFrameNum = 0;
|
||||
int iSpatialLayerNum = 1;
|
||||
int iSliceNum = 1;
|
||||
|
||||
// prepare params
|
||||
SEncParamExt sParam1;
|
||||
encoder_->GetDefaultParams (&sParam1);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
|
||||
sParam1.iSpsPpsIdStrategy = SPS_PPS_LISTING;
|
||||
|
||||
//prepare output if needed
|
||||
FILE* fEnc = NULL;
|
||||
#ifdef DEBUG_FILE_SAVE6
|
||||
fEnc = fopen ("encLIST1.264", "wb");
|
||||
#endif
|
||||
|
||||
// step#1: pParam1
|
||||
int rv = encoder_->InitializeExt (&sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
|
||||
sParam1.iPicHeight;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// new IDR
|
||||
rv = encoder_->ForceIntraFrame (true);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
rv = encoder_->Uninitialize();
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
|
||||
#ifdef DEBUG_FILE_SAVE6
|
||||
fclose (fEnc);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING2) {
|
||||
//usage 2: 2 resolution Params, encode IDR0, IDR1, IDR2;
|
||||
//the bs will show two SPS and different PPS
|
||||
// === SPS LIST ===
|
||||
//SPS: seq_parameter_set_id 1 ( 0) -- PARAM1
|
||||
//SPS: seq_parameter_set_id 010 ( 1) -- PARAM2
|
||||
// === PPS LIST ===
|
||||
//PPS: pic_parameter_set_id 1 ( 0)
|
||||
//PPS: seq_parameter_set_id 1 ( 0)
|
||||
//PPS: pic_parameter_set_id 010 ( 1)
|
||||
//PPS: seq_parameter_set_id 010 ( 1)
|
||||
//PPS: pic_parameter_set_id 011 ( 2) -- PPS2 - SPS0
|
||||
//PPS: seq_parameter_set_id 1 ( 0)
|
||||
//PPS: pic_parameter_set_id 00100 ( 3) -- PPS3 - SPS1
|
||||
//PPS: seq_parameter_set_id 010 ( 1)
|
||||
//PPS: pic_parameter_set_id 00101 ( 4) -- PPS4 - SPS0
|
||||
//PPS: seq_parameter_set_id 1 ( 0)
|
||||
// === VCL LAYER ===
|
||||
//SH: slice_type 011 ( 2) -- PARAM2
|
||||
//SH: pic_parameter_set_id 010 ( 1) -- PPS1 - SPS1 - PARAM2
|
||||
//SH: slice_type 011 ( 2) -- PARAM1
|
||||
//SH: pic_parameter_set_id 011 ( 2) -- PPS2 - SPS0 - PARAM1
|
||||
//SH: slice_type 011 ( 2) -- PARAM1
|
||||
//SH: pic_parameter_set_id 00101 ( 4) -- PPS4 - SPS0 - PARAM1
|
||||
|
||||
int iWidth = GetRandWidth();
|
||||
int iHeight = GetRandHeight();
|
||||
float fFrameRate = rand() + 0.5f;
|
||||
int iEncFrameNum = 0;
|
||||
int iSpatialLayerNum = 1;
|
||||
int iSliceNum = 1;
|
||||
|
||||
// prepare params
|
||||
SEncParamExt sParam1;
|
||||
SEncParamExt sParam2;
|
||||
encoder_->GetDefaultParams (&sParam1);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
|
||||
sParam1.iSpsPpsIdStrategy = SPS_PPS_LISTING;
|
||||
//prepare param2
|
||||
memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
|
||||
while (sParam2.iPicWidth == sParam1.iPicWidth) {
|
||||
sParam2.iPicWidth = GetRandWidth();
|
||||
}
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
|
||||
sParam2.iSpsPpsIdStrategy = SPS_PPS_LISTING;
|
||||
|
||||
//prepare output if needed
|
||||
FILE* fEnc = NULL;
|
||||
#ifdef DEBUG_FILE_SAVE5
|
||||
fEnc = fopen ("encLIST2.264", "wb");
|
||||
#endif
|
||||
|
||||
// step#1: pParam1
|
||||
int rv = encoder_->InitializeExt (&sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
|
||||
sParam1.iPicHeight;
|
||||
|
||||
// step#2: pParam2
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
|
||||
EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// step#3: back to pParam1, SHOULD NOT encounter ERROR
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
|
||||
sParam1.iPicHeight;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// new IDR
|
||||
rv = encoder_->ForceIntraFrame (true);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
rv = encoder_->Uninitialize();
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
|
||||
#ifdef DEBUG_FILE_SAVE5
|
||||
fclose (fEnc);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING3) {
|
||||
|
||||
int iWidth = GetRandWidth();
|
||||
int iHeight = GetRandHeight();
|
||||
float fFrameRate = rand() + 0.5f;
|
||||
int iEncFrameNum = 0;
|
||||
int iSpatialLayerNum = 1;
|
||||
int iSliceNum = 1;
|
||||
|
||||
// prepare params
|
||||
SEncParamExt sParam1;
|
||||
SEncParamExt sParam2;
|
||||
SEncParamExt sParam3;
|
||||
encoder_->GetDefaultParams (&sParam1);
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
|
||||
sParam1.iSpsPpsIdStrategy = SPS_PPS_LISTING;
|
||||
//prepare param2
|
||||
memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
|
||||
while (sParam2.iPicWidth == sParam1.iPicWidth) {
|
||||
sParam2.iPicWidth = GetRandWidth();
|
||||
}
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
|
||||
sParam2.iSpsPpsIdStrategy = SPS_PPS_LISTING;
|
||||
//prepare param3
|
||||
memcpy (&sParam3, &sParam1, sizeof (SEncParamExt));
|
||||
while (sParam3.iPicWidth == sParam1.iPicWidth || sParam3.iPicWidth == sParam2.iPicWidth) {
|
||||
sParam3.iPicWidth = GetRandWidth();
|
||||
}
|
||||
prepareParam (iSpatialLayerNum, iSliceNum, sParam3.iPicWidth, sParam3.iPicHeight, fFrameRate, &sParam3);
|
||||
sParam3.iSpsPpsIdStrategy = SPS_PPS_LISTING;
|
||||
|
||||
//prepare output if needed
|
||||
FILE* fEnc = NULL;
|
||||
#ifdef DEBUG_FILE_SAVE5
|
||||
fEnc = fopen ("enc4.264", "wb");
|
||||
#endif
|
||||
|
||||
// step#1: ordinary encoding
|
||||
int rv = encoder_->InitializeExt (&sParam1);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
|
||||
sParam1.iPicHeight;
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
|
||||
EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// step#2: set strategy for success
|
||||
int32_t iNewStra = SPS_PPS_LISTING;
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iNewStra);
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv << " iNewStra=" << iNewStra;
|
||||
|
||||
// step#3: setting new strategy, SHOULD encounter ERROR
|
||||
unsigned int TraceLevel = WELS_LOG_QUIET;
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &TraceLevel);
|
||||
ASSERT_TRUE (rv == cmResultSuccess);
|
||||
iNewStra = CONSTANT_ID;
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iNewStra);
|
||||
ASSERT_TRUE (rv != cmResultSuccess);
|
||||
|
||||
EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
|
||||
|
||||
// step#4: pParam3, SHOULD encounter ERROR
|
||||
rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam3);
|
||||
ASSERT_TRUE (rv != cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam3.iPicWidth << "x" <<
|
||||
sParam3.iPicHeight;
|
||||
|
||||
rv = encoder_->Uninitialize();
|
||||
ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
|
||||
|
||||
#ifdef DEBUG_FILE_SAVE5
|
||||
fclose (fEnc);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
122
test/encoder/EncUT_ParameterSetStrategy.cpp
Normal file
122
test/encoder/EncUT_ParameterSetStrategy.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include <stdlib.h>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "au_set.h"
|
||||
#include "param_svc.h"
|
||||
#include "parameter_sets.h"
|
||||
#include "wels_const.h"
|
||||
|
||||
using namespace WelsEnc;
|
||||
|
||||
class ParameterSetStrategyTest : public ::testing::Test {
|
||||
public:
|
||||
virtual void SetUp() {
|
||||
pMa = NULL;
|
||||
m_pSpsArray = NULL;
|
||||
m_pSubsetArray = NULL;
|
||||
|
||||
pMa = new CMemoryAlign (0);
|
||||
m_pSpsArray = (SWelsSPS*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SWelsSPS), "m_pSpsArray");
|
||||
ASSERT_TRUE (NULL != m_pSpsArray);
|
||||
m_pSubsetArray = (SSubsetSps*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SSubsetSps), "m_pSubsetArray");
|
||||
ASSERT_TRUE (NULL != m_pSubsetArray);
|
||||
|
||||
m_pSpsArrayPointer = &m_pSpsArray[0];
|
||||
m_pSubsetArrayPointer = &m_pSubsetArray[0];
|
||||
|
||||
}
|
||||
virtual void TearDown() {
|
||||
pMa->WelsFree (m_pSpsArray, "m_pSpsArray");
|
||||
pMa->WelsFree (m_pSubsetArray, "m_pSubsetArray");
|
||||
delete pMa;
|
||||
}
|
||||
void GenerateParam (SWelsSvcCodingParam* pParam);
|
||||
public:
|
||||
CMemoryAlign* pMa;
|
||||
SWelsSPS* m_pSpsArray;
|
||||
SSubsetSps* m_pSubsetArray;
|
||||
|
||||
SWelsSPS* m_pSpsArrayPointer;
|
||||
SSubsetSps* m_pSubsetArrayPointer;
|
||||
|
||||
};
|
||||
|
||||
void ParameterSetStrategyTest::GenerateParam (SWelsSvcCodingParam* pParam) {
|
||||
SEncParamBase sEncParamBase;
|
||||
//TODO: consider randomize it
|
||||
sEncParamBase.iUsageType = CAMERA_VIDEO_REAL_TIME;
|
||||
sEncParamBase.iPicWidth = 1280;
|
||||
sEncParamBase.iPicHeight = 720;
|
||||
sEncParamBase.iTargetBitrate = 1000000;
|
||||
sEncParamBase.iRCMode = RC_BITRATE_MODE;
|
||||
sEncParamBase.fMaxFrameRate = 30.0f;
|
||||
pParam->ParamBaseTranscode (sEncParamBase);
|
||||
}
|
||||
|
||||
TEST_F (ParameterSetStrategyTest, FindExistingSps) {
|
||||
int iDlayerIndex = 0;
|
||||
int iDlayerCount = 0;
|
||||
bool bUseSubsetSps = false;
|
||||
int iFoundId = -1;
|
||||
int iRet = 0;
|
||||
SSpatialLayerConfig* pDlayerParam;
|
||||
|
||||
//init parameter
|
||||
SWelsSvcCodingParam sParam1;
|
||||
GenerateParam (&sParam1);
|
||||
|
||||
//prepare first SPS
|
||||
int iCurSpsId = 0;
|
||||
int iCurSpsInUse = 1;
|
||||
m_pSpsArrayPointer = &m_pSpsArray[iCurSpsId];
|
||||
|
||||
pDlayerParam = & (sParam1.sSpatialLayers[iDlayerIndex]);
|
||||
iRet = WelsInitSps (m_pSpsArrayPointer, pDlayerParam, &sParam1.sDependencyLayers[iDlayerIndex], sParam1.uiIntraPeriod,
|
||||
sParam1.iMaxNumRefFrame,
|
||||
iCurSpsId, sParam1.bEnableFrameCroppingFlag, sParam1.iRCMode != RC_OFF_MODE, iDlayerCount);
|
||||
|
||||
// try finding #0
|
||||
iFoundId = FindExistingSps (&sParam1, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
|
||||
m_pSpsArray, m_pSubsetArray);
|
||||
EXPECT_EQ (iFoundId, iCurSpsId);
|
||||
|
||||
// try not finding
|
||||
SWelsSvcCodingParam sParam2 = sParam1;
|
||||
sParam2.iMaxNumRefFrame ++;
|
||||
iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
|
||||
m_pSpsArray, m_pSubsetArray);
|
||||
EXPECT_EQ (iFoundId, INVALID_ID);
|
||||
|
||||
// add new sps
|
||||
iCurSpsId = 1;
|
||||
m_pSpsArrayPointer = &m_pSpsArray[iCurSpsId];
|
||||
pDlayerParam = & (sParam2.sSpatialLayers[iDlayerIndex]);
|
||||
iRet = WelsInitSps (m_pSpsArrayPointer, pDlayerParam, &sParam2.sDependencyLayers[iDlayerIndex], sParam2.uiIntraPeriod,
|
||||
sParam2.iMaxNumRefFrame,
|
||||
iCurSpsId, sParam2.bEnableFrameCroppingFlag, sParam2.iRCMode != RC_OFF_MODE, iDlayerCount);
|
||||
iCurSpsInUse = 2;
|
||||
|
||||
// try finding #1
|
||||
iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
|
||||
m_pSpsArray, m_pSubsetArray);
|
||||
EXPECT_EQ (iFoundId, iCurSpsId);
|
||||
|
||||
// try finding #0
|
||||
iFoundId = FindExistingSps (&sParam1, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
|
||||
m_pSpsArray, m_pSubsetArray);
|
||||
EXPECT_EQ (iFoundId, 0);
|
||||
|
||||
// try not finding
|
||||
if (sParam2.sDependencyLayers[0].iActualWidth > 1) {
|
||||
|
||||
sParam2.sDependencyLayers[0].iActualWidth--;
|
||||
} else {
|
||||
sParam2.sDependencyLayers[0].iActualWidth++;
|
||||
}
|
||||
|
||||
iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
|
||||
m_pSpsArray, m_pSubsetArray);
|
||||
EXPECT_EQ (iFoundId, INVALID_ID);
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ ENCODER_UNITTEST_CPP_SRCS=\
|
||||
$(ENCODER_UNITTEST_SRCDIR)/EncUT_MemoryAlloc.cpp\
|
||||
$(ENCODER_UNITTEST_SRCDIR)/EncUT_MemoryZero.cpp\
|
||||
$(ENCODER_UNITTEST_SRCDIR)/EncUT_MotionEstimate.cpp\
|
||||
$(ENCODER_UNITTEST_SRCDIR)/EncUT_ParameterSetStrategy.cpp\
|
||||
$(ENCODER_UNITTEST_SRCDIR)/EncUT_Reconstruct.cpp\
|
||||
$(ENCODER_UNITTEST_SRCDIR)/EncUT_Sample.cpp\
|
||||
$(ENCODER_UNITTEST_SRCDIR)/EncUT_SVC_me.cpp\
|
||||
|
Loading…
x
Reference in New Issue
Block a user