History

Merge pull request #1732 from sijchen/sps_list2

[Encoder] add new SpsPpsStrategy and UT

ruil2 committed 11 years ago

Commit aea10172 parents 9ba316c 98ed30216 files · +1150 −161Browse files

Unified · Split

16 files
  1. codec/api/svc/codec_app_def.h +12 −1
  2. codec/console/enc/src/welsenc.cpp +4 −4
  3. codec/encoder/core/inc/au_set.h +19 −1
  4. codec/encoder/core/inc/encoder.h +1 −1
  5. codec/encoder/core/inc/encoder_context.h +2 −0
  6. codec/encoder/core/inc/extern.h +2 −1
  7. codec/encoder/core/inc/param_svc.h +15 −3
  8. codec/encoder/core/inc/wels_common_basis.h +7 −1
  9. codec/encoder/core/inc/wels_const.h +1 −0
  10. codec/encoder/core/src/au_set.cpp +11 −11
  11. codec/encoder/core/src/encoder_ext.cpp +408 −73
  12. codec/encoder/core/src/svc_encode_slice.cpp +10 −7
  13. codec/encoder/plus/src/welsEncoderExt.cpp +29 −10
  14. test/api/encode_decode_api_test.cpp +506 −48
  15. test/encoder/EncUT_ParameterSetStrategy.cpp +122 −0
  16. test/encoder/targets.mk +1 −0
codec/api/svc/codec_app_def.h+12−1
@@ -385,6 +385,17 @@ typedef enum { · 384 unmodified lines
385385 HIGH_COMPLEXITY ///< high complexity, lowest speed, high quality
386386 } ECOMPLEXITY_MODE;
387387
388+/**
389+ * @brief Enumulate for the stategy of SPS/PPS strategy
390+ */
391+typedef enum {
392+ CONSTANT_ID = 0, ///< constant id in SPS/PPS
393+ INCREASING_ID = 0x01, ///< SPS/PPS id increases at each IDR
394+ SPS_LISTING = 0x02, ///< using SPS in the existing list if possible
395+ SPS_LISTING_AND_PPS_INCREASING = 0x03,
396+ SPS_PPS_LISTING = 0x06,
397+} EParameterSetStrategy;
398+
388399 // TODO: Refine the parameters definition.
389400 /**
390401 * @brief SVC Encoding Parameters
@@ -421,7 +432,7 @@ typedef struct TagEncParamExt { · 30 unmodified lines
421432 ECOMPLEXITY_MODE iComplexityMode;
422433 unsigned int uiIntraPeriod; ///< period of Intra frame
423434 int iNumRefFrame; ///< number of reference frame used
424− bool bEnableSpsPpsIdAddition; ///< false:not adjust ID in SPS/PPS; true: adjust ID in SPS/PPS
435+ int iSpsPpsIdStrategy; ///< different stategy in adjust ID in SPS/PPS: 0- constant ID, 1-additional ID, 6-mapping and additional
425436 bool bPrefixNalAddingCtrl; ///< false:not use Prefix NAL; true: use Prefix NAL
426437 bool bEnableSSEI; ///< false:not use SSEI; true: use SSEI -- TODO: planning to remove the interface of SSEI
427438 bool bSimulcastAVC; ///< (when encoding more than 1 spatial layer) false: use SVC syntax for higher layers; true: use Simulcast AVC -- coming soon
codec/console/enc/src/welsenc.cpp+4−4
@@ -232,8 +232,8 @@ int ParseConfig (CReadConfig& cRdCfg, SSourcePicture* pSrcPic, SEncParamExt& pSv · 231 unmodified lines
232232 pSvcParam.uiIntraPeriod = atoi (strTag[1].c_str());
233233 } else if (strTag[0].compare ("MaxNalSize") == 0) {
234234 pSvcParam.uiMaxNalSize = atoi (strTag[1].c_str());
235− } else if (strTag[0].compare ("EnableSpsPpsIDAddition") == 0) {
236− pSvcParam.bEnableSpsPpsIdAddition = atoi (strTag[1].c_str()) ? true : false;
235+ } else if (strTag[0].compare ("SpsPpsIDStrategy") == 0) {
236+ pSvcParam.iSpsPpsIdStrategy = atoi (strTag[1].c_str());
237237 } else if (strTag[0].compare ("EnableScalableSEI") == 0) {
238238 pSvcParam.bEnableSSEI = atoi (strTag[1].c_str()) ? true : false;
239239 } else if (strTag[0].compare ("EnableFrameCropping") == 0) {
@@ -421,7 +421,7 @@ int ParseCommandLine (int argc, char** argv, SSourcePicture* pSrcPic, SEncParamE · 181 unmodified lines
421421 pSvcParam.uiMaxNalSize = atoi (argv[n++]);
422422
423423 else if (!strcmp (pCommand, "-spsid") && (n < argc))
424− pSvcParam.bEnableSpsPpsIdAddition = atoi (argv[n++]) ? true : false;
424+ pSvcParam.iSpsPpsIdStrategy = atoi (argv[n++]);
425425
426426 else if (!strcmp (pCommand, "-cabac") && (n < argc))
427427 pSvcParam.iEntropyCodingModeFlag = atoi (argv[n++]);
@@ -591,7 +591,7 @@ int FillSpecificParameters (SEncParamExt& sParam) { · 163 unmodified lines
591591 sParam.bEnableLongTermReference = 0; // long term reference control
592592 sParam.iLtrMarkPeriod = 30;
593593 sParam.uiIntraPeriod = 320; // period of Intra frame
594− sParam.bEnableSpsPpsIdAddition = 1;
594+ sParam.iSpsPpsIdStrategy = INCREASING_ID;
595595 sParam.bPrefixNalAddingCtrl = 0;
596596 sParam.iComplexityMode = MEDIUM_COMPLEXITY;
597597 int iIndexLayer = 0;
codec/encoder/core/inc/au_set.h+19−1
@@ -141,8 +141,26 @@ int32_t WelsInitPps (SWelsPPS* pPps, · 140 unmodified lines
141141 const bool kbDeblockingFilterPresentFlag,
142142 const bool kbUsingSubsetSps,
143143 const bool kbEntropyCodingModeFlag);
144+
144145 int32_t WelsCheckRefFrameLimitationNumRefFirst (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam);
145146 int32_t WelsCheckRefFrameLimitationLevelIdcFirst (SLogContext* pLogCtx, SWelsSvcCodingParam* pParam);
146−int32_t WelsAdjustLevel( SSpatialLayerConfig* pSpatialLayer);
147+
148+int32_t WelsAdjustLevel (SSpatialLayerConfig* pSpatialLayer);
149+
150+/*!
151+ * \brief check if the current parameter can found a presenting sps
152+ * \param pParam the current encoding paramter in SWelsSvcCodingParam
153+ * \param kbUseSubsetSps bool
154+ * \param iDlayerIndex int, the index of current D layer
155+ * \param iDlayerCount int, the number of total D layer
156+ * \param pSpsArray array of all the stored SPSs
157+ * \param pSubsetArray array of all the stored Subset-SPSs
158+ * \return 0 - successful
159+ * -1 - cannot find existing SPS for current encoder parameter
160+ */
161+int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
162+ const int32_t iDlayerCount, const int32_t iSpsNumInUse,
163+ SWelsSPS* pSpsArray,
164+ SSubsetSps* pSubsetArray);
147165 }
148166 #endif//WELS_ACCESS_UNIT_PARSER_H__
codec/encoder/core/inc/encoder.h+1−1
@@ -48,7 +48,7 @@ namespace WelsEnc { · 47 unmodified lines
4848 * \param pEncCtx sWelsEncCtx*
4949 * \return successful - 0; otherwise none 0 for failed
5050 */
51−int32_t RequestMemorySvc (sWelsEncCtx** ppCtx);
51+int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingParasetList);
5252
5353 /*!
5454 * \brief free memory in SVC core encoder
codec/encoder/core/inc/encoder_context.h+2−0
@@ -191,6 +191,7 @@ typedef struct TagWelsEncCtx { · 190 unmodified lines
191191 SSubsetSps* pSubsetArray; // MAX_SPS_COUNT by standard compatible
192192 SSubsetSps* pSubsetSps;
193193 int32_t iSpsNum; // number of pSps used
194+ int32_t iSubsetSpsNum; // number of pSps used
194195 int32_t iPpsNum; // number of pPps used
195196
196197 // Output
@@ -216,6 +217,7 @@ typedef struct TagWelsEncCtx { · 19 unmodified lines
216217 pDqIdcMap; // overall DQ map of full scalability in specific frame (All full D/T/Q layers involved) // pDqIdcMap[dq_index] for each SDqIdc pData
217218
218219 SParaSetOffset sPSOVector;
220+ SParaSetOffset* pPSOVector;
219221 CMemoryAlign* pMemAlign;
220222
221223 #if defined(STAT_OUTPUT)
codec/encoder/core/inc/extern.h+2−1
@@ -75,7 +75,8 @@ void GomValidCheck (const int32_t kiMbWidth, const int32_t kiMbHeight, int32_t* · 74 unmodified lines
7575 * \param para SWelsSvcCodingParam*
7676 * \return successful - 0; otherwise none 0 for failed
7777 */
78−int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pPara, SLogContext* pLogCtx);
78+int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pPara, SLogContext* pLogCtx,
79+ SExistingParasetList* pExistingParasetList);
7980
8081 /*!
8182 * \brief uninitialize Wels encoder core library
codec/encoder/core/inc/param_svc.h+15−3
@@ -162,7 +162,7 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt { · 161 unmodified lines
162162 param.bEnableAdaptiveQuant = true; // adaptive quantization control
163163 param.bEnableFrameSkip = true; // frame skipping
164164 param.bEnableLongTermReference = false; // long term reference control
165− param.bEnableSpsPpsIdAddition = true; // pSps pPps id addition control
165+ param.iSpsPpsIdStrategy = INCREASING_ID; // pSps pPps id addition control
166166 param.bPrefixNalAddingCtrl = false; // prefix NAL adding control
167167 param.iSpatialLayerNum = 1; // number of dependency(Spatial/CGS) layers used to be encoded
168168 param.iTemporalLayerNum = 1; // number of temporal layer specified
@@ -350,8 +350,8 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt { · 181 unmodified lines
350350
351351 bPrefixNalAddingCtrl = pCodingParam.bPrefixNalAddingCtrl;
352352
353− bEnableSpsPpsIdAddition =
354− pCodingParam.bEnableSpsPpsIdAddition;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference.
353+ iSpsPpsIdStrategy =
354+ pCodingParam.iSpsPpsIdStrategy;//For SVC meeting application, to avoid mosaic issue caused by cross-IDR reference.
355355 //SHOULD enable this feature.
356356
357357 SSpatialLayerInternal* pDlp = &sDependencyLayers[0];
@@ -477,6 +477,18 @@ typedef struct TagWelsSvcCodingParam: SEncParamExt { · 119 unmodified lines
477477
478478 } SWelsSvcCodingParam;
479479
480+
481+typedef struct TagExistingParasetList {
482+ SWelsSPS sSps[MAX_SPS_COUNT];
483+ SSubsetSps sSubsetSps[MAX_SPS_COUNT];
484+ SWelsPPS sPps[MAX_PPS_COUNT];
485+
486+ uint32_t uiInUseSpsNum;
487+ uint32_t uiInUseSubsetSpsNum;
488+ uint32_t uiInUsePpsNum;
489+} SExistingParasetList;
490+
491+
480492 static inline int32_t FreeCodingParam (SWelsSvcCodingParam** pParam, CMemoryAlign* pMa) {
481493 if (pParam == NULL || *pParam == NULL || pMa == NULL)
482494 return 1;
codec/encoder/core/inc/wels_common_basis.h+7−1
@@ -83,9 +83,15 @@ typedef struct TagParaSetOffset { · 82 unmodified lines
8383 bool
8484 bPpsIdMappingIntoSubsetsps[MAX_DQ_LAYER_NUM/*+1*/]; // need not extra +1 due no MGS and FMO case so far
8585
86+ 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
87+
8688 #if _DEBUG
87− bool bEnableSpsPpsIdAddition;
89+ int32_t iSpsPpsIdStrategy;
8890 #endif
91+
92+ uint32_t uiInUseSpsNum;
93+ uint32_t uiInUseSubsetSpsNum;
94+ uint32_t uiInUsePpsNum;
8995 } SParaSetOffset;
9096
9197
codec/encoder/core/inc/wels_const.h+1−0
@@ -171,6 +171,7 @@ · 170 unmodified lines
171171
172172 #define UNAVAILABLE_DQ_ID ((uint8_t)(-1))
173173 #define LAYER_NUM_EXCHANGEABLE 2
174+#define INVALID_ID (-1)
174175
175176 #define NAL_HEADER_ADD_0X30BYTES 50
176177
codec/encoder/core/src/au_set.cpp+11−11
@@ -336,27 +336,27 @@ int32_t WelsWriteSubsetSpsSyntax (SSubsetSps* pSubsetSps, SBitStringAux* pBitStr · 335 unmodified lines
336336 * \note Call it in case EWelsNalUnitType is PPS.
337337 *************************************************************************************
338338 */
339−int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, SParaSetOffset* sPSOVector) {
339+int32_t WelsWritePpsSyntax (SWelsPPS* pPps, SBitStringAux* pBitStringAux, SParaSetOffset* pPSOVector) {
340340 SBitStringAux* pLocalBitStringAux = pBitStringAux;
341341
342− bool bUsedSubset = sPSOVector->bPpsIdMappingIntoSubsetsps[pPps->iPpsId];
343− int32_t iParameterSetType = (bUsedSubset ? PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS);
342+ const int32_t kiParameterSetType = (pPSOVector != NULL) ? (pPSOVector->bPpsIdMappingIntoSubsetsps[pPps->iPpsId] ?
343+ PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS) : 0;
344344
345− BsWriteUE (pLocalBitStringAux, pPps->iPpsId +
346− sPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId]);
347− BsWriteUE (pLocalBitStringAux, pPps->iSpsId +
348− sPSOVector->sParaSetOffsetVariable[iParameterSetType].iParaSetIdDelta[pPps->iSpsId]);
345+ BsWriteUE (pLocalBitStringAux, pPps->iPpsId
346+ + ((pPSOVector != NULL) ? (pPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId]) : 0));
347+ BsWriteUE (pLocalBitStringAux, pPps->iSpsId
348+ + ((pPSOVector != NULL) ? (pPSOVector->sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[pPps->iSpsId]) : 0));
349349
350350 #if _DEBUG
351351 //SParaSetOffset use, 110421
352− if (sPSOVector->bEnableSpsPpsIdAddition) {
352+ if ((pPSOVector != NULL) && (INCREASING_ID & pPSOVector->iSpsPpsIdStrategy)) {
353353 const int32_t kiTmpSpsIdInBs = pPps->iSpsId +
354− sPSOVector->sParaSetOffsetVariable[iParameterSetType].iParaSetIdDelta[pPps->iSpsId];
354+ pPSOVector->sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[pPps->iSpsId];
355355 const int32_t tmp_pps_id_in_bs = pPps->iPpsId +
356− sPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId];
356+ pPSOVector->sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[pPps->iPpsId];
357357 assert (MAX_SPS_COUNT > kiTmpSpsIdInBs);
358358 assert (MAX_PPS_COUNT > tmp_pps_id_in_bs);
359− assert (sPSOVector->sParaSetOffsetVariable[iParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
359+ assert (pPSOVector->sParaSetOffsetVariable[kiParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
360360 }
361361 #endif
362362
codec/encoder/core/src/encoder_ext.cpp+408−73
@@ -323,6 +323,12 @@ int32_t ParamValidationExt (SLogContext* pLogCtx, SWelsSvcCodingParam* pCodingPa · 322 unmodified lines
323323 pCodingParam->bDeblockingParallelFlag = true;
324324 }
325325
326+ if (pCodingParam->iSpatialLayerNum > 1 && (SPS_LISTING & pCodingParam->iSpsPpsIdStrategy)) {
327+ WelsLog (pLogCtx, WELS_LOG_INFO,
328+ "ParamValidationExt(), iSpsPpsIdStrategy adjusted to CONSTANT_ID");
329+ pCodingParam->iSpsPpsIdStrategy = CONSTANT_ID;
330+ }
331+
326332 for (i = 0; i < pCodingParam->iSpatialLayerNum; ++ i) {
327333 SSpatialLayerConfig* pSpatialLayer = &pCodingParam->sSpatialLayers[i];
328334 const int32_t kiPicWidth = pSpatialLayer->iVideoWidth;
@@ -665,8 +671,12 @@ static inline int32_t AcquireLayersNals (sWelsEncCtx** ppCtx, SWelsSvcCodingPara · 336 unmodified lines
665671 ++ iDIndex;
666672 } while (iDIndex < iNumDependencyLayers);
667673
674+ // count parasets
668675 iCountNumNals += 1 + iNumDependencyLayers + (iCountNumLayers << 1) +
669− iCountNumLayers; // plus iCountNumLayers for reserved application
676+ iCountNumLayers // plus iCountNumLayers for reserved application
677+ + ((SPS_LISTING & pParam->iSpsPpsIdStrategy) ? MAX_SPS_COUNT : 0) //for Sps
678+ + (((SPS_LISTING & pParam->iSpsPpsIdStrategy) && (iNumDependencyLayers > 1)) ? MAX_SPS_COUNT : 0) //for SubsetSps
679+ + ((SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy) ? MAX_PPS_COUNT : 0);
670680
671681 // to check number of layers / nals / slices dependencies, 12/8/2010
672682 if (iCountNumLayers > MAX_LAYER_NUM_OF_FRAME) {
@@ -847,9 +857,9 @@ void FreeMbCache (SMbCache* pMbCache, CMemoryAlign* pMa) { · 174 unmodified lines
847857 }
848858 }
849859
850−int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
851− const int32_t iDlayerCount, const int32_t kiSpsId,
852− SWelsSPS*& pSps, SSubsetSps*& pSubsetSps) {
860+static int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
861+ const int32_t iDlayerCount, const int32_t kiSpsId,
862+ SWelsSPS*& pSps, SSubsetSps*& pSubsetSps) {
853863 int32_t iRet = 0;
854864
855865 if (!kbUseSubsetSps) {
@@ -866,9 +876,6 @@ int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const · 10 unmodified lines
866876 iRet = WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
867877 pParam->iMaxNumRefFrame,
868878 kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
869−
870−
871−
872879 } else {
873880 iRet = WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
874881 pParam->iMaxNumRefFrame,
@@ -877,12 +884,131 @@ int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const · 2 unmodified lines
877884 return iRet;
878885 }
879886
887+static bool CheckMatchedSps (SWelsSPS* const pSps1, SWelsSPS* const pSps2) {
888+
889+ if ((pSps1->iMbWidth != pSps2->iMbWidth)
890+ || (pSps1->iMbHeight != pSps2->iMbHeight)) {
891+ return false;
892+ }
893+
894+ if ((pSps1->uiLog2MaxFrameNum != pSps2->uiLog2MaxFrameNum)
895+ || (pSps1->iLog2MaxPocLsb != pSps2->iLog2MaxPocLsb)) {
896+ return false;
897+ }
898+
899+ if (pSps1->iNumRefFrames != pSps2->iNumRefFrames) {
900+ return false;
901+ }
902+
903+ if ((pSps1->bFrameCroppingFlag != pSps2->bFrameCroppingFlag)
904+ || (pSps1->sFrameCrop.iCropLeft != pSps2->sFrameCrop.iCropLeft)
905+ || (pSps1->sFrameCrop.iCropRight != pSps2->sFrameCrop.iCropRight)
906+ || (pSps1->sFrameCrop.iCropTop != pSps2->sFrameCrop.iCropTop)
907+ || (pSps1->sFrameCrop.iCropBottom != pSps2->sFrameCrop.iCropBottom)
908+ ) {
909+ return false;
910+ }
911+
912+ if ((pSps1->uiProfileIdc != pSps2->uiProfileIdc)
913+ || (pSps1->bConstraintSet0Flag != pSps2->bConstraintSet0Flag)
914+ || (pSps1->bConstraintSet1Flag != pSps2->bConstraintSet1Flag)
915+ || (pSps1->bConstraintSet2Flag != pSps2->bConstraintSet2Flag)
916+ || (pSps1->bConstraintSet3Flag != pSps2->bConstraintSet3Flag)
917+ || (pSps1->iLevelIdc != pSps2->iLevelIdc)) {
918+ return false;
919+ }
920+
921+ return true;
922+}
923+
924+static bool CheckMatchedSubsetSps (SSubsetSps* const pSubsetSps1, SSubsetSps* const pSubsetSps2) {
925+ if (!CheckMatchedSps (&pSubsetSps1->pSps, &pSubsetSps2->pSps)) {
926+ return false;
927+ }
928+
929+ if ((pSubsetSps1->sSpsSvcExt.iExtendedSpatialScalability != pSubsetSps2->sSpsSvcExt.iExtendedSpatialScalability)
930+ || (pSubsetSps1->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag)
931+ || (pSubsetSps1->sSpsSvcExt.bSeqTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bSeqTcoeffLevelPredFlag)
932+ || (pSubsetSps1->sSpsSvcExt.bSliceHeaderRestrictionFlag != pSubsetSps2->sSpsSvcExt.bSliceHeaderRestrictionFlag)) {
933+ return false;
934+ }
935+
936+ return true;
937+}
938+
939+int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
940+ const int32_t iDlayerCount, const int32_t iSpsNumInUse,
941+ SWelsSPS* pSpsArray,
942+ SSubsetSps* pSubsetArray) {
943+ SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
944+
945+ assert (iSpsNumInUse <= MAX_SPS_COUNT);
946+ if (!kbUseSubsetSps) {
947+ SWelsSPS sTmpSps;
948+ WelsInitSps (&sTmpSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
949+ pParam->iMaxNumRefFrame,
950+ 0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
951+ for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
952+ if (CheckMatchedSps (&sTmpSps, &pSpsArray[iId])) {
953+ return iId;
954+ }
955+ }
956+ } else {
957+ SSubsetSps sTmpSubsetSps;
958+ WelsInitSubsetSps (&sTmpSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
959+ pParam->iMaxNumRefFrame,
960+ 0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE);
961+
962+ for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
963+ if (CheckMatchedSubsetSps (&sTmpSubsetSps, &pSubsetArray[iId])) {
964+ return iId;
965+ }
966+ }
967+ }
968+
969+ return INVALID_ID;
970+}
971+
972+int32_t FindExistingPps (SWelsSPS* pSps, SSubsetSps* pSubsetSps, const bool kbUseSubsetSps, const int32_t iSpsId,
973+ const bool kbEntropyCodingFlag, const int32_t iPpsNumInUse,
974+ SWelsPPS* pPpsArray) {
975+#if !defined(DISABLE_FMO_FEATURE)
976+ // feature not supported yet
977+ return INVALID_ID;
978+#endif//!DISABLE_FMO_FEATURE
979+
980+ SWelsPPS sTmpPps;
981+ WelsInitPps (&sTmpPps,
982+ pSps,
983+ pSubsetSps,
984+ 0,
985+ true,
986+ kbUseSubsetSps,
987+ kbEntropyCodingFlag);
988+
989+ assert (iPpsNumInUse <= MAX_PPS_COUNT);
990+ for (int32_t iId = 0; iId < iPpsNumInUse; iId++) {
991+ if ((sTmpPps.iSpsId == pPpsArray[iId].iSpsId)
992+ && (sTmpPps.bEntropyCodingModeFlag == pPpsArray[iId].bEntropyCodingModeFlag)
993+ && (sTmpPps.iPicInitQp == pPpsArray[iId].iPicInitQp)
994+ && (sTmpPps.iPicInitQs == pPpsArray[iId].iPicInitQs)
995+ && (sTmpPps.uiChromaQpIndexOffset == pPpsArray[iId].uiChromaQpIndexOffset)
996+ && (sTmpPps.bDeblockingFilterControlPresentFlag == pPpsArray[iId].bDeblockingFilterControlPresentFlag)
997+ ) {
998+ return iId;
999+ }
1000+ }
1001+
1002+ return INVALID_ID;
1003+}
1004+
1005+
8801006 /*!
8811007 * \brief initialize ppDqLayerList and slicepEncCtx_list due to count number of layers available
8821008 * \pParam pCtx sWelsEncCtx*
8831009 * \return 0 - successful; otherwise failed
8841010 */
885−static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) {
1011+static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingParasetList) {
8861012 SWelsSvcCodingParam* pParam = NULL;
8871013 SWelsSPS* pSps = NULL;
8881014 SSubsetSps* pSubsetSps = NULL;
@@ -1045,14 +1171,51 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) { · 156 unmodified lines
10451171 }
10461172
10471173 // for dynamically malloc for parameter sets memory instead of maximal items for standard to reduce size, 3/18/2010
1048− (*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (iDlayerCount * sizeof (SWelsPPS), "pPPSArray");
1049− WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
1174+ // SPS
1175+ if (! (SPS_LISTING & pParam->iSpsPpsIdStrategy)) {
1176+ (*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (sizeof (SWelsSPS), "pSpsArray");
1177+ WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
1178+ if (iDlayerCount > 1) {
1179+ (*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMalloc ((iDlayerCount - 1) * sizeof (SSubsetSps), "pSubsetArray");
1180+ WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc (ppCtx))
1181+ }
1182+ } else {
1183+ // pParam->iSpsPpsIdStrategy == SPS_LISTING_AND_PPS_INCREASING
1184+ // new memory
1185+ (*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SWelsSPS), "pSpsArray");
1186+ WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
10501187
1051− (*ppCtx)->pSpsArray = (SWelsSPS*)pMa->WelsMalloc (sizeof (SWelsSPS), "pSpsArray");
1052− WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSpsArray), FreeMemorySvc (ppCtx))
1053− if (iDlayerCount > 1) {
1054− (*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMalloc ((iDlayerCount - 1) * sizeof (SSubsetSps), "pSubsetArray");
1188+ (*ppCtx)->pSubsetArray = (SSubsetSps*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SSubsetSps), "pSubsetArray");
10551189 WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pSubsetArray), FreeMemorySvc (ppCtx))
1190+
1191+ // copy from existing if the pointer exists
1192+ if (NULL != pExistingParasetList) {
1193+ (*ppCtx)->sPSOVector.uiInUseSpsNum = pExistingParasetList->uiInUseSpsNum;
1194+ (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = pExistingParasetList->uiInUseSubsetSpsNum;
1195+ memcpy ((*ppCtx)->pSpsArray, pExistingParasetList->sSps, MAX_SPS_COUNT * sizeof (SWelsSPS));
1196+ memcpy ((*ppCtx)->pSubsetArray, pExistingParasetList->sSubsetSps, MAX_SPS_COUNT * sizeof (SSubsetSps));
1197+ }
1198+ }
1199+ // PPS
1200+ if (! (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy)) {
1201+ (*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (iDlayerCount * sizeof (SWelsPPS), "pPPSArray");
1202+ WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
1203+ } else {
1204+ (*ppCtx)->pPPSArray = (SWelsPPS*)pMa->WelsMalloc (MAX_PPS_COUNT * sizeof (SWelsPPS), "pPPSArray");
1205+ WELS_VERIFY_RETURN_PROC_IF (1, (NULL == (*ppCtx)->pPPSArray), FreeMemorySvc (ppCtx))
1206+
1207+
1208+ // copy from existing if the pointer exists
1209+ if (NULL != pExistingParasetList) {
1210+ (*ppCtx)->sPSOVector.uiInUsePpsNum = pExistingParasetList->uiInUsePpsNum;
1211+ memcpy ((*ppCtx)->pPPSArray, pExistingParasetList->sPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
1212+ }
1213+ }
1214+
1215+ if (INCREASING_ID & pParam->iSpsPpsIdStrategy) {
1216+ (*ppCtx)->pPSOVector = & ((*ppCtx)->sPSOVector);
1217+ } else {
1218+ (*ppCtx)->pPSOVector = NULL;
10561219 }
10571220
10581221 (*ppCtx)->pDqIdcMap = (SDqIdc*)pMa->WelsMallocz (iDlayerCount * sizeof (SDqIdc), "pDqIdcMap");
@@ -1066,12 +1229,79 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) { · 7 unmodified lines
10661229
10671230 pDqIdc->uiSpatialId = iDlayerIndex;
10681231
1069− WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
1070− iDlayerCount, iSpsId, pSps, pSubsetSps);
1232+ if (! (SPS_LISTING & pParam->iSpsPpsIdStrategy)) {
1233+ WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
1234+ iDlayerCount, iSpsId, pSps, pSubsetSps);
1235+ } else {
1236+ //SPS_LISTING_AND_PPS_INCREASING == pParam->iSpsPpsIdStrategy
1237+ //check if the current param can fit in an existing SPS
1238+ const int32_t kiFoundSpsId = FindExistingSps ((*ppCtx)->pSvcParam, bUseSubsetSps, iDlayerIndex, iDlayerCount,
1239+ bUseSubsetSps ? ((*ppCtx)->sPSOVector.uiInUseSubsetSpsNum) : ((*ppCtx)->sPSOVector.uiInUseSpsNum),
1240+ (*ppCtx)->pSpsArray,
1241+ (*ppCtx)->pSubsetArray);
1242+
1243+
1244+ if (INVALID_ID != kiFoundSpsId) {
1245+ //if yes, set pSps or pSubsetSps to it
1246+ iSpsId = kiFoundSpsId;
1247+ if (!bUseSubsetSps) {
1248+ pSps = & ((*ppCtx)->pSpsArray[kiFoundSpsId]);
1249+ } else {
1250+ pSubsetSps = & ((*ppCtx)->pSubsetArray[kiFoundSpsId]);
1251+ }
1252+ } else {
1253+ //if no, generate a new SPS as usual
1254+ if ((SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy) && (MAX_PPS_COUNT <= (*ppCtx)->sPSOVector.uiInUsePpsNum)) {
1255+ //check if we can generate new SPS or not
1256+ WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
1257+ "InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
1258+ return ENC_RETURN_UNSUPPORTED_PARA;
1259+ }
10711260
1072− pPps = & (*ppCtx)->pPPSArray[iPpsId];
1073− // initialize pPps
1074− WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
1261+ iSpsId = (!bUseSubsetSps) ? ((*ppCtx)->sPSOVector.uiInUseSpsNum++) : ((*ppCtx)->sPSOVector.uiInUseSubsetSpsNum++);
1262+ if (iSpsId >= MAX_SPS_COUNT) {
1263+ if (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy) {
1264+ WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
1265+ "InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
1266+ return ENC_RETURN_UNSUPPORTED_PARA;
1267+ }
1268+ // reset current list
1269+ if (!bUseSubsetSps) {
1270+ (*ppCtx)->sPSOVector.uiInUseSpsNum = 1;
1271+ memset ((*ppCtx)->pSpsArray, 0, MAX_SPS_COUNT * sizeof (SWelsSPS));
1272+ } else {
1273+ (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum = 1;
1274+ memset ((*ppCtx)->pSubsetArray, 0, MAX_SPS_COUNT * sizeof (SSubsetSps));
1275+ }
1276+ iSpsId = 0;
1277+ }
1278+
1279+ WelsGenerateNewSps (*ppCtx, bUseSubsetSps, iDlayerIndex,
1280+ iDlayerCount, iSpsId, pSps, pSubsetSps);
1281+ }
1282+ }
1283+
1284+ if (! (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy)) {
1285+ pPps = & (*ppCtx)->pPPSArray[iPpsId];
1286+ // initialize pPps
1287+ WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
1288+ } else {
1289+ const int32_t kiFoundPpsId = FindExistingPps (pSps, pSubsetSps, bUseSubsetSps, iSpsId,
1290+ pParam->iEntropyCodingModeFlag != 0,
1291+ (*ppCtx)->sPSOVector.uiInUsePpsNum,
1292+ (*ppCtx)->pPPSArray);
1293+
1294+
1295+ if (INVALID_ID != kiFoundPpsId) {
1296+ //if yes, set pPps to it
1297+ iPpsId = kiFoundPpsId;
1298+ pPps = & ((*ppCtx)->pPPSArray[kiFoundPpsId]);
1299+ } else {
1300+ iPpsId = ((*ppCtx)->sPSOVector.uiInUsePpsNum++);
1301+ pPps = & (*ppCtx)->pPPSArray[iPpsId];
1302+ WelsInitPps (pPps, pSps, pSubsetSps, iPpsId, true, bUseSubsetSps, pParam->iEntropyCodingModeFlag != 0);
1303+ }
1304+ }
10751305
10761306 // Not using FMO in SVC coding so far, come back if need FMO
10771307 {
@@ -1085,7 +1315,7 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) { · 7 unmodified lines
10851315 if (iResult) {
10861316 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "InitDqLayers(), InitSlicePEncCtx failed(%d)!", iResult);
10871317 FreeMemorySvc (ppCtx);
1088− return 1;
1318+ return iResult;
10891319 }
10901320 (*ppCtx)->ppDqLayerList[iDlayerIndex]->pSliceEncCtx = & (*ppCtx)->pSliceCtxList[iDlayerIndex];
10911321 }
@@ -1097,12 +1327,23 @@ static inline int32_t InitDqLayers (sWelsEncCtx** ppCtx) { · 5 unmodified lines
10971327 if (bUseSubsetSps)
10981328 ++ iSpsId;
10991329 ++ iPpsId;
1100− ++ (*ppCtx)->iSpsNum;
1330+ if (bUseSubsetSps) {
1331+ ++ (*ppCtx)->iSubsetSpsNum;
1332+ } else {
1333+ ++ (*ppCtx)->iSpsNum;
1334+ }
11011335 ++ (*ppCtx)->iPpsNum;
11021336
11031337 ++ iDlayerIndex;
11041338 }
1105− return 0;
1339+ if (SPS_LISTING & pParam->iSpsPpsIdStrategy) {
1340+ (*ppCtx)->iSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
1341+ (*ppCtx)->iSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
1342+ }
1343+ if (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy) {
1344+ (*ppCtx)->iPpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
1345+ }
1346+ return ENC_RETURN_SUCCESS;
11061347 }
11071348
11081349 int32_t AllocStrideTables (sWelsEncCtx** ppCtx, const int32_t kiNumSpatialLayers) {
@@ -1411,7 +1652,7 @@ void GetMvMvdRange (SWelsSvcCodingParam* pParam, int32_t& iMvRange, int32_t& iMv · 302 unmodified lines
14111652
14121653 iMvdRange = WELS_MIN (iMvdRange, iFixMvdRange);
14131654 }
1414−int32_t RequestMemorySvc (sWelsEncCtx** ppCtx) {
1655+int32_t RequestMemorySvc (sWelsEncCtx** ppCtx, SExistingParasetList* pExistingParasetList) {
14151656 SWelsSvcCodingParam* pParam = (*ppCtx)->pSvcParam;
14161657 CMemoryAlign* pMa = (*ppCtx)->pMemAlign;
14171658 SSpatialLayerConfig* pFinalSpatial = NULL;
@@ -1616,7 +1857,7 @@ int32_t RequestMemorySvc (sWelsEncCtx** ppCtx) { · 198 unmodified lines
16161857
16171858 //End of pVaa memory allocation
16181859
1619− iResult = InitDqLayers (ppCtx);
1860+ iResult = InitDqLayers (ppCtx, pExistingParasetList);
16201861 if (iResult) {
16211862 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_WARNING, "RequestMemorySvc(), InitDqLayers failed(%d)!", iResult);
16221863 FreeMemorySvc (ppCtx);
@@ -2130,7 +2371,8 @@ int32_t GetMultipleThreadIdc (SLogContext* pLogCtx, SWelsSvcCodingParam* pCoding · 507 unmodified lines
21302371 * \pParam pParam SWelsSvcCodingParam*
21312372 * \return successful - 0; otherwise none 0 for failed
21322373 */
2133−int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) {
2374+int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx,
2375+ SExistingParasetList* pExistingParasetList) {
21342376 sWelsEncCtx* pCtx = NULL;
21352377 int32_t iRet = 0;
21362378 int16_t iSliceNum = 1; // number of slices used
@@ -2189,7 +2431,7 @@ int32_t WelsInitEncoderExt (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pCodingPar · 52 unmodified lines
21892431
21902432 pCtx->iActiveThreadsNum = pCodingParam->iCountThreadsNum;
21912433 pCtx->iMaxSliceCount = iSliceNum;
2192− iRet = RequestMemorySvc (&pCtx);
2434+ iRet = RequestMemorySvc (&pCtx, pExistingParasetList);
21932435 if (iRet != 0) {
21942436 WelsLog (pLogCtx, WELS_LOG_ERROR, "WelsInitEncoderExt(), RequestMemorySvc failed return %d.", iRet);
21952437 FreeMemorySvc (&pCtx);
@@ -2553,18 +2795,26 @@ void WelsInitCurrentLayer (sWelsEncCtx* pCtx, · 357 unmodified lines
25532795 iSliceCount = GetCurrentSliceNum (pCurDq->pSliceEncCtx);
25542796 assert (iSliceCount > 0);
25552797
2556− pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId = pDqIdc->iPpsId;
2798+ int32_t iCurPpsId = pDqIdc->iPpsId;
2799+ int32_t iCurSpsId = pDqIdc->iSpsId;
2800+
2801+ if (SPS_PPS_LISTING == pParam->iSpsPpsIdStrategy) {
2802+ iCurPpsId = pCtx->sPSOVector.iPpsIdList[pDqIdc->iPpsId][WELS_ABS (pCtx->uiIdrPicId - 1) % MAX_PPS_COUNT];
2803+ }
2804+
2805+ pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId = iCurPpsId;
25572806 pCurDq->sLayerInfo.pPpsP =
2558− pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps = &pCtx->pPPSArray[pBaseSlice->sSliceHeaderExt.sSliceHeader.iPpsId];
2559− pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId = pDqIdc->iSpsId;
2807+ pBaseSlice->sSliceHeaderExt.sSliceHeader.pPps = &pCtx->pPPSArray[iCurPpsId];
2808+
2809+ pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId = iCurSpsId;
25602810 if (kbUseSubsetSpsFlag) {
2561− pCurDq->sLayerInfo.pSubsetSpsP = &pCtx->pSubsetArray[pDqIdc->iSpsId];
2811+ pCurDq->sLayerInfo.pSubsetSpsP = &pCtx->pSubsetArray[iCurSpsId];
25622812 pCurDq->sLayerInfo.pSpsP =
25632813 pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCurDq->sLayerInfo.pSubsetSpsP->pSps;
25642814 } else {
25652815 pCurDq->sLayerInfo.pSubsetSpsP = NULL;
25662816 pCurDq->sLayerInfo.pSpsP =
2567− pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCtx->pSpsArray[pBaseSlice->sSliceHeaderExt.sSliceHeader.iSpsId];
2817+ pBaseSlice->sSliceHeaderExt.sSliceHeader.pSps = &pCtx->pSpsArray[iCurSpsId];
25682818 }
25692819
25702820 pSlice = pBaseSlice;
@@ -2865,46 +3115,68 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN · 294 unmodified lines
28653115 /* write all SPS */
28663116 iIdx = 0;
28673117 while (iIdx < pCtx->iSpsNum) {
2868− SDqIdc* pDqIdc = &pCtx->pDqIdcMap[iIdx];
2869− const int32_t kiDid = pDqIdc->uiSpatialId;
2870− const bool kbUsingSubsetSps = (kiDid > BASE_DEPENDENCY_ID);
2871−
28723118 iNal = pCtx->pOut->iNalIndex;
28733119
2874− if (pCtx->pSvcParam->bEnableSpsPpsIdAddition) {
3120+ if (INCREASING_ID == pCtx->pSvcParam->iSpsPpsIdStrategy) {
28753121 #if _DEBUG
2876− pCtx->sPSOVector.bEnableSpsPpsIdAddition = 1;
2877− assert (kiDid < MAX_DEPENDENCY_LAYER);
3122+ pCtx->sPSOVector.iSpsPpsIdStrategy = INCREASING_ID;
28783123 assert (iIdx < MAX_DQ_LAYER_NUM);
28793124 #endif
28803125
2881− ParasetIdAdditionIdAdjust (& (pCtx->sPSOVector.sParaSetOffsetVariable[kbUsingSubsetSps ? PARA_SET_TYPE_SUBSETSPS :
2882− PARA_SET_TYPE_AVCSPS]),
2883− (kbUsingSubsetSps) ? (pCtx->pSubsetArray[iIdx - 1].pSps.uiSpsId) : (pCtx->pSpsArray[0].uiSpsId),
3126+ ParasetIdAdditionIdAdjust (& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS]),
3127+ pCtx->pSpsArray[0].uiSpsId,
28843128 MAX_SPS_COUNT);
2885− } else {
3129+ } else if (CONSTANT_ID == pCtx->pSvcParam->iSpsPpsIdStrategy) {
28863130 memset (& (pCtx->sPSOVector), 0, sizeof (pCtx->sPSOVector));
28873131 }
28883132
2889− if (kbUsingSubsetSps) {
2890− iId = iIdx - 1;
3133+ /* generate sequence parameters set */
3134+ iId = (SPS_LISTING & pCtx->pSvcParam->iSpsPpsIdStrategy) ? iIdx : 0;
28913135
2892− /* generate Subset SPS */
2893− WelsLoadNal (pCtx->pOut, NAL_UNIT_SUBSET_SPS, NRI_PRI_HIGHEST);
3136+ WelsLoadNal (pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST);
3137+ WelsWriteSpsNal (&pCtx->pSpsArray[iId], &pCtx->pOut->sBsWrite,
3138+ & (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS].iParaSetIdDelta[0]));
3139+ WelsUnloadNal (pCtx->pOut);
28943140
2895− WelsWriteSubsetSpsSyntax (&pCtx->pSubsetArray[iId], &pCtx->pOut->sBsWrite,
2896− & (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS].iParaSetIdDelta[0]));
2897− WelsUnloadNal (pCtx->pOut);
2898− } else {
2899− iId = 0;
3141+ iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
3142+ pCtx->iFrameBsSize - pCtx->iPosBsBuffer,//available buffer to be written, so need to substract the used length
3143+ pCtx->pFrameBs + pCtx->iPosBsBuffer,
3144+ &iNalLength);
3145+ WELS_VERIFY_RETURN_IFNEQ (iReturn, ENC_RETURN_SUCCESS)
3146+ pNalLen[iCountNal] = iNalLength;
29003147
2901− /* generate sequence parameters set */
2902− WelsLoadNal (pCtx->pOut, NAL_UNIT_SPS, NRI_PRI_HIGHEST);
2903− WelsWriteSpsNal (&pCtx->pSpsArray[0], &pCtx->pOut->sBsWrite,
2904− & (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_AVCSPS].iParaSetIdDelta[0]));
2905− WelsUnloadNal (pCtx->pOut);
3148+ pCtx->iPosBsBuffer += iNalLength;
3149+ iSize += iNalLength;
3150+
3151+ ++ iIdx;
3152+ ++ iCountNal;
3153+ }
3154+
3155+ /* write all Subset SPS */
3156+ iIdx = 0;
3157+ while (iIdx < pCtx->iSubsetSpsNum) {
3158+ iNal = pCtx->pOut->iNalIndex;
3159+
3160+ if (INCREASING_ID == pCtx->pSvcParam->iSpsPpsIdStrategy) {
3161+#if _DEBUG
3162+ pCtx->sPSOVector.iSpsPpsIdStrategy = INCREASING_ID;
3163+ assert (iIdx < MAX_DQ_LAYER_NUM);
3164+#endif
3165+
3166+ ParasetIdAdditionIdAdjust (& (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS]),
3167+ pCtx->pSubsetArray[iIdx].pSps.uiSpsId,
3168+ MAX_SPS_COUNT);
29063169 }
29073170
3171+ iId = iIdx;
3172+
3173+ /* generate Subset SPS */
3174+ WelsLoadNal (pCtx->pOut, NAL_UNIT_SUBSET_SPS, NRI_PRI_HIGHEST);
3175+
3176+ WelsWriteSubsetSpsSyntax (&pCtx->pSubsetArray[iId], &pCtx->pOut->sBsWrite,
3177+ & (pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_SUBSETSPS].iParaSetIdDelta[0]));
3178+ WelsUnloadNal (pCtx->pOut);
3179+
29083180 iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
29093181 pCtx->iFrameBsSize - pCtx->iPosBsBuffer,//available buffer to be written, so need to substract the used length
29103182 pCtx->pFrameBs + pCtx->iPosBsBuffer,
@@ -2921,8 +3193,30 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN · 10 unmodified lines
29213193
29223194 /* write all PPS */
29233195 iIdx = 0;
3196+ if ((SPS_PPS_LISTING == pCtx->pSvcParam->iSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
3197+ assert (pCtx->iPpsNum <= MAX_DQ_LAYER_NUM);
3198+
3199+ //Generate PPS LIST
3200+ int32_t iPpsId = 0, iUsePpsNum = pCtx->iPpsNum;
3201+
3202+ for (int32_t iIdrRound = 0; iIdrRound < MAX_PPS_COUNT; iIdrRound++) {
3203+ for (iPpsId = 0; iPpsId < pCtx->iPpsNum; iPpsId++) {
3204+ pCtx->sPSOVector.iPpsIdList[iPpsId][iIdrRound] = ((iIdrRound * iUsePpsNum + iPpsId) % MAX_PPS_COUNT);
3205+ }
3206+ }
3207+
3208+ for (iPpsId = iUsePpsNum; iPpsId < MAX_PPS_COUNT; iPpsId++) {
3209+ memcpy (& (pCtx->pPPSArray[iPpsId]), & (pCtx->pPPSArray[iPpsId % iUsePpsNum]), sizeof (SWelsPPS));
3210+ pCtx->pPPSArray[iPpsId].iPpsId = iPpsId;
3211+ pCtx->iPpsNum++;
3212+ }
3213+
3214+ assert (pCtx->iPpsNum == MAX_PPS_COUNT);
3215+ pCtx->sPSOVector.uiInUsePpsNum = pCtx->iPpsNum;
3216+ }
3217+
29243218 while (iIdx < pCtx->iPpsNum) {
2925− if (pCtx->pSvcParam->bEnableSpsPpsIdAddition) {
3219+ if ((INCREASING_ID & pCtx->pSvcParam->iSpsPpsIdStrategy)) {
29263220 //para_set_type = 2: PPS, use MAX_PPS_COUNT
29273221 ParasetIdAdditionIdAdjust (&pCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS], pCtx->pPPSArray[iIdx].iPpsId,
29283222 MAX_PPS_COUNT);
@@ -2931,7 +3225,8 @@ int32_t WelsWriteParameterSets (sWelsEncCtx* pCtx, int32_t* pNalLen, int32_t* pN · 2 unmodified lines
29313225 iNal = pCtx->pOut->iNalIndex;
29323226 /* generate picture parameter set */
29333227 WelsLoadNal (pCtx->pOut, NAL_UNIT_PPS, NRI_PRI_HIGHEST);
2934− WelsWritePpsSyntax (&pCtx->pPPSArray[iIdx], &pCtx->pOut->sBsWrite, & (pCtx->sPSOVector));
3228+ WelsWritePpsSyntax (&pCtx->pPPSArray[iIdx], &pCtx->pOut->sBsWrite,
3229+ ((SPS_PPS_LISTING != pCtx->pSvcParam->iSpsPpsIdStrategy)) ? (& (pCtx->sPSOVector)) : NULL);
29353230 WelsUnloadNal (pCtx->pOut);
29363231
29373232 iReturn = WelsEncodeNal (&pCtx->pOut->sNalList[iNal], NULL,
@@ -3237,7 +3532,6 @@ int32_t WelsEncoderEncodeExt (sWelsEncCtx* pCtx, SFrameBSInfo* pFbi, const SSour · 299 unmodified lines
32373532 iDidList[iSpatialIdx] = iCurDid;
32383533
32393534 // Encoding this picture might mulitiple sQualityStat layers potentially be encoded as followed
3240−
32413535 switch (pParam->sSliceCfg.uiSliceMode) {
32423536 case SM_FIXEDSLCNUM_SLICE:
32433537 case SM_AUTO_SLICE: {
@@ -3829,7 +4123,8 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa · 585 unmodified lines
38294123 (pOldParam->iLTRRefNum != pNewParam->iLTRRefNum) ||
38304124 (pOldParam->iMultipleThreadIdc != pNewParam->iMultipleThreadIdc) ||
38314125 (pOldParam->bEnableBackgroundDetection != pNewParam->bEnableBackgroundDetection) ||
3832− (pOldParam->bEnableAdaptiveQuant != pNewParam->bEnableAdaptiveQuant);
4126+ (pOldParam->bEnableAdaptiveQuant != pNewParam->bEnableAdaptiveQuant) ||
4127+ (pOldParam->iSpsPpsIdStrategy != pNewParam->iSpsPpsIdStrategy);
38334128 if (pNewParam->iMaxNumRefFrame > pOldParam->iMaxNumRefFrame) {
38344129 bNeedReset = true;
38354130 }
@@ -3876,35 +4171,75 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa · 40 unmodified lines
38764171 }
38774172
38784173 if (bNeedReset) {
3879− SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE];
3880− uint16_t uiTmpIdrPicId;//this is for LTR!
38814174 SLogContext sLogCtx = (*ppCtx)->sLogCtx;
3882− for (int32_t k = 0; k < PARA_SET_TYPE; k++)
3883− memset (((*ppCtx)->sPSOVector.sParaSetOffsetVariable[k].bUsedParaSetIdInBs), 0, MAX_PPS_COUNT * sizeof (bool));
3884− memcpy (sTmpPsoVariable, (*ppCtx)->sPSOVector.sParaSetOffsetVariable,
3885− (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
3886− uiTmpIdrPicId = (*ppCtx)->uiIdrPicId;
4175+
4176+ int32_t iOldSpsPpsIdStrategy = pOldParam->iSpsPpsIdStrategy;
4177+ SParaSetOffsetVariable sTmpPsoVariable[PARA_SET_TYPE];
4178+ int32_t iTmpPpsIdList[MAX_DQ_LAYER_NUM * MAX_PPS_COUNT];
4179+ uint16_t uiTmpIdrPicId = (*ppCtx)->uiIdrPicId;//this is for LTR!
38874180
38884181 SEncoderStatistics sTempEncoderStatistics = (*ppCtx)->sEncoderStatistics;
38894182
4183+ SExistingParasetList sExistingParasetList;
4184+ SExistingParasetList* pExistingParasetList = NULL;
4185+
4186+ if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->iSpsPpsIdStrategy)) {
4187+ for (int32_t k = 0; k < PARA_SET_TYPE; k++) {
4188+ memset (((*ppCtx)->sPSOVector.sParaSetOffsetVariable[k].bUsedParaSetIdInBs), 0, MAX_PPS_COUNT * sizeof (bool));
4189+ }
4190+ memcpy (sTmpPsoVariable, (*ppCtx)->sPSOVector.sParaSetOffsetVariable,
4191+ (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
4192+
4193+ if ((SPS_LISTING & iOldSpsPpsIdStrategy)
4194+ && (SPS_LISTING & pNewParam->iSpsPpsIdStrategy)) {
4195+ pExistingParasetList = &sExistingParasetList;
4196+ sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
4197+ sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
4198+ memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
4199+ memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
4200+ }
4201+
4202+ if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
4203+ && (SPS_PPS_LISTING == pNewParam->iSpsPpsIdStrategy)) {
4204+ pExistingParasetList = &sExistingParasetList;
4205+ sExistingParasetList.uiInUseSpsNum = (*ppCtx)->sPSOVector.uiInUseSpsNum;
4206+ sExistingParasetList.uiInUseSubsetSpsNum = (*ppCtx)->sPSOVector.uiInUseSubsetSpsNum;
4207+ sExistingParasetList.uiInUsePpsNum = (*ppCtx)->sPSOVector.uiInUsePpsNum;
4208+ memcpy (sExistingParasetList.sSps, (*ppCtx)->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
4209+ memcpy (sExistingParasetList.sSubsetSps, (*ppCtx)->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
4210+ memcpy (sExistingParasetList.sPps, (*ppCtx)->pPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
4211+
4212+ memcpy (iTmpPpsIdList, ((*ppCtx)->sPSOVector.iPpsIdList), MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
4213+ }
4214+ }
4215+
4216+
38904217 WelsUninitEncoderExt (ppCtx);
38914218
38924219 /* Update new parameters */
3893− if (WelsInitEncoderExt (ppCtx, pNewParam, &sLogCtx))
4220+ if (WelsInitEncoderExt (ppCtx, pNewParam, &sLogCtx, pExistingParasetList))
38944221 return 1;
38954222
38964223 // reset the scaled spatial picture size
38974224 (*ppCtx)->pVpp->WelsPreprocessReset (*ppCtx);
38984225 //if WelsInitEncoderExt succeed
38994226
3900− //load back the needed structure
3901− //for FLEXIBLE_PARASET_ID
3902− memcpy ((*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable,
3903− (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
39044227 //for LTR
39054228 (*ppCtx)->uiIdrPicId = uiTmpIdrPicId;
4229+
39064230 //for sEncoderStatistics
39074231 (*ppCtx)->sEncoderStatistics = sTempEncoderStatistics;
4232+
4233+ //load back the needed structure for iSpsPpsIdStrategy
4234+ if ((CONSTANT_ID != iOldSpsPpsIdStrategy) && (CONSTANT_ID != pNewParam->iSpsPpsIdStrategy)) {
4235+ memcpy ((*ppCtx)->sPSOVector.sParaSetOffsetVariable, sTmpPsoVariable,
4236+ (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
4237+ }
4238+
4239+ if ((SPS_PPS_LISTING == iOldSpsPpsIdStrategy)
4240+ && (SPS_PPS_LISTING == pNewParam->iSpsPpsIdStrategy)) {
4241+ memcpy (((*ppCtx)->sPSOVector.iPpsIdList), iTmpPpsIdList, MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
4242+ }
39084243 } else {
39094244 /* maybe adjustment introduced in bitrate or little settings adjustment and so on.. */
39104245 pNewParam->iNumRefFrame = WELS_CLIP3 (pNewParam->iNumRefFrame, MIN_REF_PIC_COUNT,
@@ -3919,7 +4254,7 @@ int32_t WelsEncoderParamAdjust (sWelsEncCtx** ppCtx, SWelsSvcCodingParam* pNewPa · 8 unmodified lines
39194254 pOldParam->fMaxFrameRate = pNewParam->fMaxFrameRate; // maximal frame rate [Hz / fps]
39204255 pOldParam->iComplexityMode = pNewParam->iComplexityMode; // color space of input sequence
39214256 pOldParam->uiIntraPeriod = pNewParam->uiIntraPeriod; // intra period (multiple of GOP size as desired)
3922− pOldParam->bEnableSpsPpsIdAddition = pNewParam->bEnableSpsPpsIdAddition;
4257+ pOldParam->iSpsPpsIdStrategy = pNewParam->iSpsPpsIdStrategy;
39234258 pOldParam->bPrefixNalAddingCtrl = pNewParam->bPrefixNalAddingCtrl;
39244259 pOldParam->iNumRefFrame = pNewParam->iNumRefFrame; // number of reference frame used
39254260 pOldParam->uiGopSize = pNewParam->uiGopSize;
codec/encoder/core/src/svc_encode_slice.cpp+10−7
@@ -237,7 +237,8 @@ void WriteRefPicMarking (SBitStringAux* pBs, SSliceHeader* pSliceHeader, SNalUni · 236 unmodified lines
237237 }
238238 }
239239
240−void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) {
240+void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
241+ int32_t* pPpsIdDelta) {
241242 SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
242243 SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
243244 SSliceHeader* pSliceHeader = &pSlice->sSliceHeaderExt.sSliceHeader;
@@ -246,7 +247,7 @@ void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCur · 2 unmodified lines
246247 BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice);
247248 BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */
248249
249− BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId]);
250+ BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + ((pPpsIdDelta != NULL) ? pPpsIdDelta[pSliceHeader->pPps->iPpsId] : 0));
250251
251252 BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
252253
@@ -301,7 +302,8 @@ void WelsSliceHeaderWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCur · 48 unmodified lines
301302 }
302303 }
303304
304−void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice, int32_t* pPpsIdDelta) {
305+void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* pCurLayer, SSlice* pSlice,
306+ int32_t* pPpsIdDelta) {
305307 SWelsSPS* pSps = pCurLayer->sLayerInfo.pSpsP;
306308 SWelsPPS* pPps = pCurLayer->sLayerInfo.pPpsP;
307309 SSubsetSps* pSubSps = pCurLayer->sLayerInfo.pSubsetSpsP;
@@ -312,7 +314,7 @@ void WelsSliceHeaderExtWrite (sWelsEncCtx* pCtx, SBitStringAux* pBs, SDqLayer* p · 4 unmodified lines
312314 BsWriteUE (pBs, pSliceHeader->iFirstMbInSlice);
313315 BsWriteUE (pBs, pSliceHeader->eSliceType); /* same type things */
314316
315− BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + pPpsIdDelta[pSliceHeader->pPps->iPpsId]);
317+ BsWriteUE (pBs, pSliceHeader->pPps->iPpsId + ((pPpsIdDelta != NULL) ? pPpsIdDelta[pSliceHeader->pPps->iPpsId] : 0));
316318
317319 BsWriteBits (pBs, pSps->uiLog2MaxFrameNum, pSliceHeader->iFrameNum);
318320
@@ -727,11 +729,12 @@ int32_t WelsCodeOneSlice (sWelsEncCtx* pEncCtx, const int32_t kiSliceIdx, const · 408 unmodified lines
727729
728730 WelsSliceHeaderExtInit (pEncCtx, pCurLayer, pCurSlice);
729731
730−
731732 g_pWelsWriteSliceHeader[pCurSlice->bSliceHeaderExtFlag] (pEncCtx, pBs, pCurLayer, pCurSlice,
732− & (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0]));
733+ ((SPS_PPS_LISTING != pEncCtx->pSvcParam->iSpsPpsIdStrategy) ? (&
734+ (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0])) : NULL));
735+
733736 #if _DEBUG
734− if (pEncCtx->sPSOVector.bEnableSpsPpsIdAddition) {
737+ if (INCREASING_ID & pEncCtx->sPSOVector.iSpsPpsIdStrategy) {
735738 const int32_t kiEncoderPpsId = pCurSlice->sSliceHeaderExt.sSliceHeader.pPps->iPpsId;
736739 const int32_t kiTmpPpsIdInBs = kiEncoderPpsId +
737740 pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[ kiEncoderPpsId ];
codec/encoder/plus/src/welsEncoderExt.cpp+29−10
@@ -332,7 +332,7 @@ int CWelsH264SVCEncoder::InitializeInternal (SWelsSvcCodingParam* pCfg) { · 331 unmodified lines
332332 m_iMaxPicHeight = pCfg->iPicHeight;
333333
334334 TraceParamInfo (pCfg);
335− if (WelsInitEncoderExt (&m_pEncContext, pCfg, &m_pWelsTrace->m_sLogCtx)) {
335+ if (WelsInitEncoderExt (&m_pEncContext, pCfg, &m_pWelsTrace->m_sLogCtx, NULL)) {
336336 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR, "CWelsH264SVCEncoder::Initialize(), WelsInitEncoderExt failed.");
337337 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_DEBUG,
338338 "Problematic Input Base Param: iUsageType=%d, Resolution=%dx%d, FR=%f, TLayerNum=%d, DLayerNum=%d",
@@ -477,6 +477,7 @@ int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR) { · 138 unmodified lines
477477 }
478478 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
479479 "CWelsH264SVCEncoder::ForceIntraFrame(), bIDR= %d", bIDR);
480+
480481 ForceCodingIDR (m_pEncContext);
481482
482483 m_pEncContext->sEncoderStatistics.uiIDRReqNum++;
@@ -486,8 +487,8 @@ int CWelsH264SVCEncoder::ForceIntraFrame (bool bIDR) { · 3 unmodified lines
486487 void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) {
487488 WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
488489 "iUsageType = %d,iPicWidth= %d;iPicHeight= %d;iTargetBitrate= %d;iMaxBitrate= %d;iRCMode= %d;iPaddingFlag= %d;iTemporalLayerNum= %d;iSpatialLayerNum= %d;fFrameRate= %.6ff;uiIntraPeriod= %d;\
489− bEnableSpsPpsIdAddition = %d;bPrefixNalAddingCtrl = %d;bEnableDenoise= %d;bEnableBackgroundDetection= %d;bEnableAdaptiveQuant= %d;bEnableFrameSkip= %d;bEnableLongTermReference= %d;iLtrMarkPeriod= %d;\
490− iComplexityMode = %d;iNumRefFrame = %d;iEntropyCodingModeFlag = %d;uiMaxNalSize = %d;iLTRRefNum = %d;iMultipleThreadIdc = %d;iLoopFilterDisableIdc = %d",
490+ iSpsPpsIdStrategy = %d;bPrefixNalAddingCtrl = %d;bEnableDenoise= %d;bEnableBackgroundDetection= %d;bEnableAdaptiveQuant= %d;bEnableFrameSkip= %d;bEnableLongTermReference= %d;iLtrMarkPeriod= %d;\
491+ iComplexityMode = %d;iNumRefFrame = %d;iEntropyCodingModeFlag = %d;uiMaxNalSize = %d;iLTRRefNum = %d;iMultipleThreadIdc = %d;iLoopFilterDisableIdc = %d (offset(alpha/beta): %d,%d)",
491492 pParam->iUsageType,
492493 pParam->iPicWidth,
493494 pParam->iPicHeight,
@@ -499,7 +500,7 @@ void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) { · 5 unmodified lines
499500 pParam->iSpatialLayerNum,
500501 pParam->fMaxFrameRate,
501502 pParam->uiIntraPeriod,
502− pParam->bEnableSpsPpsIdAddition,
503+ pParam->iSpsPpsIdStrategy,
503504 pParam->bPrefixNalAddingCtrl,
504505 pParam->bEnableDenoise,
505506 pParam->bEnableBackgroundDetection,
@@ -513,7 +514,9 @@ void CWelsH264SVCEncoder::TraceParamInfo (SEncParamExt* pParam) { · 7 unmodified lines
513514 pParam->uiMaxNalSize,
514515 pParam->iLTRRefNum,
515516 pParam->iMultipleThreadIdc,
516− pParam->iLoopFilterDisableIdc
517+ pParam->iLoopFilterDisableIdc,
518+ pParam->iLoopFilterAlphaC0Offset,
519+ pParam->iLoopFilterBetaOffset
517520 );
518521 int32_t i = 0;
519522 int32_t iSpatialLayers = (pParam->iSpatialLayerNum < MAX_SPATIAL_LAYER_NUM) ? (pParam->iSpatialLayerNum) :
@@ -706,16 +709,26 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) { · 186 unmodified lines
706709 #endif//OUTPUT_BIT_STREAM
707710 if (sEncodingParam.iSpatialLayerNum < 1
708711 || sEncodingParam.iSpatialLayerNum > MAX_SPATIAL_LAYER_NUM) { // verify number of spatial layer
712+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
713+ "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, iSpatialLayerNum(%d) failed!",
714+ sEncodingParam.iSpatialLayerNum);
709715 return cmInitParaError;
710716 }
711717
712718 if (sConfig.ParamTranscode (sEncodingParam)) {
719+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
720+ "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ParamTranscode failed!");
713721 return cmInitParaError;
714722 }
715723 if (sConfig.iSpatialLayerNum < 1) {
724+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
725+ "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, iSpatialLayerNum(%d) failed!",
726+ sConfig.iSpatialLayerNum);
716727 return cmInitParaError;
717728 }
718729 if (sConfig.DetermineTemporalSettings()) {
730+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
731+ "CWelsH264SVCEncoder::SetOption():ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, DetermineTemporalSettings failed!");
719732 return cmInitParaError;
720733 }
721734
@@ -898,11 +911,17 @@ int CWelsH264SVCEncoder::SetOption (ENCODER_OPTION eOptionId, void* pOption) { · 176 unmodified lines
898911 }
899912 break;
900913 case ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION: {
901− bool iValue = * ((bool*)pOption);
902−
903− m_pEncContext->pSvcParam->bEnableSpsPpsIdAddition = iValue;
904− WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption enable SPS/PPS ID = %d ",
905− m_pEncContext->pSvcParam->bEnableSpsPpsIdAddition);
914+ int32_t iValue = * ((int32_t*)pOption);
915+ if (((iValue > INCREASING_ID) || (m_pEncContext->pSvcParam->iSpsPpsIdStrategy > INCREASING_ID))
916+ && m_pEncContext->pSvcParam->iSpsPpsIdStrategy != iValue) {
917+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_ERROR,
918+ " 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",
919+ m_pEncContext->pSvcParam->iSpsPpsIdStrategy, iValue);
920+ return cmInitParaError;
921+ }
922+ m_pEncContext->pSvcParam->iSpsPpsIdStrategy = iValue;
923+ WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, " CWelsH264SVCEncoder::SetOption iSpsPpsIdStrategy = %d ",
924+ m_pEncContext->pSvcParam->iSpsPpsIdStrategy);
906925 }
907926 break;
908927 case ENCODER_OPTION_CURRENT_PATH: {
test/api/encode_decode_api_test.cpp+506−48
@@ -88,26 +88,25 @@ class EncodeDecodeTestBase : public ::testing::TestWithParam<EncodeDecodeFilePar · 87 unmodified lines
8888 BaseDecoderTest::TearDown();
8989 }
9090
91− virtual void prepareParam (int iLayers, int iSlices, int width, int height, float framerate) {
92− memset (&param_, 0, sizeof (SEncParamExt));
93− param_.iUsageType = CAMERA_VIDEO_REAL_TIME;
94− param_.iPicWidth = width;
95− param_.iPicHeight = height;
96− param_.fMaxFrameRate = framerate;
97− param_.iRCMode = RC_OFF_MODE; //rc off
98− param_.iMultipleThreadIdc = 1; //single thread
99− param_.iSpatialLayerNum = iLayers;
100− param_.iNumRefFrame = AUTO_REF_PIC_COUNT;
91+ virtual void prepareParam (int iLayers, int iSlices, int width, int height, float framerate, SEncParamExt* pParam) {
92+ memset (pParam, 0, sizeof (SEncParamExt));
93+ pParam->iUsageType = CAMERA_VIDEO_REAL_TIME;
94+ pParam->iPicWidth = width;
95+ pParam->iPicHeight = height;
96+ pParam->fMaxFrameRate = framerate;
97+ pParam->iRCMode = RC_OFF_MODE; //rc off
98+ pParam->iMultipleThreadIdc = 1; //single thread
99+ pParam->iSpatialLayerNum = iLayers;
100+ pParam->iNumRefFrame = AUTO_REF_PIC_COUNT;
101101 for (int i = 0; i < iLayers; i++) {
102− param_.sSpatialLayers[i].iVideoWidth = width >> (iLayers - i - 1);
103− param_.sSpatialLayers[i].iVideoHeight = height >> (iLayers - i - 1);
104− param_.sSpatialLayers[i].fFrameRate = framerate;
105− param_.sSpatialLayers[i].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
106− param_.sSpatialLayers[i].sSliceCfg.sSliceArgument.uiSliceNum = iSlices;
102+ pParam->sSpatialLayers[i].iVideoWidth = width >> (iLayers - i - 1);
103+ pParam->sSpatialLayers[i].iVideoHeight = height >> (iLayers - i - 1);
104+ pParam->sSpatialLayers[i].fFrameRate = framerate;
105+ pParam->sSpatialLayers[i].sSliceCfg.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
106+ pParam->sSpatialLayers[i].sSliceCfg.sSliceArgument.uiSliceNum = iSlices;
107107 }
108−
109−
110108 }
109+
111110 virtual void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam) {
112111 //for encoder
113112 //I420: 1(Y) + 1/4(U) + 1/4(V)
@@ -147,6 +146,15 @@ class EncodeDecodeTestBase : public ::testing::TestWithParam<EncodeDecodeFilePar · 33 unmodified lines
147146 len = layerInfo.pNalLengthInByte[iSliceNum];
148147 }
149148
149+
150+ virtual int GetRandWidth() {
151+ return (WELS_CLIP3 ((((rand() % MAX_WIDTH) >> 1) + 1) << 1, 2, MAX_WIDTH));
152+ }
153+
154+ virtual int GetRandHeight() {
155+ return (WELS_CLIP3 ((((rand() % MAX_HEIGHT) >> 1) + 1) << 1, 2, MAX_HEIGHT));
156+ }
157+
150158 protected:
151159 SEncParamExt param_;
152160 BufferedData buf_;
@@ -171,8 +179,8 @@ class EncodeDecodeTestAPI : public EncodeDecodeTestBase { · 18 unmodified lines
171179 EncodeDecodeTestBase::TearDown();
172180 }
173181
174− void prepareParam (int iLayers, int iSlices, int width, int height, float framerate) {
175− EncodeDecodeTestBase::prepareParam (iLayers, iSlices, width, height, framerate);
182+ void prepareParam (int iLayers, int iSlices, int width, int height, float framerate, SEncParamExt* pParam) {
183+ EncodeDecodeTestBase::prepareParam (iLayers, iSlices, width, height, framerate, pParam);
176184 }
177185
178186 void InitialEncDec (int iWidth, int iHeight);
@@ -192,6 +200,24 @@ class EncodeDecodeTestAPI : public EncodeDecodeTestBase { · 13 unmodified lines
192200 else if (1 == iCheckTypeIndex)
193201 ASSERT_TRUE (rv == cmResultSuccess || rv == cmUnkonwReason);
194202 }
203+
204+ void EncDecOneFrame (const int iWidth, const int iHeight, const int iFrame, FILE* pfEnc) {
205+ int iLen = 0, rv;
206+ InitialEncDec (iWidth, iHeight);
207+ EncodeOneFrame (iFrame);
208+
209+ //extract target layer data
210+ encToDecData (info, iLen);
211+ //call decoder
212+ unsigned char* pData[3] = { NULL };
213+ memset (&dstBufInfo_, 0, sizeof (SBufferInfo));
214+ rv = decoder_->DecodeFrame2 (info.sLayerInfo[0].pBsBuf, iLen, pData, &dstBufInfo_);
215+ EXPECT_TRUE (rv == cmResultSuccess) << " rv = " << rv << " iFrameIdx = " << iFrame;
216+
217+ if (NULL != pfEnc) {
218+ fwrite (info.sLayerInfo[0].pBsBuf, iLen, 1, pfEnc);
219+ }
220+ }
195221 };
196222
197223 void EncodeDecodeTestAPI::InitialEncDec (int iWidth, int iHeight) {
@@ -234,7 +260,7 @@ void EncodeDecodeTestAPI::RandomParamExtCombination() { · 36 unmodified lines
234260 param_.iNumRefFrame = AUTO_REF_PIC_COUNT;
235261 param_.iMultipleThreadIdc = rand();
236262
237− param_.bEnableSpsPpsIdAddition = (rand() % 2 == 0) ? false : true;
263+ param_.iSpsPpsIdStrategy = rand() % 3;
238264 param_.bPrefixNalAddingCtrl = (rand() % 2 == 0) ? false : true;
239265 param_.bEnableSSEI = (rand() % 2 == 0) ? false : true;
240266 param_.iPaddingFlag = rand() % 2;
@@ -462,7 +488,7 @@ static const EncodeDecodeFileParamBase kFileParamArray[] = { · 221 unmodified lines
462488
463489 TEST_P (EncodeDecodeTestAPI, DecoderVclNal) {
464490 EncodeDecodeFileParamBase p = GetParam();
465− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
491+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
466492 encoder_->Uninitialize();
467493 int rv = encoder_->InitializeExt (&param_);
468494 ASSERT_TRUE (rv == cmResultSuccess);
@@ -498,7 +524,7 @@ TEST_P (EncodeDecodeTestAPI, DecoderVclNal) { · 29 unmodified lines
498524
499525 TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) {
500526 EncodeDecodeFileParamBase p = GetParam();
501− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
527+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
502528 encoder_->Uninitialize();
503529 int rv = encoder_->InitializeExt (&param_);
504530 ASSERT_TRUE (rv == cmResultSuccess);
@@ -535,7 +561,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionFramenum) { · 30 unmodified lines
535561
536562 TEST_P (EncodeDecodeTestAPI, GetOptionIDR) {
537563 EncodeDecodeFileParamBase p = GetParam();
538− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
564+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
539565 encoder_->Uninitialize();
540566 int rv = encoder_->InitializeExt (&param_);
541567 ASSERT_TRUE (rv == cmResultSuccess);
@@ -554,7 +580,8 @@ TEST_P (EncodeDecodeTestAPI, GetOptionIDR) { · 12 unmodified lines
554580 int32_t iSpsPpsIdAddition = 0;
555581 int iIdx = 0;
556582 while (iIdx <= p.numframes) {
557− iSpsPpsIdAddition = rand() % 2;
583+ iSpsPpsIdAddition = rand() %
584+ 2; //the current strategy supports more than 2 modes, but the switch between the modes>2 is not allowed
558585 iIDRPeriod = (rand() % 150) + 1;
559586 encoder_->SetOption (ENCODER_OPTION_IDR_INTERVAL, &iIDRPeriod);
560587 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 · 215 unmodified lines
776803
777804 TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLIDR) {
778805 EncodeDecodeFileParamBase p = GetParam();
779− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
806+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
780807 encoder_->Uninitialize();
781808 int rv = encoder_->InitializeExt (&param_);
782809 ASSERT_TRUE (rv == cmResultSuccess);
@@ -809,7 +836,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionLTR_ALLLTR) { · 26 unmodified lines
809836 SLTRMarkingFeedback m_LTR_Marking_Feedback;
810837 SLTRRecoverRequest m_LTR_Recover_Request;
811838 EncodeDecodeFileParamBase p = GetParam();
812− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
839+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
813840 encoder_->Uninitialize();
814841 int rv = encoder_->InitializeExt (&param_);
815842 ASSERT_TRUE (rv == cmResultSuccess);
@@ -868,7 +895,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionLTR_Engine) { · 52 unmodified lines
868895 SLTRRecoverRequest m_LTR_Recover_Request;
869896 m_LTR_Recover_Request.uiIDRPicId = 0;
870897 EncodeDecodeFileParamBase p = GetParam();
871− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
898+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
872899 encoder_->Uninitialize();
873900 int rv = encoder_->InitializeExt (&param_);
874901 ASSERT_TRUE (rv == cmResultSuccess);
@@ -918,7 +945,7 @@ TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_DISABLE) { · 43 unmodified lines
918945 SLTRRecoverRequest m_LTR_Recover_Request;
919946 m_LTR_Recover_Request.uiIDRPicId = 0;
920947 EncodeDecodeFileParamBase p = GetParam();
921− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
948+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
922949 param_.bEnableLongTermReference = true;
923950 param_.iLTRRefNum = 1;
924951 encoder_->Uninitialize();
@@ -985,7 +1012,7 @@ TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_SLICE_COPY) { · 60 unmodified lines
9851012 SLTRRecoverRequest m_LTR_Recover_Request;
9861013 m_LTR_Recover_Request.uiIDRPicId = 0;
9871014 EncodeDecodeFileParamBase p = GetParam();
988− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
1015+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
9891016 encoder_->Uninitialize();
9901017 int rv = encoder_->InitializeExt (&param_);
9911018 ASSERT_TRUE (rv == cmResultSuccess);
@@ -1036,7 +1063,7 @@ TEST_P (EncodeDecodeTestAPI, SetOptionECFlag_ERROR_CON_SLICE_COPY) { · 44 unmodified lines
10361063
10371064 TEST_P (EncodeDecodeTestAPI, InOutTimeStamp) {
10381065 EncodeDecodeFileParamBase p = GetParam();
1039− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
1066+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
10401067 encoder_->Uninitialize();
10411068 int rv = encoder_->InitializeExt (&param_);
10421069 ASSERT_TRUE (rv == cmResultSuccess);
@@ -1086,7 +1113,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_NOPREFIX) { · 43 unmodified lines
10861113 SLTRRecoverRequest m_LTR_Recover_Request;
10871114 m_LTR_Recover_Request.uiIDRPicId = 0;
10881115 EncodeDecodeFileParamBase p = GetParam();
1089− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
1116+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
10901117 param_.bPrefixNalAddingCtrl = false;
10911118 param_.iTemporalLayerNum = (rand() % 4) + 1;
10921119 encoder_->Uninitialize();
@@ -1155,7 +1182,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionTid_AVC_WITH_PREFIX_NOLOSS) { · 62 unmodified lines
11551182 SLTRRecoverRequest m_LTR_Recover_Request;
11561183 m_LTR_Recover_Request.uiIDRPicId = 0;
11571184 EncodeDecodeFileParamBase p = GetParam();
1158− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
1185+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
11591186 param_.bPrefixNalAddingCtrl = true;
11601187 param_.iTemporalLayerNum = (rand() % 4) + 1;
11611188 param_.iSpatialLayerNum = 1;
@@ -1210,7 +1237,7 @@ TEST_P (EncodeDecodeTestAPI, GetOptionTid_SVC_L1_NOLOSS) { · 48 unmodified lines
12101237 SLTRRecoverRequest m_LTR_Recover_Request;
12111238 m_LTR_Recover_Request.uiIDRPicId = 0;
12121239 EncodeDecodeFileParamBase p = GetParam();
1213− prepareParam (2, p.slicenum, p.width, p.height, p.frameRate);
1240+ prepareParam (2, p.slicenum, p.width, p.height, p.frameRate, &param_);
12141241 param_.iTemporalLayerNum = (rand() % 4) + 1;
12151242 param_.iSpatialLayerNum = 2;
12161243 encoder_->Uninitialize();
@@ -1266,7 +1293,7 @@ TEST_P (EncodeDecodeTestAPI, SetOption_Trace) { · 49 unmodified lines
12661293 SLTRRecoverRequest m_LTR_Recover_Request;
12671294 m_LTR_Recover_Request.uiIDRPicId = 0;
12681295 EncodeDecodeFileParamBase p = GetParam();
1269− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
1296+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
12701297 param_.iSpatialLayerNum = 1;
12711298
12721299 int rv = encoder_->InitializeExt (&param_);
@@ -1330,7 +1357,7 @@ TEST_P (EncodeDecodeTestAPI, SetOption_Trace_NULL) { · 57 unmodified lines
13301357 SLTRRecoverRequest m_LTR_Recover_Request;
13311358 m_LTR_Recover_Request.uiIDRPicId = 0;
13321359 EncodeDecodeFileParamBase p = GetParam();
1333− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
1360+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
13341361 param_.iSpatialLayerNum = 1;
13351362 int rv = encoder_->InitializeExt (&param_);
13361363 ASSERT_TRUE (rv == cmResultSuccess);
@@ -1393,7 +1420,7 @@ TEST_P (EncodeDecodeTestAPI, SetOptionECIDC_GeneralSliceChange) { · 56 unmodified lines
13931420 uint32_t uiEcIdc;
13941421 uint32_t uiGet;
13951422 EncodeDecodeFileParamBase p = GetParam();
1396− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
1423+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
13971424 param_.iSpatialLayerNum = 1;
13981425 encoder_->Uninitialize();
13991426 int rv = encoder_->InitializeExt (&param_);
@@ -1473,7 +1500,7 @@ TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificFrameChange) { · 73 unmodified lines
14731500 uint32_t uiEcIdc;
14741501 uint32_t uiGet;
14751502 EncodeDecodeFileParamBase p = kFileParamArray[0];
1476− prepareParam (1, p.slicenum, p.width, p.height, p.frameRate);
1503+ prepareParam (1, p.slicenum, p.width, p.height, p.frameRate, &param_);
14771504 param_.iSpatialLayerNum = 1;
14781505 encoder_->Uninitialize();
14791506 int rv = encoder_->InitializeExt (&param_);
@@ -1612,7 +1639,7 @@ TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificSliceChange_IDRLoss) { · 132 unmodified lines
16121639 uint32_t uiEcIdc = 2; //default set as SLICE_COPY
16131640 uint32_t uiGet;
16141641 EncodeDecodeFileParamBase p = kFileParamArray[0];
1615− prepareParam (1, 2, p.width, p.height, p.frameRate);
1642+ prepareParam (1, 2, p.width, p.height, p.frameRate, &param_);
16161643 param_.iSpatialLayerNum = 1;
16171644 encoder_->Uninitialize();
16181645 int rv = encoder_->InitializeExt (&param_);
@@ -1745,7 +1772,7 @@ TEST_F (EncodeDecodeTestAPI, SetOptionECIDC_SpecificSliceChange_IDRNoLoss) { · 126 unmodified lines
17451772 uint32_t uiEcIdc;
17461773 uint32_t uiGet;
17471774 EncodeDecodeFileParamBase p = kFileParamArray[0];
1748− prepareParam (1, 2, p.width, p.height, p.frameRate);
1775+ prepareParam (1, 2, p.width, p.height, p.frameRate, &param_);
17491776 param_.iSpatialLayerNum = 1;
17501777 encoder_->Uninitialize();
17511778 int rv = encoder_->InitializeExt (&param_);
@@ -1914,7 +1941,7 @@ TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_I) { · 162 unmodified lines
19141941 EncodeDecodeFileParamBase p = kSVCSwitch[0];
19151942 p.width = p.width << 2;
19161943 p.height = p.height << 2;
1917− prepareParam (4, p.slicenum, p.width, p.height, p.frameRate);
1944+ prepareParam (4, p.slicenum, p.width, p.height, p.frameRate, &param_);
19181945 param_.iTemporalLayerNum = (rand() % 4) + 1;
19191946 param_.iSpatialLayerNum = 4;
19201947 encoder_->Uninitialize();
@@ -1979,7 +2006,7 @@ TEST_F (EncodeDecodeTestAPI, Engine_SVC_Switch_P) { · 58 unmodified lines
19792006 int iLastDid = 0;
19802007 p.width = p.width << 2;
19812008 p.height = p.height << 2;
1982− prepareParam (4, p.slicenum, p.width, p.height, p.frameRate);
2009+ prepareParam (4, p.slicenum, p.width, p.height, p.frameRate, &param_);
19832010 param_.iTemporalLayerNum = (rand() % 4) + 1;
19842011 param_.iSpatialLayerNum = 4;
19852012 encoder_->Uninitialize();
@@ -2065,7 +2092,7 @@ TEST_F (EncodeDecodeTestAPI, SetOptionEncParamExt) { · 79 unmodified lines
20652092 int iEncFrameNum = WelsClip3 ((rand() % ENCODE_FRAME_NUM) + 1, 1, ENCODE_FRAME_NUM);
20662093 int iSliceNum = 1;
20672094 encoder_->GetDefaultParams (&param_);
2068− prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate);
2095+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &param_);
20692096
20702097 int rv = encoder_->InitializeExt (&param_);
20712098 ASSERT_TRUE (rv == cmResultSuccess);
@@ -2128,8 +2155,8 @@ class DecodeCrashTestAPI : public EncodeDecodeTestBase { · 56 unmodified lines
21282155 ASSERT_TRUE (ucBuf_ == NULL);
21292156 }
21302157
2131− void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate) {
2132− EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate);
2158+ void prepareParam (int iLayerNum, int iSliceNum, int width, int height, float framerate, SEncParamExt* pParam) {
2159+ EncodeDecodeTestBase::prepareParam (iLayerNum, iSliceNum, width, height, framerate, pParam);
21332160 }
21342161
21352162 void prepareEncDecParam (const EncodeDecodeFileParamBase EncDecFileParam);
@@ -2203,11 +2230,11 @@ TEST_F (DecodeCrashTestAPI, DecoderCrashTest) { · 67 unmodified lines
22032230 int iSeed = rand() % 3; //3 indicates the length of kParamArray[] used in the following
22042231 EncodeDecodeParamBase p = kParamArray[iSeed];
22052232 //Initialize Encoder
2206− prepareParam (1, 1, p.width, p.height, p.frameRate);
2233+ prepareParam (1, 1, p.width, p.height, p.frameRate, &param_);
22072234 param_.iRCMode = RC_BITRATE_MODE;
22082235 param_.iTargetBitrate = p.iTarBitrate;
22092236 param_.uiIntraPeriod = 0;
2210− param_.bEnableSpsPpsIdAddition = true;
2237+ param_.iSpsPpsIdStrategy = INCREASING_ID;
22112238 param_.bEnableBackgroundDetection = true;
22122239 param_.bEnableSceneChangeDetect = true;
22132240 param_.bPrefixNalAddingCtrl = true;
@@ -2398,7 +2425,7 @@ TEST_F (DecodeParseAPI, ParseOnly_General) { · 184 unmodified lines
23982425 p.height = iHeight_;
23992426 p.frameRate = kiFrameRate;
24002427 p.numframes = kiFrameNum;
2401− prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate);
2428+ prepareParam (kiTotalLayer, kiSliceNum, p.width, p.height, p.frameRate, &param_);
24022429 param_.iSpatialLayerNum = kiTotalLayer;
24032430 encoder_->Uninitialize();
24042431 int rv = encoder_->InitializeExt (&param_);
@@ -2475,7 +2502,7 @@ TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) { · 70 unmodified lines
24752502 p.height = iHeight_;
24762503 p.frameRate = kiFrameRate;
24772504 p.numframes = 5;
2478− prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate);
2505+ prepareParam (iLayerNum, iSliceNum, p.width, p.height, p.frameRate, &param_);
24792506 param_.iSpatialLayerNum = iLayerNum;
24802507 encoder_->Uninitialize();
24812508 int rv = encoder_->InitializeExt (&param_);
@@ -2525,3 +2552,434 @@ TEST_F (DecodeParseAPI, ParseOnly_SpecSliceLoss) { · 43 unmodified lines
25252552 } //while
25262553 }
25272554
2555+//#define DEBUG_FILE_SAVE2
2556+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING1) {
2557+
2558+ int iWidth = GetRandWidth();
2559+ int iHeight = GetRandHeight();
2560+ float fFrameRate = rand() + 0.5f;
2561+ int iEncFrameNum = 0;
2562+ int iSpatialLayerNum = 1;
2563+ int iSliceNum = 1;
2564+
2565+ // prepare params
2566+ SEncParamExt sParam1;
2567+ SEncParamExt sParam2;
2568+ SEncParamExt sParam3;
2569+ encoder_->GetDefaultParams (&sParam1);
2570+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
2571+ sParam1.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
2572+ //prepare param2
2573+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
2574+ while (sParam2.iPicWidth == sParam1.iPicWidth) {
2575+ sParam2.iPicWidth = GetRandWidth();
2576+ }
2577+ prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
2578+ sParam2.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
2579+ //prepare param3
2580+ memcpy (&sParam3, &sParam1, sizeof (SEncParamExt));
2581+ while (sParam3.iPicHeight == sParam1.iPicHeight) {
2582+ sParam3.iPicHeight = GetRandHeight();
2583+ }
2584+ prepareParam (iSpatialLayerNum, iSliceNum, sParam3.iPicWidth, sParam3.iPicHeight, fFrameRate, &sParam3);
2585+ sParam3.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
2586+
2587+ //prepare output if needed
2588+ FILE* fEnc = NULL;
2589+#ifdef DEBUG_FILE_SAVE2
2590+ fEnc = fopen ("enc2.264", "wb");
2591+#endif
2592+
2593+ // Test part#1
2594+ // step#1: pParam1
2595+ //int TraceLevel = WELS_LOG_INFO;
2596+ //encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &TraceLevel);
2597+ int rv = encoder_->InitializeExt (&sParam1);
2598+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
2599+ sParam1.iPicHeight;
2600+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2601+
2602+ // new IDR
2603+ rv = encoder_->ForceIntraFrame (true);
2604+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2605+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2606+
2607+ // step#2: pParam2
2608+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
2609+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam2.iPicWidth << "x" <<
2610+ sParam2.iPicHeight;
2611+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
2612+
2613+ // new IDR
2614+ rv = encoder_->ForceIntraFrame (true);
2615+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2616+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
2617+
2618+ // step#3: back to pParam1
2619+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
2620+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
2621+ sParam1.iPicHeight;
2622+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2623+
2624+ // step#4: back to pParam2
2625+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
2626+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv << sParam2.iPicWidth << sParam2.iPicHeight;
2627+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
2628+
2629+#ifdef DEBUG_FILE_SAVE2
2630+ fclose (fEnc);
2631+#endif
2632+ rv = encoder_->Uninitialize();
2633+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2634+
2635+ // Test part#2
2636+ // step#1: pParam1
2637+ rv = encoder_->InitializeExt (&sParam1);
2638+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt Failed: rv = " << rv;
2639+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
2640+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
2641+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam3);
2642+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam3: rv = " << rv;
2643+
2644+#ifdef DEBUG_FILE_SAVE2
2645+ fEnc = fopen ("enc3.264", "wb");
2646+#endif
2647+ iEncFrameNum = 0;
2648+ EncDecOneFrame (sParam3.iPicWidth, sParam3.iPicHeight, iEncFrameNum++, fEnc);
2649+
2650+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
2651+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
2652+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
2653+
2654+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
2655+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
2656+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2657+
2658+#ifdef DEBUG_FILE_SAVE2
2659+ fclose (fEnc);
2660+#endif
2661+ rv = encoder_->Uninitialize();
2662+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2663+}
2664+
2665+#define DEBUG_FILE_SAVE5
2666+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING2) {
2667+ //usage 3: 2 Params with different num_ref, encode IDR0, P1, IDR2;
2668+ //the bs will show two SPS and different PPS
2669+
2670+ int iWidth = GetRandWidth();
2671+ int iHeight = GetRandHeight();
2672+ float fFrameRate = rand() + 0.5f;
2673+ int iEncFrameNum = 0;
2674+ int iSpatialLayerNum = 1;
2675+ int iSliceNum = 1;
2676+
2677+ // prepare params
2678+ SEncParamExt sParam1;
2679+ SEncParamExt sParam2;
2680+ encoder_->GetDefaultParams (&sParam1);
2681+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
2682+ sParam1.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
2683+ sParam1.iTemporalLayerNum = 1;
2684+ //prepare param2
2685+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
2686+ prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
2687+ sParam2.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
2688+ sParam2.iTemporalLayerNum = 3;
2689+
2690+ //prepare output if needed
2691+ FILE* fEnc = NULL;
2692+#ifdef DEBUG_FILE_SAVE5
2693+ fEnc = fopen ("encID2.264", "wb");
2694+#endif
2695+
2696+ // step#1: pParam1
2697+ int rv = encoder_->InitializeExt (&sParam1);
2698+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
2699+ sParam1.iPicHeight;
2700+
2701+ // step#2: pParam2
2702+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
2703+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
2704+
2705+ // step#3: set back to pParam1, with a smaller num_ref, it still uses the previous SPS
2706+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
2707+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam1: rv = " << rv;
2708+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2709+
2710+ // new IDR, PPS increases
2711+ rv = encoder_->ForceIntraFrame (true);
2712+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2713+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2714+
2715+ rv = encoder_->Uninitialize();
2716+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2717+
2718+#ifdef DEBUG_FILE_SAVE5
2719+ fclose (fEnc);
2720+#endif
2721+}
2722+
2723+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_LISTING_AND_PPS_INCREASING3) {
2724+
2725+ int iWidth = GetRandWidth();
2726+ int iHeight = GetRandHeight();
2727+ float fFrameRate = rand() + 0.5f;
2728+ int iEncFrameNum = 0;
2729+ int iSpatialLayerNum = 1;
2730+ int iSliceNum = 1;
2731+
2732+ // prepare params
2733+ SEncParamExt sParam1;
2734+ SEncParamExt sParam2;
2735+ encoder_->GetDefaultParams (&sParam1);
2736+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
2737+ sParam1.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
2738+
2739+ //prepare output if needed
2740+ FILE* fEnc = NULL;
2741+#ifdef DEBUG_FILE_SAVE2
2742+ fEnc = fopen ("enc4.264", "wb");
2743+#endif
2744+
2745+ // step#1: pParam1
2746+ int rv = encoder_->InitializeExt (&sParam1);
2747+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt Failed: rv = " << rv;
2748+
2749+ int max_count = 65; // make it more then twice as MAX_SPS_COUNT
2750+ std::vector<int> vWidthTable;
2751+ vWidthTable.push_back (sParam1.iPicWidth);
2752+
2753+ std::vector<int>::iterator vWidthTableIt;
2754+ for (int times = 0; times < max_count; times++) {
2755+ //prepare param2
2756+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
2757+ do {
2758+ sParam2.iPicWidth = GetRandWidth();
2759+ vWidthTableIt = std::find (vWidthTable.begin(), vWidthTable.end(), sParam2.iPicWidth);
2760+ } while (vWidthTableIt == vWidthTable.end());
2761+ vWidthTable.push_back (sParam2.iPicWidth);
2762+ prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
2763+ sParam2.iSpsPpsIdStrategy = SPS_LISTING_AND_PPS_INCREASING;
2764+
2765+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
2766+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv << ", sParam2.iPicWidth=" <<
2767+ sParam2.iPicWidth;
2768+ } // end of setting loop
2769+
2770+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
2771+
2772+#ifdef DEBUG_FILE_SAVE2
2773+ fclose (fEnc);
2774+#endif
2775+ rv = encoder_->Uninitialize();
2776+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2777+}
2778+
2779+//#define DEBUG_FILE_SAVE6
2780+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING1) {
2781+ //usage 1: 1 resolution Params, encode IDR0, P1, IDR2;
2782+ //the bs will show same SPS and different PPS
2783+ // PPS: pic_parameter_set_id 1 ( 0)
2784+ // PPS: seq_parameter_set_id 1 ( 0)
2785+ // PPS: pic_parameter_set_id 010 ( 1)
2786+ // PPS: seq_parameter_set_id 1 ( 0)
2787+ // SH: slice_type 011 ( 2)
2788+ // SH: pic_parameter_set_id 1 ( 0)
2789+ // SH: slice_type 1 ( 0)
2790+ // SH: pic_parameter_set_id 1 ( 0)
2791+ // SH: slice_type 011 ( 2)
2792+ // SH: pic_parameter_set_id 010 ( 1)
2793+ int iWidth = GetRandWidth();
2794+ int iHeight = GetRandHeight();
2795+ float fFrameRate = rand() + 0.5f;
2796+ int iEncFrameNum = 0;
2797+ int iSpatialLayerNum = 1;
2798+ int iSliceNum = 1;
2799+
2800+ // prepare params
2801+ SEncParamExt sParam1;
2802+ encoder_->GetDefaultParams (&sParam1);
2803+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
2804+ sParam1.iSpsPpsIdStrategy = SPS_PPS_LISTING;
2805+
2806+ //prepare output if needed
2807+ FILE* fEnc = NULL;
2808+#ifdef DEBUG_FILE_SAVE6
2809+ fEnc = fopen ("encLIST1.264", "wb");
2810+#endif
2811+
2812+ // step#1: pParam1
2813+ int rv = encoder_->InitializeExt (&sParam1);
2814+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
2815+ sParam1.iPicHeight;
2816+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2817+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2818+
2819+ // new IDR
2820+ rv = encoder_->ForceIntraFrame (true);
2821+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2822+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2823+
2824+ rv = encoder_->Uninitialize();
2825+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2826+
2827+#ifdef DEBUG_FILE_SAVE6
2828+ fclose (fEnc);
2829+#endif
2830+}
2831+
2832+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING2) {
2833+ //usage 2: 2 resolution Params, encode IDR0, IDR1, IDR2;
2834+ //the bs will show two SPS and different PPS
2835+ // === SPS LIST ===
2836+ //SPS: seq_parameter_set_id 1 ( 0) -- PARAM1
2837+ //SPS: seq_parameter_set_id 010 ( 1) -- PARAM2
2838+ // === PPS LIST ===
2839+ //PPS: pic_parameter_set_id 1 ( 0)
2840+ //PPS: seq_parameter_set_id 1 ( 0)
2841+ //PPS: pic_parameter_set_id 010 ( 1)
2842+ //PPS: seq_parameter_set_id 010 ( 1)
2843+ //PPS: pic_parameter_set_id 011 ( 2) -- PPS2 - SPS0
2844+ //PPS: seq_parameter_set_id 1 ( 0)
2845+ //PPS: pic_parameter_set_id 00100 ( 3) -- PPS3 - SPS1
2846+ //PPS: seq_parameter_set_id 010 ( 1)
2847+ //PPS: pic_parameter_set_id 00101 ( 4) -- PPS4 - SPS0
2848+ //PPS: seq_parameter_set_id 1 ( 0)
2849+ // === VCL LAYER ===
2850+ //SH: slice_type 011 ( 2) -- PARAM2
2851+ //SH: pic_parameter_set_id 010 ( 1) -- PPS1 - SPS1 - PARAM2
2852+ //SH: slice_type 011 ( 2) -- PARAM1
2853+ //SH: pic_parameter_set_id 011 ( 2) -- PPS2 - SPS0 - PARAM1
2854+ //SH: slice_type 011 ( 2) -- PARAM1
2855+ //SH: pic_parameter_set_id 00101 ( 4) -- PPS4 - SPS0 - PARAM1
2856+
2857+ int iWidth = GetRandWidth();
2858+ int iHeight = GetRandHeight();
2859+ float fFrameRate = rand() + 0.5f;
2860+ int iEncFrameNum = 0;
2861+ int iSpatialLayerNum = 1;
2862+ int iSliceNum = 1;
2863+
2864+ // prepare params
2865+ SEncParamExt sParam1;
2866+ SEncParamExt sParam2;
2867+ encoder_->GetDefaultParams (&sParam1);
2868+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
2869+ sParam1.iSpsPpsIdStrategy = SPS_PPS_LISTING;
2870+ //prepare param2
2871+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
2872+ while (sParam2.iPicWidth == sParam1.iPicWidth) {
2873+ sParam2.iPicWidth = GetRandWidth();
2874+ }
2875+ prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
2876+ sParam2.iSpsPpsIdStrategy = SPS_PPS_LISTING;
2877+
2878+ //prepare output if needed
2879+ FILE* fEnc = NULL;
2880+#ifdef DEBUG_FILE_SAVE5
2881+ fEnc = fopen ("encLIST2.264", "wb");
2882+#endif
2883+
2884+ // step#1: pParam1
2885+ int rv = encoder_->InitializeExt (&sParam1);
2886+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
2887+ sParam1.iPicHeight;
2888+
2889+ // step#2: pParam2
2890+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
2891+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
2892+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
2893+
2894+ // step#3: back to pParam1, SHOULD NOT encounter ERROR
2895+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam1);
2896+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
2897+ sParam1.iPicHeight;
2898+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2899+
2900+ // new IDR
2901+ rv = encoder_->ForceIntraFrame (true);
2902+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2903+ EncDecOneFrame (sParam1.iPicWidth, sParam1.iPicHeight, iEncFrameNum++, fEnc);
2904+
2905+ rv = encoder_->Uninitialize();
2906+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2907+
2908+#ifdef DEBUG_FILE_SAVE5
2909+ fclose (fEnc);
2910+#endif
2911+}
2912+
2913+TEST_F (EncodeDecodeTestAPI, ParameterSetStrategy_SPS_PPS_LISTING3) {
2914+
2915+ int iWidth = GetRandWidth();
2916+ int iHeight = GetRandHeight();
2917+ float fFrameRate = rand() + 0.5f;
2918+ int iEncFrameNum = 0;
2919+ int iSpatialLayerNum = 1;
2920+ int iSliceNum = 1;
2921+
2922+ // prepare params
2923+ SEncParamExt sParam1;
2924+ SEncParamExt sParam2;
2925+ SEncParamExt sParam3;
2926+ encoder_->GetDefaultParams (&sParam1);
2927+ prepareParam (iSpatialLayerNum, iSliceNum, iWidth, iHeight, fFrameRate, &sParam1);
2928+ sParam1.iSpsPpsIdStrategy = SPS_PPS_LISTING;
2929+ //prepare param2
2930+ memcpy (&sParam2, &sParam1, sizeof (SEncParamExt));
2931+ while (sParam2.iPicWidth == sParam1.iPicWidth) {
2932+ sParam2.iPicWidth = GetRandWidth();
2933+ }
2934+ prepareParam (iSpatialLayerNum, iSliceNum, sParam2.iPicWidth, sParam2.iPicHeight, fFrameRate, &sParam2);
2935+ sParam2.iSpsPpsIdStrategy = SPS_PPS_LISTING;
2936+ //prepare param3
2937+ memcpy (&sParam3, &sParam1, sizeof (SEncParamExt));
2938+ while (sParam3.iPicWidth == sParam1.iPicWidth || sParam3.iPicWidth == sParam2.iPicWidth) {
2939+ sParam3.iPicWidth = GetRandWidth();
2940+ }
2941+ prepareParam (iSpatialLayerNum, iSliceNum, sParam3.iPicWidth, sParam3.iPicHeight, fFrameRate, &sParam3);
2942+ sParam3.iSpsPpsIdStrategy = SPS_PPS_LISTING;
2943+
2944+ //prepare output if needed
2945+ FILE* fEnc = NULL;
2946+#ifdef DEBUG_FILE_SAVE5
2947+ fEnc = fopen ("enc4.264", "wb");
2948+#endif
2949+
2950+ // step#1: ordinary encoding
2951+ int rv = encoder_->InitializeExt (&sParam1);
2952+ ASSERT_TRUE (rv == cmResultSuccess) << "InitializeExt: rv = " << rv << " at " << sParam1.iPicWidth << "x" <<
2953+ sParam1.iPicHeight;
2954+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam2);
2955+ ASSERT_TRUE (rv == cmResultSuccess) << "SetOption Failed sParam2: rv = " << rv;
2956+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
2957+
2958+ // step#2: set strategy for success
2959+ int32_t iNewStra = SPS_PPS_LISTING;
2960+ rv = encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iNewStra);
2961+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv << " iNewStra=" << iNewStra;
2962+
2963+ // step#3: setting new strategy, SHOULD encounter ERROR
2964+ unsigned int TraceLevel = WELS_LOG_QUIET;
2965+ rv = encoder_->SetOption (ENCODER_OPTION_TRACE_LEVEL, &TraceLevel);
2966+ ASSERT_TRUE (rv == cmResultSuccess);
2967+ iNewStra = CONSTANT_ID;
2968+ rv = encoder_->SetOption (ENCODER_OPTION_ENABLE_SPS_PPS_ID_ADDITION, &iNewStra);
2969+ ASSERT_TRUE (rv != cmResultSuccess);
2970+
2971+ EncDecOneFrame (sParam2.iPicWidth, sParam2.iPicHeight, iEncFrameNum++, fEnc);
2972+
2973+ // step#4: pParam3, SHOULD encounter ERROR
2974+ rv = encoder_->SetOption (ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sParam3);
2975+ ASSERT_TRUE (rv != cmResultSuccess) << "SetOption: rv = " << rv << " at " << sParam3.iPicWidth << "x" <<
2976+ sParam3.iPicHeight;
2977+
2978+ rv = encoder_->Uninitialize();
2979+ ASSERT_TRUE (rv == cmResultSuccess) << "rv = " << rv;
2980+
2981+#ifdef DEBUG_FILE_SAVE5
2982+ fclose (fEnc);
2983+#endif
2984+}
2985+
test/encoder/EncUT_ParameterSetStrategy.cpp+122−0
@@ -0,0 +1,122 @@
1+#include <stdlib.h>
2+#include "gtest/gtest.h"
3+
4+#include "au_set.h"
5+#include "param_svc.h"
6+#include "parameter_sets.h"
7+#include "wels_const.h"
8+
9+using namespace WelsEnc;
10+
11+class ParameterSetStrategyTest : public ::testing::Test {
12+ public:
13+ virtual void SetUp() {
14+ pMa = NULL;
15+ m_pSpsArray = NULL;
16+ m_pSubsetArray = NULL;
17+
18+ pMa = new CMemoryAlign (0);
19+ m_pSpsArray = (SWelsSPS*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SWelsSPS), "m_pSpsArray");
20+ ASSERT_TRUE (NULL != m_pSpsArray);
21+ m_pSubsetArray = (SSubsetSps*)pMa->WelsMalloc (MAX_SPS_COUNT * sizeof (SSubsetSps), "m_pSubsetArray");
22+ ASSERT_TRUE (NULL != m_pSubsetArray);
23+
24+ m_pSpsArrayPointer = &m_pSpsArray[0];
25+ m_pSubsetArrayPointer = &m_pSubsetArray[0];
26+
27+ }
28+ virtual void TearDown() {
29+ pMa->WelsFree (m_pSpsArray, "m_pSpsArray");
30+ pMa->WelsFree (m_pSubsetArray, "m_pSubsetArray");
31+ delete pMa;
32+ }
33+ void GenerateParam (SWelsSvcCodingParam* pParam);
34+ public:
35+ CMemoryAlign* pMa;
36+ SWelsSPS* m_pSpsArray;
37+ SSubsetSps* m_pSubsetArray;
38+
39+ SWelsSPS* m_pSpsArrayPointer;
40+ SSubsetSps* m_pSubsetArrayPointer;
41+
42+};
43+
44+void ParameterSetStrategyTest::GenerateParam (SWelsSvcCodingParam* pParam) {
45+ SEncParamBase sEncParamBase;
46+ //TODO: consider randomize it
47+ sEncParamBase.iUsageType = CAMERA_VIDEO_REAL_TIME;
48+ sEncParamBase.iPicWidth = 1280;
49+ sEncParamBase.iPicHeight = 720;
50+ sEncParamBase.iTargetBitrate = 1000000;
51+ sEncParamBase.iRCMode = RC_BITRATE_MODE;
52+ sEncParamBase.fMaxFrameRate = 30.0f;
53+ pParam->ParamBaseTranscode (sEncParamBase);
54+}
55+
56+TEST_F (ParameterSetStrategyTest, FindExistingSps) {
57+ int iDlayerIndex = 0;
58+ int iDlayerCount = 0;
59+ bool bUseSubsetSps = false;
60+ int iFoundId = -1;
61+ int iRet = 0;
62+ SSpatialLayerConfig* pDlayerParam;
63+
64+ //init parameter
65+ SWelsSvcCodingParam sParam1;
66+ GenerateParam (&sParam1);
67+
68+ //prepare first SPS
69+ int iCurSpsId = 0;
70+ int iCurSpsInUse = 1;
71+ m_pSpsArrayPointer = &m_pSpsArray[iCurSpsId];
72+
73+ pDlayerParam = & (sParam1.sSpatialLayers[iDlayerIndex]);
74+ iRet = WelsInitSps (m_pSpsArrayPointer, pDlayerParam, &sParam1.sDependencyLayers[iDlayerIndex], sParam1.uiIntraPeriod,
75+ sParam1.iMaxNumRefFrame,
76+ iCurSpsId, sParam1.bEnableFrameCroppingFlag, sParam1.iRCMode != RC_OFF_MODE, iDlayerCount);
77+
78+ // try finding #0
79+ iFoundId = FindExistingSps (&sParam1, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
80+ m_pSpsArray, m_pSubsetArray);
81+ EXPECT_EQ (iFoundId, iCurSpsId);
82+
83+ // try not finding
84+ SWelsSvcCodingParam sParam2 = sParam1;
85+ sParam2.iMaxNumRefFrame ++;
86+ iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
87+ m_pSpsArray, m_pSubsetArray);
88+ EXPECT_EQ (iFoundId, INVALID_ID);
89+
90+ // add new sps
91+ iCurSpsId = 1;
92+ m_pSpsArrayPointer = &m_pSpsArray[iCurSpsId];
93+ pDlayerParam = & (sParam2.sSpatialLayers[iDlayerIndex]);
94+ iRet = WelsInitSps (m_pSpsArrayPointer, pDlayerParam, &sParam2.sDependencyLayers[iDlayerIndex], sParam2.uiIntraPeriod,
95+ sParam2.iMaxNumRefFrame,
96+ iCurSpsId, sParam2.bEnableFrameCroppingFlag, sParam2.iRCMode != RC_OFF_MODE, iDlayerCount);
97+ iCurSpsInUse = 2;
98+
99+ // try finding #1
100+ iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
101+ m_pSpsArray, m_pSubsetArray);
102+ EXPECT_EQ (iFoundId, iCurSpsId);
103+
104+ // try finding #0
105+ iFoundId = FindExistingSps (&sParam1, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
106+ m_pSpsArray, m_pSubsetArray);
107+ EXPECT_EQ (iFoundId, 0);
108+
109+ // try not finding
110+ if (sParam2.sDependencyLayers[0].iActualWidth > 1) {
111+
112+ sParam2.sDependencyLayers[0].iActualWidth--;
113+ } else {
114+ sParam2.sDependencyLayers[0].iActualWidth++;
115+ }
116+
117+ iFoundId = FindExistingSps (&sParam2, bUseSubsetSps, iDlayerIndex, iDlayerCount, iCurSpsInUse,
118+ m_pSpsArray, m_pSubsetArray);
119+ EXPECT_EQ (iFoundId, INVALID_ID);
120+}
121+
122+
test/encoder/targets.mk+1−0
@@ -11,6 +11,7 @@ ENCODER_UNITTEST_CPP_SRCS=\ · 10 unmodified lines
1111 $(ENCODER_UNITTEST_SRCDIR)/EncUT_MemoryAlloc.cpp\
1212 $(ENCODER_UNITTEST_SRCDIR)/EncUT_MemoryZero.cpp\
1313 $(ENCODER_UNITTEST_SRCDIR)/EncUT_MotionEstimate.cpp\
14+ $(ENCODER_UNITTEST_SRCDIR)/EncUT_ParameterSetStrategy.cpp\
1415 $(ENCODER_UNITTEST_SRCDIR)/EncUT_Reconstruct.cpp\
1516 $(ENCODER_UNITTEST_SRCDIR)/EncUT_Sample.cpp\
1617 $(ENCODER_UNITTEST_SRCDIR)/EncUT_SVC_me.cpp\

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t