1 /*!
2 * \copy
3 * Copyright (c) 2013, Cisco Systems
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33 #include "au_set.h"
34 #include "encoder_context.h"
35 #include "paraset_strategy.h"
36
37 namespace WelsEnc {
38
39
CreateParametersetStrategy(EParameterSetStrategy eSpsPpsIdStrategy,bool bSimulcastAVC,const int32_t kiSpatialLayerNum)40 IWelsParametersetStrategy* IWelsParametersetStrategy::CreateParametersetStrategy (
41 EParameterSetStrategy eSpsPpsIdStrategy, bool bSimulcastAVC,
42 const int32_t kiSpatialLayerNum) {
43
44 IWelsParametersetStrategy* pParametersetStrategy = NULL;
45 switch (eSpsPpsIdStrategy) {
46 case INCREASING_ID:
47 pParametersetStrategy = WELS_NEW_OP (CWelsParametersetIdIncreasing (bSimulcastAVC, kiSpatialLayerNum),
48 CWelsParametersetIdIncreasing);
49 WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
50 break;
51 case SPS_LISTING:
52 pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsListing (bSimulcastAVC, kiSpatialLayerNum),
53 CWelsParametersetSpsListing);
54 WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
55 break;
56 case SPS_LISTING_AND_PPS_INCREASING:
57 pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsListingPpsIncreasing (bSimulcastAVC, kiSpatialLayerNum),
58 CWelsParametersetSpsListingPpsIncreasing);
59 WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
60 break;
61 case SPS_PPS_LISTING:
62 pParametersetStrategy = WELS_NEW_OP (CWelsParametersetSpsPpsListing (bSimulcastAVC, kiSpatialLayerNum),
63 CWelsParametersetSpsPpsListing);
64 WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
65 break;
66 case CONSTANT_ID:
67 default:
68 pParametersetStrategy = WELS_NEW_OP (CWelsParametersetIdConstant (bSimulcastAVC, kiSpatialLayerNum),
69 CWelsParametersetIdConstant);
70 WELS_VERIFY_RETURN_IF (NULL, NULL == pParametersetStrategy)
71 break;
72 }
73
74 return pParametersetStrategy;
75 }
76
77
WelsGenerateNewSps(sWelsEncCtx * pCtx,const bool kbUseSubsetSps,const int32_t iDlayerIndex,const int32_t iDlayerCount,const int32_t kiSpsId,SWelsSPS * & pSps,SSubsetSps * & pSubsetSps,bool bSVCBaselayer)78 static int32_t WelsGenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
79 const int32_t iDlayerCount, const int32_t kiSpsId,
80 SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) {
81 int32_t iRet = 0;
82
83 if (!kbUseSubsetSps) {
84 pSps = & (pCtx->pSpsArray[kiSpsId]);
85 } else {
86 pSubsetSps = & (pCtx->pSubsetArray[kiSpsId]);
87 pSps = &pSubsetSps->pSps;
88 }
89
90 SWelsSvcCodingParam* pParam = pCtx->pSvcParam;
91 SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
92 // Need port pSps/pPps initialization due to spatial scalability changed
93 if (!kbUseSubsetSps) {
94 iRet = WelsInitSps (pSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
95 pParam->iMaxNumRefFrame,
96 kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
97 bSVCBaselayer);
98 } else {
99 iRet = WelsInitSubsetSps (pSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
100 pParam->iMaxNumRefFrame,
101 kiSpsId, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
102 }
103 return iRet;
104 }
105
CheckMatchedSps(SWelsSPS * const pSps1,SWelsSPS * const pSps2)106 static bool CheckMatchedSps (SWelsSPS* const pSps1, SWelsSPS* const pSps2) {
107
108 if ((pSps1->iMbWidth != pSps2->iMbWidth)
109 || (pSps1->iMbHeight != pSps2->iMbHeight)) {
110 return false;
111 }
112
113 if ((pSps1->uiLog2MaxFrameNum != pSps2->uiLog2MaxFrameNum)
114 || (pSps1->iLog2MaxPocLsb != pSps2->iLog2MaxPocLsb)) {
115 return false;
116 }
117
118 if (pSps1->iNumRefFrames != pSps2->iNumRefFrames) {
119 return false;
120 }
121
122 if ((pSps1->bFrameCroppingFlag != pSps2->bFrameCroppingFlag)
123 || (pSps1->sFrameCrop.iCropLeft != pSps2->sFrameCrop.iCropLeft)
124 || (pSps1->sFrameCrop.iCropRight != pSps2->sFrameCrop.iCropRight)
125 || (pSps1->sFrameCrop.iCropTop != pSps2->sFrameCrop.iCropTop)
126 || (pSps1->sFrameCrop.iCropBottom != pSps2->sFrameCrop.iCropBottom)
127 ) {
128 return false;
129 }
130
131 if ((pSps1->uiProfileIdc != pSps2->uiProfileIdc)
132 || (pSps1->bConstraintSet0Flag != pSps2->bConstraintSet0Flag)
133 || (pSps1->bConstraintSet1Flag != pSps2->bConstraintSet1Flag)
134 || (pSps1->bConstraintSet2Flag != pSps2->bConstraintSet2Flag)
135 || (pSps1->bConstraintSet3Flag != pSps2->bConstraintSet3Flag)
136 || (pSps1->iLevelIdc != pSps2->iLevelIdc)) {
137 return false;
138 }
139
140 return true;
141 }
142
CheckMatchedSubsetSps(SSubsetSps * const pSubsetSps1,SSubsetSps * const pSubsetSps2)143 static bool CheckMatchedSubsetSps (SSubsetSps* const pSubsetSps1, SSubsetSps* const pSubsetSps2) {
144 if (!CheckMatchedSps (&pSubsetSps1->pSps, &pSubsetSps2->pSps)) {
145 return false;
146 }
147
148 if ((pSubsetSps1->sSpsSvcExt.iExtendedSpatialScalability != pSubsetSps2->sSpsSvcExt.iExtendedSpatialScalability)
149 || (pSubsetSps1->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bAdaptiveTcoeffLevelPredFlag)
150 || (pSubsetSps1->sSpsSvcExt.bSeqTcoeffLevelPredFlag != pSubsetSps2->sSpsSvcExt.bSeqTcoeffLevelPredFlag)
151 || (pSubsetSps1->sSpsSvcExt.bSliceHeaderRestrictionFlag != pSubsetSps2->sSpsSvcExt.bSliceHeaderRestrictionFlag)) {
152 return false;
153 }
154
155 return true;
156 }
157
158 /*!
159 * \brief check if the current parameter can found a presenting sps
160 * \param pParam the current encoding paramter in SWelsSvcCodingParam
161 * \param kbUseSubsetSps bool
162 * \param iDlayerIndex int, the index of current D layer
163 * \param iDlayerCount int, the number of total D layer
164 * \param pSpsArray array of all the stored SPSs
165 * \param pSubsetArray array of all the stored Subset-SPSs
166 * \return 0 - successful
167 * -1 - cannot find existing SPS for current encoder parameter
168 */
FindExistingSps(SWelsSvcCodingParam * pParam,const bool kbUseSubsetSps,const int32_t iDlayerIndex,const int32_t iDlayerCount,const int32_t iSpsNumInUse,SWelsSPS * pSpsArray,SSubsetSps * pSubsetArray,bool bSVCBaseLayer)169 int32_t FindExistingSps (SWelsSvcCodingParam* pParam, const bool kbUseSubsetSps, const int32_t iDlayerIndex,
170 const int32_t iDlayerCount, const int32_t iSpsNumInUse,
171 SWelsSPS* pSpsArray,
172 SSubsetSps* pSubsetArray, bool bSVCBaseLayer) {
173 SSpatialLayerConfig* pDlayerParam = &pParam->sSpatialLayers[iDlayerIndex];
174
175 assert (iSpsNumInUse <= MAX_SPS_COUNT);
176 if (!kbUseSubsetSps) {
177 SWelsSPS sTmpSps;
178 WelsInitSps (&sTmpSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
179 pParam->iMaxNumRefFrame,
180 0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount,
181 bSVCBaseLayer);
182 for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
183 if (CheckMatchedSps (&sTmpSps, &pSpsArray[iId])) {
184 return iId;
185 }
186 }
187 } else {
188 SSubsetSps sTmpSubsetSps;
189 WelsInitSubsetSps (&sTmpSubsetSps, pDlayerParam, &pParam->sDependencyLayers[iDlayerIndex], pParam->uiIntraPeriod,
190 pParam->iMaxNumRefFrame,
191 0, pParam->bEnableFrameCroppingFlag, pParam->iRCMode != RC_OFF_MODE, iDlayerCount);
192
193 for (int32_t iId = 0; iId < iSpsNumInUse; iId++) {
194 if (CheckMatchedSubsetSps (&sTmpSubsetSps, &pSubsetArray[iId])) {
195 return iId;
196 }
197 }
198 }
199
200 return INVALID_ID;
201 }
202
CWelsParametersetIdConstant(const bool bSimulcastAVC,const int32_t kiSpatialLayerNum)203 CWelsParametersetIdConstant::CWelsParametersetIdConstant (const bool bSimulcastAVC, const int32_t kiSpatialLayerNum) {
204 memset (&m_sParaSetOffset, 0, sizeof (m_sParaSetOffset));
205
206 m_bSimulcastAVC = bSimulcastAVC;
207 m_iSpatialLayerNum = kiSpatialLayerNum;
208
209 m_iBasicNeededSpsNum = 1;
210 m_iBasicNeededPpsNum = (1 + m_iSpatialLayerNum);
211 }
212
~CWelsParametersetIdConstant()213 CWelsParametersetIdConstant::~CWelsParametersetIdConstant() {
214 }
215
GetPpsIdOffset(const int32_t iPpsId)216 int32_t CWelsParametersetIdConstant::GetPpsIdOffset (const int32_t iPpsId) {
217 return 0;
218 };
GetSpsIdOffset(const int32_t iPpsId,const int32_t iSpsId)219 int32_t CWelsParametersetIdConstant::GetSpsIdOffset (const int32_t iPpsId, const int32_t iSpsId) {
220 return 0;
221 };
222
GetSpsIdOffsetList(const int iParasetType)223 int32_t* CWelsParametersetIdConstant::GetSpsIdOffsetList (const int iParasetType) {
224 return & (m_sParaSetOffset.sParaSetOffsetVariable[iParasetType].iParaSetIdDelta[0]);
225 }
226
GetAllNeededParasetNum()227 uint32_t CWelsParametersetIdConstant::GetAllNeededParasetNum() {
228 return (GetNeededSpsNum()
229 + GetNeededSubsetSpsNum()
230 + GetNeededPpsNum());
231 }
232
GetNeededSpsNum()233 uint32_t CWelsParametersetIdConstant::GetNeededSpsNum() {
234 if (0 >= m_sParaSetOffset.uiNeededSpsNum) {
235 m_sParaSetOffset.uiNeededSpsNum = m_iBasicNeededSpsNum * ((m_bSimulcastAVC) ? (m_iSpatialLayerNum) : (1));
236 }
237 return m_sParaSetOffset.uiNeededSpsNum;
238 }
239
240
GetNeededSubsetSpsNum()241 uint32_t CWelsParametersetIdConstant::GetNeededSubsetSpsNum() {
242 if (0 >= m_sParaSetOffset.uiNeededSubsetSpsNum) {
243 m_sParaSetOffset.uiNeededSubsetSpsNum = (m_bSimulcastAVC ? 0 : (m_iSpatialLayerNum - 1));
244 }
245 return m_sParaSetOffset.uiNeededSubsetSpsNum;
246 }
247
GetNeededPpsNum()248 uint32_t CWelsParametersetIdConstant::GetNeededPpsNum() {
249 if (0 == m_sParaSetOffset.uiNeededPpsNum) {
250 m_sParaSetOffset.uiNeededPpsNum = m_iBasicNeededPpsNum * ((m_bSimulcastAVC) ? (m_iSpatialLayerNum) :
251 (1));
252 }
253 return m_sParaSetOffset.uiNeededPpsNum;
254 }
255
LoadPrevious(SExistingParasetList * pExistingParasetList,SWelsSPS * pSpsArray,SSubsetSps * pSubsetArray,SWelsPPS * pPpsArray)256 void CWelsParametersetIdConstant::LoadPrevious (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
257 SSubsetSps* pSubsetArray, SWelsPPS* pPpsArray) {
258 return;
259 }
260
Update(const uint32_t kuiId,const int iParasetType)261 void CWelsParametersetIdConstant::Update (const uint32_t kuiId, const int iParasetType) {
262 memset (&m_sParaSetOffset, 0, sizeof (SParaSetOffset));
263 }
264
GenerateNewSps(sWelsEncCtx * pCtx,const bool kbUseSubsetSps,const int32_t iDlayerIndex,const int32_t iDlayerCount,uint32_t kuiSpsId,SWelsSPS * & pSps,SSubsetSps * & pSubsetSps,bool bSVCBaselayer)265 uint32_t CWelsParametersetIdConstant::GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps,
266 const int32_t iDlayerIndex,
267 const int32_t iDlayerCount, uint32_t kuiSpsId,
268 SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSVCBaselayer) {
269 WelsGenerateNewSps (pCtx, kbUseSubsetSps, iDlayerIndex,
270 iDlayerCount, kuiSpsId,
271 pSps, pSubsetSps, bSVCBaselayer);
272 return kuiSpsId;
273 }
274
275
InitPps(sWelsEncCtx * pCtx,uint32_t kiSpsId,SWelsSPS * pSps,SSubsetSps * pSubsetSps,uint32_t kuiPpsId,const bool kbDeblockingFilterPresentFlag,const bool kbUsingSubsetSps,const bool kbEntropyCodingModeFlag)276 uint32_t CWelsParametersetIdConstant::InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
277 SWelsSPS* pSps,
278 SSubsetSps* pSubsetSps,
279 uint32_t kuiPpsId,
280 const bool kbDeblockingFilterPresentFlag,
281 const bool kbUsingSubsetSps,
282 const bool kbEntropyCodingModeFlag) {
283 WelsInitPps (& pCtx->pPPSArray[kuiPpsId], pSps, pSubsetSps, kuiPpsId, true, kbUsingSubsetSps, kbEntropyCodingModeFlag);
284 SetUseSubsetFlag (kuiPpsId, kbUsingSubsetSps);
285 return kuiPpsId;
286 }
287
SetUseSubsetFlag(const uint32_t iPpsId,const bool bUseSubsetSps)288 void CWelsParametersetIdConstant::SetUseSubsetFlag (const uint32_t iPpsId, const bool bUseSubsetSps) {
289 m_sParaSetOffset.bPpsIdMappingIntoSubsetsps[iPpsId] = bUseSubsetSps;
290 }
291
OutputCurrentStructure(SParaSetOffsetVariable * pParaSetOffsetVariable,int32_t * pPpsIdList,sWelsEncCtx * pCtx,SExistingParasetList * pExistingParasetList)292 void CWelsParametersetIdNonConstant::OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
293 int32_t* pPpsIdList, sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) {
294 for (int32_t k = 0; k < PARA_SET_TYPE; k++) {
295 memset ((m_sParaSetOffset.sParaSetOffsetVariable[k].bUsedParaSetIdInBs), 0, MAX_PPS_COUNT * sizeof (bool));
296 }
297 memcpy (pParaSetOffsetVariable, m_sParaSetOffset.sParaSetOffsetVariable,
298 (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
299 }
LoadPreviousStructure(SParaSetOffsetVariable * pParaSetOffsetVariable,int32_t * pPpsIdList)300 void CWelsParametersetIdNonConstant::LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
301 int32_t* pPpsIdList) {
302 memcpy (m_sParaSetOffset.sParaSetOffsetVariable, pParaSetOffsetVariable,
303 (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
304 }
305
306 //
307 //CWelsParametersetIdIncreasing
308 //
309
DebugSpsPps(const int32_t kiPpsId,const int32_t kiSpsId)310 void CWelsParametersetIdIncreasing::DebugSpsPps (const int32_t kiPpsId, const int32_t kiSpsId) {
311 #if _DEBUG
312 //SParaSetOffset use, 110421
313 //if ( (INCREASING_ID & eSpsPpsIdStrategy)) {
314 const int32_t kiParameterSetType = (m_sParaSetOffset.bPpsIdMappingIntoSubsetsps[kiPpsId] ?
315 PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS) ;
316
317 const int32_t kiTmpSpsIdInBs = kiSpsId +
318 m_sParaSetOffset.sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[kiSpsId];
319 const int32_t tmp_pps_id_in_bs = kiPpsId +
320 m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[kiPpsId];
321 assert (MAX_SPS_COUNT > kiTmpSpsIdInBs);
322 assert (MAX_PPS_COUNT > tmp_pps_id_in_bs);
323 assert (m_sParaSetOffset.sParaSetOffsetVariable[kiParameterSetType].bUsedParaSetIdInBs[kiTmpSpsIdInBs]);
324 //}
325 #endif
326 }
DebugPps(const int32_t kiPpsId)327 void CWelsParametersetIdIncreasing::DebugPps (const int32_t kiPpsId) {
328 #if _DEBUG
329 const int32_t kiTmpPpsIdInBs = kiPpsId +
330 m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[ kiPpsId ];
331 assert (MAX_PPS_COUNT > kiTmpPpsIdInBs);
332
333 //when activated need to sure there is avialable PPS
334 assert (m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].bUsedParaSetIdInBs[kiTmpPpsIdInBs]);
335 #endif
336 }
337
ParasetIdAdditionIdAdjust(SParaSetOffsetVariable * sParaSetOffsetVariable,const int32_t kiCurEncoderParaSetId,const uint32_t kuiMaxIdInBs)338 void ParasetIdAdditionIdAdjust (SParaSetOffsetVariable* sParaSetOffsetVariable,
339 const int32_t kiCurEncoderParaSetId,
340 const uint32_t kuiMaxIdInBs) { //paraset_type = 0: SPS; =1: PPS
341 //SPS_ID in avc_sps and pSubsetSps will be different using this
342 //SPS_ID case example:
343 //1st enter: next_spsid_in_bs == 0; spsid == 0; delta==0; //actual spsid_in_bs == 0
344 //1st finish: next_spsid_in_bs == 1;
345 //2nd enter: next_spsid_in_bs == 1; spsid == 0; delta==1; //actual spsid_in_bs == 1
346 //2nd finish: next_spsid_in_bs == 2;
347 //31st enter: next_spsid_in_bs == 31; spsid == 0~2; delta==31~29; //actual spsid_in_bs == 31
348 //31st finish:next_spsid_in_bs == 0;
349 //31st enter: next_spsid_in_bs == 0; spsid == 0~2; delta==-2~0; //actual spsid_in_bs == 0
350 //31st finish:next_spsid_in_bs == 1;
351
352 const int32_t kiEncId = kiCurEncoderParaSetId;
353 uint32_t uiNextIdInBs = sParaSetOffsetVariable->uiNextParaSetIdToUseInBs;
354
355 //update current layer's pCodingParam
356 sParaSetOffsetVariable->iParaSetIdDelta[kiEncId] = uiNextIdInBs -
357 kiEncId; //for current parameter set, change its id_delta
358 //write pso pData for next update:
359 sParaSetOffsetVariable->bUsedParaSetIdInBs[uiNextIdInBs] = true; // update current used_id
360
361 //prepare for next update:
362 // find the next avaibable iId
363 ++uiNextIdInBs;
364 if (uiNextIdInBs >= kuiMaxIdInBs) {
365 uiNextIdInBs = 0;//ensure the SPS_ID wound not exceed MAX_SPS_COUNT
366 }
367 // update next_id
368 sParaSetOffsetVariable->uiNextParaSetIdToUseInBs = uiNextIdInBs;
369 }
370
Update(const uint32_t kuiId,const int iParasetType)371 void CWelsParametersetIdIncreasing::Update (const uint32_t kuiId, const int iParasetType) {
372 #if _DEBUG
373 m_sParaSetOffset.eSpsPpsIdStrategy = INCREASING_ID;
374 assert (kuiId < MAX_DQ_LAYER_NUM);
375 #endif
376
377 ParasetIdAdditionIdAdjust (& (m_sParaSetOffset.sParaSetOffsetVariable[iParasetType]),
378 kuiId,
379 (iParasetType != PARA_SET_TYPE_PPS) ? MAX_SPS_COUNT : MAX_PPS_COUNT);
380 }
381 //((SPS_PPS_LISTING != pEncCtx->pSvcParam->eSpsPpsIdStrategy) ? (&
382 // (pEncCtx->sPSOVector.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[0])) : NULL)
383
GetPpsIdOffset(const int32_t kiPpsId)384 int32_t CWelsParametersetIdIncreasing::GetPpsIdOffset (const int32_t kiPpsId) {
385 #if _DEBUG
386 DebugPps (kiPpsId);
387 #endif
388 return (m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[kiPpsId]);
389 }
390
GetSpsIdOffset(const int32_t kiPpsId,const int32_t kiSpsId)391 int32_t CWelsParametersetIdIncreasing::GetSpsIdOffset (const int32_t kiPpsId, const int32_t kiSpsId) {
392 const int32_t kiParameterSetType = (m_sParaSetOffset.bPpsIdMappingIntoSubsetsps[kiPpsId] ?
393 PARA_SET_TYPE_SUBSETSPS : PARA_SET_TYPE_AVCSPS);
394 #if _DEBUG
395 DebugSpsPps (kiPpsId, kiSpsId);
396 #endif
397 return (m_sParaSetOffset.sParaSetOffsetVariable[kiParameterSetType].iParaSetIdDelta[kiSpsId]);
398 }
399
400 //
401 //CWelsParametersetSpsListing
402 //
403
CWelsParametersetSpsListing(const bool bSimulcastAVC,const int32_t kiSpatialLayerNum)404 CWelsParametersetSpsListing::CWelsParametersetSpsListing (const bool bSimulcastAVC,
405 const int32_t kiSpatialLayerNum) : CWelsParametersetIdNonConstant (bSimulcastAVC, kiSpatialLayerNum) {
406 memset (&m_sParaSetOffset, 0, sizeof (m_sParaSetOffset));
407
408 m_bSimulcastAVC = bSimulcastAVC;
409 m_iSpatialLayerNum = kiSpatialLayerNum;
410
411 m_iBasicNeededSpsNum = MAX_SPS_COUNT;
412 m_iBasicNeededPpsNum = 1;
413 }
414
GetNeededSubsetSpsNum()415 uint32_t CWelsParametersetSpsListing::GetNeededSubsetSpsNum() {
416 if (0 >= m_sParaSetOffset.uiNeededSubsetSpsNum) {
417 // sPSOVector.uiNeededSubsetSpsNum = ((pSvcParam->bSimulcastAVC) ? (0) :((SPS_LISTING & pSvcParam->eSpsPpsIdStrategy) ? (MAX_SPS_COUNT) : (pSvcParam->iSpatialLayerNum - 1)));
418 m_sParaSetOffset.uiNeededSubsetSpsNum = ((m_bSimulcastAVC) ? (0) :
419 (MAX_SPS_COUNT));
420 }
421 return m_sParaSetOffset.uiNeededSubsetSpsNum;
422 }
423
LoadPreviousSps(SExistingParasetList * pExistingParasetList,SWelsSPS * pSpsArray,SSubsetSps * pSubsetArray)424 void CWelsParametersetSpsListing::LoadPreviousSps (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
425 SSubsetSps* pSubsetArray) {
426 //if ((SPS_LISTING & pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
427 m_sParaSetOffset.uiInUseSpsNum = pExistingParasetList->uiInUseSpsNum;
428 memcpy (pSpsArray, pExistingParasetList->sSps, MAX_SPS_COUNT * sizeof (SWelsSPS));
429
430 if (GetNeededSubsetSpsNum() > 0) {
431 m_sParaSetOffset.uiInUseSubsetSpsNum = pExistingParasetList->uiInUseSubsetSpsNum;
432 memcpy (pSubsetArray, pExistingParasetList->sSubsetSps, MAX_SPS_COUNT * sizeof (SSubsetSps));
433 } else {
434 m_sParaSetOffset.uiInUseSubsetSpsNum = 0;
435 }
436 //}
437
438 }
LoadPrevious(SExistingParasetList * pExistingParasetList,SWelsSPS * pSpsArray,SSubsetSps * pSubsetArray,SWelsPPS * pPpsArray)439 void CWelsParametersetSpsListing::LoadPrevious (SExistingParasetList* pExistingParasetList, SWelsSPS* pSpsArray,
440 SSubsetSps* pSubsetArray, SWelsPPS* pPpsArray) {
441 if (NULL == pExistingParasetList) {
442 return;
443 }
444 LoadPreviousSps (pExistingParasetList, pSpsArray, pSubsetArray);
445 LoadPreviousPps (pExistingParasetList, pPpsArray);
446 }
447
CheckParamCompatibility(SWelsSvcCodingParam * pCodingParam,SLogContext * pLogCtx)448 bool CWelsParametersetSpsListing::CheckParamCompatibility (SWelsSvcCodingParam* pCodingParam, SLogContext* pLogCtx) {
449 if (pCodingParam->iSpatialLayerNum > 1 && (!pCodingParam->bSimulcastAVC)) {
450 WelsLog (pLogCtx, WELS_LOG_WARNING,
451 "ParamValidationExt(), eSpsPpsIdStrategy setting (%d) with multiple svc SpatialLayers (%d) not supported! eSpsPpsIdStrategy adjusted to CONSTANT_ID",
452 pCodingParam->eSpsPpsIdStrategy, pCodingParam->iSpatialLayerNum);
453 pCodingParam->eSpsPpsIdStrategy = CONSTANT_ID;
454 return false;
455 }
456 return true;
457 }
458
CheckPpsGenerating()459 bool CWelsParametersetSpsListing::CheckPpsGenerating() {
460 return true;
461 }
SpsReset(sWelsEncCtx * pCtx,bool kbUseSubsetSps)462 int32_t CWelsParametersetSpsListing::SpsReset (sWelsEncCtx* pCtx, bool kbUseSubsetSps) {
463
464 // reset current list
465 if (!kbUseSubsetSps) {
466 m_sParaSetOffset.uiInUseSpsNum = 1;
467 memset (pCtx->pSpsArray, 0, MAX_SPS_COUNT * sizeof (SWelsSPS));
468 } else {
469 m_sParaSetOffset.uiInUseSubsetSpsNum = 1;
470 memset (pCtx->pSubsetArray, 0, MAX_SPS_COUNT * sizeof (SSubsetSps));
471 }
472
473 //iSpsId = 0;
474 return 0;
475 }
GenerateNewSps(sWelsEncCtx * pCtx,const bool kbUseSubsetSps,const int32_t iDlayerIndex,const int32_t iDlayerCount,uint32_t kuiSpsId,SWelsSPS * & pSps,SSubsetSps * & pSubsetSps,bool bSvcBaselayer)476 uint32_t CWelsParametersetSpsListing::GenerateNewSps (sWelsEncCtx* pCtx, const bool kbUseSubsetSps,
477 const int32_t iDlayerIndex,
478 const int32_t iDlayerCount, uint32_t kuiSpsId,
479 SWelsSPS*& pSps, SSubsetSps*& pSubsetSps, bool bSvcBaselayer) {
480 //check if the current param can fit in an existing SPS
481 const int32_t kiFoundSpsId = FindExistingSps (pCtx->pSvcParam, kbUseSubsetSps, iDlayerIndex, iDlayerCount,
482 kbUseSubsetSps ? (m_sParaSetOffset.uiInUseSubsetSpsNum) : (m_sParaSetOffset.uiInUseSpsNum),
483 pCtx->pSpsArray,
484 pCtx->pSubsetArray, bSvcBaselayer);
485
486
487 if (INVALID_ID != kiFoundSpsId) {
488 //if yes, set pSps or pSubsetSps to it
489 kuiSpsId = kiFoundSpsId;
490 if (!kbUseSubsetSps) {
491 pSps = & (pCtx->pSpsArray[kiFoundSpsId]);
492 } else {
493 pSubsetSps = & (pCtx->pSubsetArray[kiFoundSpsId]);
494 }
495 } else {
496 //if no, generate a new SPS as usual
497 if (!CheckPpsGenerating()) {
498 return -1;
499 }
500
501 kuiSpsId = (!kbUseSubsetSps) ? (m_sParaSetOffset.uiInUseSpsNum++) : (m_sParaSetOffset.uiInUseSubsetSpsNum++);
502 if (kuiSpsId >= MAX_SPS_COUNT) {
503 if (SpsReset (pCtx, kbUseSubsetSps) < 0) {
504 return -1;
505 }
506 kuiSpsId = 0;
507 }
508
509 WelsGenerateNewSps (pCtx, kbUseSubsetSps, iDlayerIndex,
510 iDlayerCount, kuiSpsId, pSps, pSubsetSps, bSvcBaselayer);
511 }
512 return kuiSpsId;
513 }
514
UpdateParaSetNum(sWelsEncCtx * pCtx)515 void CWelsParametersetSpsListing::UpdateParaSetNum (sWelsEncCtx* pCtx) {
516 pCtx->iSpsNum = m_sParaSetOffset.uiInUseSpsNum;
517 pCtx->iSubsetSpsNum = m_sParaSetOffset.uiInUseSubsetSpsNum;
518 };
519
OutputCurrentStructure(SParaSetOffsetVariable * pParaSetOffsetVariable,int32_t * pPpsIdList,sWelsEncCtx * pCtx,SExistingParasetList * pExistingParasetList)520 void CWelsParametersetSpsListing::OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
521 int32_t* pPpsIdList, sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) {
522 CWelsParametersetIdNonConstant::OutputCurrentStructure (pParaSetOffsetVariable, pPpsIdList, pCtx, pExistingParasetList);
523 pExistingParasetList->uiInUseSpsNum = m_sParaSetOffset.uiInUseSpsNum;
524
525 memcpy (pExistingParasetList->sSps, pCtx->pSpsArray, MAX_SPS_COUNT * sizeof (SWelsSPS));
526 if (NULL != pCtx->pSubsetArray) {
527 pExistingParasetList->uiInUseSubsetSpsNum = m_sParaSetOffset.uiInUseSubsetSpsNum;
528 memcpy (pExistingParasetList->sSubsetSps, pCtx->pSubsetArray, MAX_SPS_COUNT * sizeof (SSubsetSps));
529 } else {
530 pExistingParasetList->uiInUseSubsetSpsNum = 0;
531 }
532 }
533
534 //
535 //CWelsParametersetSpsPpsListing
536 //
537
CWelsParametersetSpsPpsListing(const bool bSimulcastAVC,const int32_t kiSpatialLayerNum)538 CWelsParametersetSpsPpsListing::CWelsParametersetSpsPpsListing (const bool bSimulcastAVC,
539 const int32_t kiSpatialLayerNum): CWelsParametersetSpsListing (bSimulcastAVC, kiSpatialLayerNum) {
540 memset (&m_sParaSetOffset, 0, sizeof (m_sParaSetOffset));
541
542 m_bSimulcastAVC = bSimulcastAVC;
543 m_iSpatialLayerNum = kiSpatialLayerNum;
544
545 m_iBasicNeededSpsNum = MAX_SPS_COUNT;
546 m_iBasicNeededPpsNum = MAX_PPS_COUNT;
547 }
548
LoadPreviousPps(SExistingParasetList * pExistingParasetList,SWelsPPS * pPpsArray)549 void CWelsParametersetSpsPpsListing::LoadPreviousPps (SExistingParasetList* pExistingParasetList, SWelsPPS* pPpsArray) {
550 // copy from existing if the pointer exists
551 //if ((SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) && (NULL != pExistingParasetList)) {
552 m_sParaSetOffset.uiInUsePpsNum = pExistingParasetList->uiInUsePpsNum;
553 memcpy (pPpsArray, pExistingParasetList->sPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
554 //}
555 }
556
557 /* if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (pCtx->iPpsNum < MAX_PPS_COUNT)) {
558 UpdatePpsList (pCtx);
559 }*/
UpdatePpsList(sWelsEncCtx * pCtx)560 void CWelsParametersetSpsPpsListing::UpdatePpsList (sWelsEncCtx* pCtx) {
561 if (pCtx->iPpsNum >= MAX_PPS_COUNT) {
562 return;
563 }
564 assert (pCtx->iPpsNum <= MAX_DQ_LAYER_NUM);
565
566 //Generate PPS LIST
567 int32_t iPpsId = 0, iUsePpsNum = pCtx->iPpsNum;
568
569 for (int32_t iIdrRound = 0; iIdrRound < MAX_PPS_COUNT; iIdrRound++) {
570 for (iPpsId = 0; iPpsId < pCtx->iPpsNum; iPpsId++) {
571 m_sParaSetOffset.iPpsIdList[iPpsId][iIdrRound] = ((iIdrRound * iUsePpsNum + iPpsId) % MAX_PPS_COUNT);
572 }
573 }
574
575 for (iPpsId = iUsePpsNum; iPpsId < MAX_PPS_COUNT; iPpsId++) {
576 memcpy (& (pCtx->pPPSArray[iPpsId]), & (pCtx->pPPSArray[iPpsId % iUsePpsNum]), sizeof (SWelsPPS));
577 pCtx->pPPSArray[iPpsId].iPpsId = iPpsId;
578 pCtx->iPpsNum++;
579 }
580
581 assert (pCtx->iPpsNum == MAX_PPS_COUNT);
582 m_sParaSetOffset.uiInUsePpsNum = pCtx->iPpsNum;
583 }
584
585
CheckPpsGenerating()586 bool CWelsParametersetSpsPpsListing::CheckPpsGenerating() {
587 /*if ((SPS_PPS_LISTING == pCtx->pSvcParam->eSpsPpsIdStrategy) && (MAX_PPS_COUNT <= pCtx->sPSOVector.uiInUsePpsNum)) {
588 //check if we can generate new SPS or not
589 WelsLog (& pCtx->sLogCtx, WELS_LOG_ERROR,
590 "InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
591 return ENC_RETURN_UNSUPPORTED_PARA;
592 }*/
593 if (MAX_PPS_COUNT <= m_sParaSetOffset.uiInUsePpsNum) {
594 return false;
595 }
596
597 return true;
598 }
SpsReset(sWelsEncCtx * pCtx,bool kbUseSubsetSps)599 int32_t CWelsParametersetSpsPpsListing::SpsReset (sWelsEncCtx* pCtx, bool kbUseSubsetSps) {
600 /* if (SPS_PPS_LISTING == pParam->eSpsPpsIdStrategy) {
601 WelsLog (& (*ppCtx)->sLogCtx, WELS_LOG_ERROR,
602 "InitDqLayers(), cannot generate new SPS under the SPS_PPS_LISTING mode!");
603 return ENC_RETURN_UNSUPPORTED_PARA;
604 }*/
605 return -1;
606 }
607
FindExistingPps(SWelsSPS * pSps,SSubsetSps * pSubsetSps,const bool kbUseSubsetSps,const int32_t iSpsId,const bool kbEntropyCodingFlag,const int32_t iPpsNumInUse,SWelsPPS * pPpsArray)608 int32_t FindExistingPps (SWelsSPS* pSps, SSubsetSps* pSubsetSps, const bool kbUseSubsetSps, const int32_t iSpsId,
609 const bool kbEntropyCodingFlag, const int32_t iPpsNumInUse,
610 SWelsPPS* pPpsArray) {
611 #if !defined(DISABLE_FMO_FEATURE)
612 // feature not supported yet
613 return INVALID_ID;
614 #endif//!DISABLE_FMO_FEATURE
615
616 SWelsPPS sTmpPps;
617 WelsInitPps (&sTmpPps,
618 pSps,
619 pSubsetSps,
620 0,
621 true,
622 kbUseSubsetSps,
623 kbEntropyCodingFlag);
624
625 assert (iPpsNumInUse <= MAX_PPS_COUNT);
626 for (int32_t iId = 0; iId < iPpsNumInUse; iId++) {
627 if ((sTmpPps.iSpsId == pPpsArray[iId].iSpsId)
628 && (sTmpPps.bEntropyCodingModeFlag == pPpsArray[iId].bEntropyCodingModeFlag)
629 && (sTmpPps.iPicInitQp == pPpsArray[iId].iPicInitQp)
630 && (sTmpPps.iPicInitQs == pPpsArray[iId].iPicInitQs)
631 && (sTmpPps.uiChromaQpIndexOffset == pPpsArray[iId].uiChromaQpIndexOffset)
632 && (sTmpPps.bDeblockingFilterControlPresentFlag == pPpsArray[iId].bDeblockingFilterControlPresentFlag)
633 ) {
634 return iId;
635 }
636 }
637
638 return INVALID_ID;
639 }
640
InitPps(sWelsEncCtx * pCtx,uint32_t kiSpsId,SWelsSPS * pSps,SSubsetSps * pSubsetSps,uint32_t kuiPpsId,const bool kbDeblockingFilterPresentFlag,const bool kbUsingSubsetSps,const bool kbEntropyCodingModeFlag)641 uint32_t CWelsParametersetSpsPpsListing::InitPps (sWelsEncCtx* pCtx, uint32_t kiSpsId,
642 SWelsSPS* pSps,
643 SSubsetSps* pSubsetSps,
644 uint32_t kuiPpsId,
645 const bool kbDeblockingFilterPresentFlag,
646 const bool kbUsingSubsetSps,
647 const bool kbEntropyCodingModeFlag) {
648 const int32_t kiFoundPpsId = FindExistingPps (pSps, pSubsetSps, kbUsingSubsetSps, kiSpsId,
649 kbEntropyCodingModeFlag,
650 m_sParaSetOffset.uiInUsePpsNum,
651 pCtx->pPPSArray);
652
653
654 if (INVALID_ID != kiFoundPpsId) {
655 //if yes, set pPps to it
656 kuiPpsId = kiFoundPpsId;
657 } else {
658 kuiPpsId = (m_sParaSetOffset.uiInUsePpsNum++);
659 WelsInitPps (& pCtx->pPPSArray[kuiPpsId], pSps, pSubsetSps, kuiPpsId, true, kbUsingSubsetSps, kbEntropyCodingModeFlag);
660 }
661 SetUseSubsetFlag (kuiPpsId, kbUsingSubsetSps);
662 return kuiPpsId;
663 }
664
UpdateParaSetNum(sWelsEncCtx * pCtx)665 void CWelsParametersetSpsPpsListing::UpdateParaSetNum (sWelsEncCtx* pCtx) {
666 CWelsParametersetSpsListing::UpdateParaSetNum (pCtx);
667
668 //UpdatePpsList (pCtx);
669 pCtx->iPpsNum = m_sParaSetOffset.uiInUsePpsNum;
670 }
671
GetCurrentPpsId(const int32_t iPpsId,const int32_t iIdrLoop)672 int32_t CWelsParametersetSpsPpsListing::GetCurrentPpsId (const int32_t iPpsId, const int32_t iIdrLoop) {
673 return m_sParaSetOffset.iPpsIdList[iPpsId][iIdrLoop];
674 }
675
LoadPreviousStructure(SParaSetOffsetVariable * pParaSetOffsetVariable,int32_t * pPpsIdList)676 void CWelsParametersetSpsPpsListing::LoadPreviousStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
677 int32_t* pPpsIdList) {
678 memcpy (m_sParaSetOffset.sParaSetOffsetVariable, pParaSetOffsetVariable,
679 (PARA_SET_TYPE)*sizeof (SParaSetOffsetVariable)); // confirmed_safe_unsafe_usage
680
681 memcpy ((m_sParaSetOffset.iPpsIdList), pPpsIdList, MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
682
683 }
684
OutputCurrentStructure(SParaSetOffsetVariable * pParaSetOffsetVariable,int32_t * pPpsIdList,sWelsEncCtx * pCtx,SExistingParasetList * pExistingParasetList)685 void CWelsParametersetSpsPpsListing::OutputCurrentStructure (SParaSetOffsetVariable* pParaSetOffsetVariable,
686 int32_t* pPpsIdList, sWelsEncCtx* pCtx, SExistingParasetList* pExistingParasetList) {
687 CWelsParametersetSpsListing::OutputCurrentStructure (pParaSetOffsetVariable, pPpsIdList, pCtx, pExistingParasetList);
688
689 pExistingParasetList->uiInUsePpsNum = m_sParaSetOffset.uiInUsePpsNum;
690 memcpy (pExistingParasetList->sPps, pCtx->pPps, MAX_PPS_COUNT * sizeof (SWelsPPS));
691 memcpy (pPpsIdList, (m_sParaSetOffset.iPpsIdList), MAX_DQ_LAYER_NUM * MAX_PPS_COUNT * sizeof (int32_t));
692 }
693
694 //
695 //CWelsParametersetSpsListingPpsIncreasing
696 //
697
GetPpsIdOffset(const int32_t kiPpsId)698 int32_t CWelsParametersetSpsListingPpsIncreasing::GetPpsIdOffset (const int32_t kiPpsId) {
699 //same as CWelsParametersetIdIncreasing::GetPpsIdOffset
700 return (m_sParaSetOffset.sParaSetOffsetVariable[PARA_SET_TYPE_PPS].iParaSetIdDelta[kiPpsId]);
701 }
702
Update(const uint32_t kuiId,const int iParasetType)703 void CWelsParametersetSpsListingPpsIncreasing::Update (const uint32_t kuiId, const int iParasetType) {
704 //same as CWelsParametersetIdIncreasing::Update
705 #if _DEBUG
706 assert (kuiId < MAX_DQ_LAYER_NUM);
707 #endif
708
709 ParasetIdAdditionIdAdjust (& (m_sParaSetOffset.sParaSetOffsetVariable[iParasetType]),
710 kuiId,
711 (iParasetType != PARA_SET_TYPE_PPS) ? MAX_SPS_COUNT : MAX_PPS_COUNT);
712 }
713 }
714