1 /*
2 * Copyright (c) 2021-2023, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     decode_vvc_basic_feature.cpp
24 //! \brief    Defines the common interface for decode vvc parameter
25 //!
26 
27 #include "decode_vvc_basic_feature.h"
28 #include "decode_utils.h"
29 #include "decode_allocator.h"
30 
31 namespace decode
32 {
~VvcBasicFeature()33     VvcBasicFeature::~VvcBasicFeature() { }
34 
Init(void * setting)35     MOS_STATUS VvcBasicFeature::Init(void *setting)
36     {
37         DECODE_FUNC_CALL();
38 
39         PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL);
40 
41         DECODE_CHK_NULL(setting);
42 
43         DECODE_CHK_STATUS(DecodeBasicFeature::Init(setting));
44         CodechalSetting *codecSettings = (CodechalSetting*)setting;
45         m_shortFormatInUse = codecSettings->shortFormatInUse;
46 
47         DECODE_CHK_STATUS(m_refFrames.Init(this, *m_allocator));
48         DECODE_CHK_STATUS(m_mvBuffers.Init(m_hwInterface, *m_allocator, *this,
49                                        vvcNumInitialMvBuffers));
50 
51         return MOS_STATUS_SUCCESS;
52     }
53 
UpdateAPS(void * params)54     MOS_STATUS VvcBasicFeature::UpdateAPS(void *params)
55     {
56         DECODE_FUNC_CALL();
57 
58         PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL);
59 
60         DECODE_CHK_NULL(params);
61 
62         CodechalDecodeParams* decodeParams = (CodechalDecodeParams*)params;
63 
64         // ALF APS
65         if (m_vvcPicParams->m_numAlfBuffers > 0 && decodeParams->m_deblockData != nullptr)
66         {
67             uint32_t actualBufNum = decodeParams->m_deblockDataSize / sizeof(CodecVvcAlfData);
68             if (m_vvcPicParams->m_numAlfBuffers > actualBufNum)
69             {
70                 DECODE_ASSERTMESSAGE("Received ALF buffer size < claimed buffer size in pic params buffer.\n");
71                 return MOS_STATUS_INVALID_PARAMETER;
72             }
73 
74             CodecVvcAlfData* alfData = (CodecVvcAlfData*)decodeParams->m_deblockData;
75             for (uint32_t i = 0; i < actualBufNum; i++)
76             {
77                 if (alfData->m_apsAdaptationParameterSetId >= vvcMaxAlfNum)
78                 {
79                     DECODE_ASSERTMESSAGE("ALF: Invalid APS set ID from App.\n");
80                     return MOS_STATUS_INVALID_PARAMETER;
81                 }
82 
83                 m_concealAlfMask &= ~(1 << alfData->m_apsAdaptationParameterSetId);
84                 if (MOS_STATUS_INVALID_PARAMETER == CheckAlfRange(alfData))
85                 {
86                     m_concealAlfMask |= (1 << alfData->m_apsAdaptationParameterSetId);
87                 }
88 
89                 MOS_SecureMemcpy(&m_alfApsArray[alfData->m_apsAdaptationParameterSetId], sizeof(CodecVvcAlfData), alfData, sizeof(CodecVvcAlfData));
90                 m_activeAlfMask |= (1 << alfData->m_apsAdaptationParameterSetId);
91 
92                 alfData++;
93             }
94 
95             //calc accumulated valid ALF number
96             m_numAlf = 0;
97             uint8_t alfFlag = m_activeAlfMask;
98             for (auto i = 0; i < vvcMaxAlfNum; i++)
99             {
100                 m_numAlf += (alfFlag >> i) & 0x1;
101             }
102         }
103         else if(m_vvcPicParams->m_numAlfBuffers > 0 && decodeParams->m_deblockData == nullptr)
104         {
105             DECODE_ASSERTMESSAGE("Inconsistent between pic params ALF num and actual ALF buffer\n");
106             return MOS_STATUS_INVALID_PARAMETER;
107         }
108 
109         // decide ALF error concealment
110         if(m_concealAlfMask)
111         {
112             DECODE_ASSERTMESSAGE("Error concealed: Disable ALF since out-of-range ALF parameters detected.\n");
113             m_vvcPicParams->m_spsFlags0.m_fields.m_spsAlfEnabledFlag    = 0;
114             m_vvcPicParams->m_spsFlags0.m_fields.m_spsCcalfEnabledFlag  = 0;
115             m_vvcPicParams->m_ppsFlags.m_fields.m_ppsAlfInfoInPhFlag    = 1;
116             m_vvcPicParams->m_phFlags.m_fields.m_phAlfEnabledFlag       = 0;
117             m_vvcPicParams->m_phFlags.m_fields.m_phAlfCbEnabledFlag     = 0;
118             m_vvcPicParams->m_phFlags.m_fields.m_phAlfCrEnabledFlag     = 0;
119             m_vvcPicParams->m_phFlags.m_fields.m_phAlfCcCbEnabledFlag   = 0;
120             m_vvcPicParams->m_phFlags.m_fields.m_phAlfCcCrEnabledFlag   = 0;
121         }
122 
123         // LMCS APS
124         if (m_vvcPicParams->m_numLmcsBuffers > 0 && decodeParams->m_macroblockParams != nullptr)
125         {
126             if (m_vvcPicParams->m_numLmcsBuffers > decodeParams->m_numMacroblocks)
127             {
128                 DECODE_ASSERTMESSAGE("Received LMCS buffer size < claimed buffer size in pic params buffer.\n");
129                 return MOS_STATUS_INVALID_PARAMETER;
130             }
131 
132             CodecVvcLmcsData *lmcsData = (CodecVvcLmcsData*)decodeParams->m_macroblockParams;
133             for (uint32_t i = 0; i < decodeParams->m_numMacroblocks; i++)
134             {
135                 if (lmcsData->m_apsAdaptationParameterSetId >= vvcMaxLmcsNum)
136                 {
137                     DECODE_ASSERTMESSAGE("LMCS: Invalid APS set ID from App.\n");
138                     return MOS_STATUS_INVALID_PARAMETER;
139                 }
140                 MOS_SecureMemcpy(&m_lmcsApsArray[lmcsData->m_apsAdaptationParameterSetId], sizeof(CodecVvcLmcsData), lmcsData, sizeof(CodecVvcLmcsData));
141                 m_activeLmcsMask |= (1 << lmcsData->m_apsAdaptationParameterSetId);
142                 m_lmcsReshaperReady &= ~(1 << lmcsData->m_apsAdaptationParameterSetId);//reset the flag to indicate reshape info not derived yet
143 
144                 lmcsData++;
145             }
146 
147             //calc accumulated valid LMCS number
148             m_numLmcs = 0;
149             uint8_t lmcsMask = m_activeLmcsMask;
150             for (auto i = 0; i < vvcMaxLmcsNum; i++)
151             {
152                 m_numLmcs += (lmcsMask >> i) & 0x1;
153             }
154         }
155         else if(m_vvcPicParams->m_numLmcsBuffers > 0 && decodeParams->m_macroblockParams == nullptr)
156         {
157             DECODE_ASSERTMESSAGE("Inconsistent between pic params LMCS num and actual LMCS buffer\n");
158             return MOS_STATUS_INVALID_PARAMETER;
159         }
160 
161         // Scaling List APS
162         if (m_vvcPicParams->m_numScalingMatrixBuffers > 0 && decodeParams->m_iqMatrixBuffer != nullptr)
163         {
164             uint32_t actualBufNum = decodeParams->m_iqMatrixSize / sizeof(CodecVvcQmData);
165             if (m_vvcPicParams->m_numScalingMatrixBuffers > actualBufNum)
166             {
167                 DECODE_ASSERTMESSAGE("Received Scaling List APS buffer size < claimed buffer size in pic params buffer.\n");
168                 return MOS_STATUS_INVALID_PARAMETER;
169             }
170 
171             CodecVvcQmData* scalingListData = (CodecVvcQmData*)decodeParams->m_iqMatrixBuffer;
172             for (uint32_t i = 0; i < actualBufNum; i++)
173             {
174                 if (scalingListData->m_apsAdaptationParameterSetId >= vvcMaxScalingMatrixNum)
175                 {
176                     DECODE_ASSERTMESSAGE("Scaling List: Invalid APS set ID from App.\n");
177                     return MOS_STATUS_INVALID_PARAMETER;
178                 }
179                 MOS_SecureMemcpy(&m_scalingListArray[scalingListData->m_apsAdaptationParameterSetId], sizeof(CodecVvcQmData), scalingListData, sizeof(CodecVvcQmData));
180                 m_activeScalingListMask |= (1 << scalingListData->m_apsAdaptationParameterSetId);
181 
182                 scalingListData++;
183             }
184 
185             //calc accumulated valid scaling list number
186             m_numScalingList = 0;
187             uint8_t scalingListMask = m_activeScalingListMask;
188             for (auto i = 0; i < vvcMaxScalingMatrixNum; i++)
189             {
190                 m_numScalingList += (scalingListMask >> i) & 0x1;
191             }
192         }
193         else if(m_vvcPicParams->m_numScalingMatrixBuffers > 0 && decodeParams->m_iqMatrixBuffer == nullptr)
194         {
195             DECODE_ASSERTMESSAGE("Scaling List APS: Inconsistent between pic params Scaling List num and actual Scaling List buffer\n");
196             return MOS_STATUS_INVALID_PARAMETER;
197         }
198 
199         return MOS_STATUS_SUCCESS;
200     }
201 
Update(void * params)202     MOS_STATUS VvcBasicFeature::Update(void *params)
203     {
204         DECODE_FUNC_CALL();
205 
206         PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL);
207 
208         DECODE_CHK_NULL(params);
209 
210         DECODE_CHK_STATUS(DecodeBasicFeature::Update(params));
211 
212         CodechalDecodeParams* decodeParams = (CodechalDecodeParams*)params;
213         m_dataSize = decodeParams->m_dataSize;
214         m_vvcPicParams  = static_cast<CodecVvcPicParams*>(decodeParams->m_picParams);
215         DECODE_CHK_NULL(m_vvcPicParams);
216         m_vvcSliceParams  = static_cast<CodecVvcSliceParams*>(decodeParams->m_sliceParams);
217         DECODE_CHK_NULL(m_vvcSliceParams);
218         m_curSlice = 0;
219 
220         DECODE_CHK_STATUS(SetPictureStructs(decodeParams));
221 
222         // APS update
223         DECODE_CHK_STATUS(UpdateAPS(params));
224 
225         // Partition & RPL update
226         m_subPicParams      = static_cast<CodecVvcSubpicParam*>(decodeParams->m_extPicParams);
227         if (m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag && m_vvcPicParams->m_spsNumSubpicsMinus1 > 0)
228         {
229             DECODE_CHK_NULL(m_subPicParams);
230         }
231         m_sliceStructParams = static_cast<CodecVvcSliceStructure*>(decodeParams->m_extSliceParams);
232         if (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRectSliceFlag && m_vvcPicParams->m_numSliceStructsMinus1 > 0)
233         {
234             DECODE_CHK_NULL(m_sliceStructParams);
235         }
236         m_rplParams         = static_cast<CodecVvcRplStructure*>(decodeParams->m_refParams);
237         m_tileParams        = static_cast<CodecVvcTileParam*>(decodeParams->m_tileParams);
238 
239         if (m_shortFormatInUse)
240         {
241             DECODE_CHK_STATUS(UpdateNumRefForList());
242         }
243 
244         DECODE_CHK_STATUS(ReconstructPartition(decodeParams));
245 
246         // Error detection and concealment
247         DECODE_CHK_STATUS(ErrorDetectAndConceal());
248 
249         return MOS_STATUS_SUCCESS;
250     }
251 
CheckAlfRange(CodecVvcAlfData * alfData)252     MOS_STATUS VvcBasicFeature::CheckAlfRange(CodecVvcAlfData* alfData)
253     {
254         DECODE_FUNC_CALL()
255 
256         DECODE_CHK_NULL(alfData);
257         MOS_STATUS res = MOS_STATUS_SUCCESS;
258 
259         // Luma
260         if (alfData->m_alfFlags.m_fields.m_alfLumaFilterSignalFlag)
261         {
262             CHECK_RANGE(alfData->m_alfLumaNumFiltersSignalledMinus1, 0, 24);
263             for (auto i = 0; i < 25; i++)
264             {
265                 CHECK_RANGE(alfData->m_alfLumaCoeffDeltaIdx[i], 0, 24);
266             }
267             for (auto i = 0; i <= alfData->m_alfLumaNumFiltersSignalledMinus1; i++)
268             {
269                 for (auto j = 0; j < 12; j++)
270                 {
271                     CHECK_RANGE(alfData->m_alfLumaClipIdx[i][j], 0, 3);
272                 }
273             }
274         }
275 
276         // Chroma
277         if (alfData->m_alfFlags.m_fields.m_alfChromaFilterSignalFlag)
278         {
279             CHECK_RANGE(alfData->m_alfChromaNumAltFiltersMinus1, 0, 7);
280             for (auto i = 0; i <= alfData->m_alfChromaNumAltFiltersMinus1; i++)
281             {
282                 for (auto j = 0; j < 6; j++)
283                 {
284                     CHECK_RANGE(alfData->m_alfChromaClipIdx[i][j], 0, 3);
285                 }
286             }
287         }
288 
289         // CC Cb
290         if (alfData->m_alfFlags.m_fields.m_alfCcCbFilterSignalFlag)
291         {
292             CHECK_RANGE(alfData->m_alfCcCbFiltersSignalledMinus1, 0, 3);
293             for (auto i = 0; i <= alfData->m_alfCcCbFiltersSignalledMinus1; i++)
294             {
295                 for (auto j = 0; j < 7; j++)
296                 {
297                     CHECK_RANGE(alfData->m_ccAlfApsCoeffCb[i][j], -64, 64);
298                 }
299             }
300         }
301 
302         // CC Cr
303         if (alfData->m_alfFlags.m_fields.m_alfCcCrFilterSignalFlag)
304         {
305             CHECK_RANGE(alfData->m_alfCcCrFiltersSignalledMinus1, 0, 3);
306             for (auto i = 0; i <= alfData->m_alfCcCrFiltersSignalledMinus1; i++)
307             {
308                 for (auto j = 0; j < 7; j++)
309                 {
310                     CHECK_RANGE(alfData->m_ccAlfApsCoeffCr[i][j], -64, 64);
311                 }
312             }
313         }
314 
315         return res;
316     }
317 
SliceErrorHandlingLF()318     MOS_STATUS VvcBasicFeature::SliceErrorHandlingLF()
319     {
320         DECODE_FUNC_CALL()
321         DECODE_CHK_NULL(m_vvcPicParams);
322         DECODE_CHK_NULL(m_vvcSliceParams);
323 
324         m_sliceIdxInOrder.clear();
325         if (!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRectSliceFlag)
326         {
327             m_sliceIdxInOrder.push_back(0);
328             for (uint16_t i = 1; i < m_numSlices; i++)
329             {
330                 CodecVvcSliceParams temp = m_vvcSliceParams[i];
331                 uint16_t startTile = temp.m_shSliceAddress;
332                 int16_t j = i - 1;
333                 for (; (j >= 0) && (m_vvcSliceParams[m_sliceIdxInOrder[j]].m_shSliceAddress > startTile); j--) {}
334 
335                 if (j == -1)
336                 {
337                     m_sliceIdxInOrder.insert(m_sliceIdxInOrder.begin(), i);
338                 }
339                 else if (m_vvcSliceParams[m_sliceIdxInOrder[j]].m_shSliceAddress == startTile) // duplicated slices detected, keep the one with bigger bitstream size
340                 {
341                     if (m_vvcSliceParams[m_sliceIdxInOrder[j]].m_sliceBytesInBuffer - m_vvcSliceParams[m_sliceIdxInOrder[j]].m_byteOffsetToSliceData < temp.m_sliceBytesInBuffer - temp.m_byteOffsetToSliceData)
342                     {
343                         m_sliceIdxInOrder[j] = i;
344                     }
345                 }
346                 else
347                 {
348                     m_sliceIdxInOrder.insert(m_sliceIdxInOrder.begin() + j + 1, i);
349                 }
350             }
351         }
352         else
353         {
354             for (uint16_t i = 0; i < m_numSlices; i++)
355             {
356                 uint16_t subPicIdx = GetSubPicIdxFromSubPicId(m_vvcSliceParams[i].m_shSubpicId);
357                 uint16_t sliceIdx = 0;
358 
359                 if(m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag && m_vvcPicParams->m_spsNumSubpicsMinus1 > 0)
360                 {
361                     sliceIdx = m_subPicParams[subPicIdx].m_sliceIdx[m_vvcSliceParams[i].m_shSliceAddress];
362                 }
363                 else
364                 {
365                     DECODE_CHK_COND(subPicIdx != 0, "Error detected: incorrect subpic index\n");
366                     sliceIdx = m_vvcSliceParams[i].m_shSliceAddress;
367                 }
368 
369                 if (!m_sliceDesc[sliceIdx].m_sliceAvailableFlag)
370                 {
371                     m_sliceDesc[sliceIdx].m_sliceAvailableFlag = true;
372                     m_sliceDesc[sliceIdx].m_sliceCtrlIdx = i;
373                 }
374                 else if(m_vvcSliceParams[m_sliceDesc[sliceIdx].m_sliceCtrlIdx].m_sliceBytesInBuffer - m_vvcSliceParams[m_sliceDesc[sliceIdx].m_sliceCtrlIdx].m_byteOffsetToSliceData < m_vvcSliceParams[i].m_sliceBytesInBuffer - m_vvcSliceParams[i].m_byteOffsetToSliceData)
375                 {
376                     m_sliceDesc[sliceIdx].m_sliceCtrlIdx = i;
377                 }
378             }
379 
380             uint16_t numSliceDesc = (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSingleSlicePerSubpicFlag) ?
381                                     ((m_vvcPicParams->m_spsNumSubpicsMinus1 == 0 || !m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag) ? 1 : (m_vvcPicParams->m_spsNumSubpicsMinus1 + 1)) : (m_vvcPicParams->m_ppsNumSlicesInPicMinus1 + 1);
382             for (auto i = 0; i < numSliceDesc; i++)
383             {
384                 if (m_sliceDesc[i].m_sliceAvailableFlag)
385                 {
386                     m_sliceIdxInOrder.push_back(m_sliceDesc[i].m_sliceCtrlIdx);
387                 }
388             }
389         }
390 
391         //Override with valid slice number
392         m_numSlices = m_sliceIdxInOrder.size();
393 
394         return MOS_STATUS_SUCCESS;
395     }
396 
CheckProfileCaps()397     MOS_STATUS VvcBasicFeature::CheckProfileCaps()
398     {
399         DECODE_FUNC_CALL();
400 
401         // Check chroma format
402         if (m_vvcPicParams->m_spsChromaFormatIdc  != 1 || // 4:2:0
403             !(m_vvcPicParams->m_spsBitdepthMinus8 == 0 || // 8 bit
404             m_vvcPicParams->m_spsBitdepthMinus8   == 2))  // 10 bit
405         {
406             DECODE_ASSERTMESSAGE("Only 4:2:0 8bit and 10bit are supported!");
407             return MOS_STATUS_INVALID_PARAMETER;
408         }
409 
410         return MOS_STATUS_SUCCESS;
411     }
412 
ErrorDetectAndConceal()413     MOS_STATUS VvcBasicFeature::ErrorDetectAndConceal()
414     {
415         DECODE_FUNC_CALL()
416         DECODE_CHK_NULL(m_vvcPicParams);
417 
418         DECODE_CHK_STATUS(CheckProfileCaps());
419 
420         // Error Detection
421         if (m_vvcPicParams->m_spsLog2CtuSizeMinus5 > 2)
422         {
423             DECODE_ASSERTMESSAGE("pps_log2_ctu_size_minus5 must be less than or equal to 2.\n");
424             return MOS_STATUS_INVALID_PARAMETER;
425         }
426 
427         //slice number limit
428         if (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRectSliceFlag && !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSingleSlicePerSubpicFlag)
429         {
430             if (m_vvcPicParams->m_ppsNumSlicesInPicMinus1 + 1 > vvcMaxSliceNum)
431             {
432                 return MOS_STATUS_INVALID_PARAMETER;
433             }
434         }
435 
436         //Slice number check
437         int16_t numSlices = 0;
438         if (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRectSliceFlag)
439         {
440             numSlices = (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSingleSlicePerSubpicFlag)? (m_vvcPicParams->m_spsNumSubpicsMinus1 + 1):(m_vvcPicParams->m_ppsNumSlicesInPicMinus1 + 1);
441             if (m_numSlices != numSlices)
442             {
443                 DECODE_ASSERTMESSAGE("Rect Slice: Slice number is incorrect.\n");
444             }
445         }
446 
447         //Concealment for bitstream size
448         if (m_numSlices > 0)
449         {
450             CodecVvcSliceParams *lastSlice = m_vvcSliceParams + (m_numSlices - 1);
451             DECODE_CHK_STATUS(SetRequiredBitstreamSize(lastSlice->m_bSNALunitDataLocation + lastSlice->m_sliceBytesInBuffer));
452         }
453 
454         if ((m_vvcPicParams->m_spsFlags0.m_fields.m_spsMaxLumaTransformSize64Flag == 1) && (m_vvcPicParams->m_spsLog2CtuSizeMinus5 == 0))
455         {
456             DECODE_ASSERTMESSAGE("Error concealed: force sps_max_luma_transform_size_64_flag = 0 when sps_log2_ctu_size_minus5 = 0.\n");
457             m_vvcPicParams->m_spsFlags0.m_fields.m_spsMaxLumaTransformSize64Flag = 0;
458         }
459 
460         if ((m_vvcPicParams->m_spsFlags0.m_fields.m_spsTransformSkipEnabledFlag == 0) &&
461             (m_vvcPicParams->m_spsLog2TransformSkipMaxSizeMinus2 > 0 || m_vvcPicParams->m_spsFlags0.m_fields.m_spsBdpcmEnabledFlag > 0))
462         {
463             DECODE_ASSERTMESSAGE("Error detected: (sps_transform_skip_enabled_flag == 0) && (sps_log2_transform_skip_max_size_minus2 > 0 || sps_bdpcm_enabled_flag >0).\n");
464             return MOS_STATUS_INVALID_PARAMETER;
465         }
466 
467         if ((m_vvcPicParams->m_spsFlags0.m_fields.m_spsMtsEnabledFlag == 0) &&
468             (m_vvcPicParams->m_spsFlags0.m_fields.m_spsExplicitMtsIntraEnabledFlag == 1 || m_vvcPicParams->m_spsFlags0.m_fields.m_spsExplicitMtsInterEnabledFlag == 1))
469         {
470             DECODE_ASSERTMESSAGE("Error detected: (sps_mts_enabled_flag == 0) &&  (sps_explicit_mts_intra_enabled_flag == 1 || sps_explicit_mts_inter_enabled_flag == 1).\n");
471             return MOS_STATUS_INVALID_PARAMETER;
472         }
473 
474         if ((m_vvcPicParams->m_spsFlags0.m_fields.m_spsAlfEnabledFlag == 0 || m_vvcPicParams->m_spsChromaFormatIdc == 0) &&
475             (m_vvcPicParams->m_spsFlags0.m_fields.m_spsCcalfEnabledFlag == 1))
476         {
477             DECODE_ASSERTMESSAGE("Error detected: (sps_alf_enabled_flag == 0 || sps_chroma_format_idc == 0) && (sps_ccalf_enabled_flag == 1).\n");
478             return MOS_STATUS_INVALID_PARAMETER;
479         }
480 
481         if (m_shortFormatInUse && (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRefWraparoundEnabledFlag) && m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag)
482         {
483             uint16_t picWidthMaxInCtus = MOS_ROUNDUP_SHIFT(m_vvcPicParams->m_spsPicWidthMaxInLumaSamples, m_vvcPicParams->m_spsLog2CtuSizeMinus5 + 5);
484             uint16_t picWidthInCtus = MOS_ROUNDUP_SHIFT(m_vvcPicParams->m_ppsPicWidthInLumaSamples, m_vvcPicParams->m_spsLog2CtuSizeMinus5 + 5);
485             if (m_vvcPicParams->m_spsNumSubpicsMinus1 > 0)
486             {
487                 for (int16_t sp = 0; sp < m_vvcPicParams->m_spsNumSubpicsMinus1 + 1; sp++)
488                 {
489                     if ((m_subPicParams[sp].m_spsSubpicWidthMinus1 + 1 != picWidthMaxInCtus) &&
490                          m_subPicParams[sp].m_subPicFlags.m_fields.m_spsSubpicTreatedAsPicFlag)
491                     {
492                         DECODE_ASSERTMESSAGE("Error detected: (sps_ref_wraparound_enabled_flag == 1) && (at least one SubPic with sps_subpic_treated_as_pic_flag[i] == 1 && sps_subpic_width_minus1[i] + 1 != (sps_pic_width_max_in_luma_samples + CtbSizeY - 1 ) >> CtbLog2SizeY )).\n");
493                         return MOS_STATUS_INVALID_PARAMETER;
494                     }
495                 }
496             }
497             else
498             {
499                 if (picWidthInCtus != picWidthMaxInCtus)
500                 {
501                     DECODE_ASSERTMESSAGE("Error detected: (sps_ref_wraparound_enabled_flag == 1) && (at least one SubPic with sps_subpic_treated_as_pic_flag[i] == 1 && sps_subpic_width_minus1[i] + 1 != (sps_pic_width_max_in_luma_samples + CtbSizeY - 1 ) >> CtbLog2SizeY )).\n");
502                     return MOS_STATUS_INVALID_PARAMETER;
503                 }
504             }
505         }
506 
507         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsTemporalMvpEnabledFlag && m_vvcPicParams->m_spsFlags1.m_fields.m_spsSbtmvpEnabledFlag)
508         {
509             DECODE_ASSERTMESSAGE("Error detected: sps_temporal_mvp_enabled_flag == 0 && sps_sbtmvp_enabled_flag == 1.\n");
510             return MOS_STATUS_INVALID_PARAMETER;
511         }
512 
513         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsBdofEnabledFlag && m_vvcPicParams->m_spsFlags1.m_fields.m_spsBdofControlPresentInPhFlag)
514         {
515             DECODE_ASSERTMESSAGE("Error detected: sps_bdof_enabled_flag == 0 && sps_bdof_control_present_in_ph_flag == 1.\n");
516             return MOS_STATUS_INVALID_PARAMETER;
517         }
518 
519         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsDmvrEnabledFlag && m_vvcPicParams->m_spsFlags1.m_fields.m_spsDmvrControlPresentInPhFlag)
520         {
521             DECODE_ASSERTMESSAGE("Error detected: sps_dmvr_enabled_flag == 0 && sps_dmvr_control_present_in_ph_flag == 1.\n");
522             return MOS_STATUS_INVALID_PARAMETER;
523         }
524 
525         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsMmvdEnabledFlag && m_vvcPicParams->m_spsFlags1.m_fields.m_spsMmvdFullpelOnlyEnabledFlag)
526         {
527             DECODE_ASSERTMESSAGE("Error detected: (sps_mmvd_enabled_flag == 0) && (sps_mmvd_fullpel_only_enabled_flag == 1).\n");
528             return MOS_STATUS_INVALID_PARAMETER;
529         }
530 
531         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsAffineEnabledFlag &&
532             (m_vvcPicParams->m_spsFiveMinusMaxNumSubblockMergeCand != 0 ||
533              m_vvcPicParams->m_spsFlags1.m_fields.m_sps6paramAffineEnabledFlag != 0 ||
534              m_vvcPicParams->m_spsFlags1.m_fields.m_spsAffineAmvrEnabledFlag == 1 ||
535              m_vvcPicParams->m_spsFlags1.m_fields.m_spsAffineProfEnabledFlag == 1 ||
536              m_vvcPicParams->m_spsFlags1.m_fields.m_spsProfControlPresentInPhFlag == 1))
537         {
538             DECODE_ASSERTMESSAGE("Error detected: sps_affine_enabled_flag == 0 && (sps_five_minus_max_num_subblock_merge_cand != 0 || sps_6param_affine_enabled_flag != 0 || sps_affine_amvr_enabled_flag == 1 || sps_affine_prof_enabled_flag == 1 || sps_prof_control_present_in_ph_flag  == 1).\n");
539             return MOS_STATUS_INVALID_PARAMETER;
540         }
541 
542         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsAmvrEnabledFlag && m_vvcPicParams->m_spsFlags1.m_fields.m_spsAffineAmvrEnabledFlag == 1)
543         {
544             DECODE_ASSERTMESSAGE("Error detected: sps_amvr_enabled_flag == 0 && sps_affine_amvr_enabled_flag == 1.\n");
545             return MOS_STATUS_INVALID_PARAMETER;
546         }
547 
548         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsAffineProfEnabledFlag && m_vvcPicParams->m_spsFlags1.m_fields.m_spsProfControlPresentInPhFlag)
549         {
550             DECODE_ASSERTMESSAGE("Error detected: sps_affine_prof_enabled_flag == 0 && sps_prof_control_present_in_ph_flag == 1.\n");
551             return MOS_STATUS_INVALID_PARAMETER;
552         }
553 
554         if (m_vvcPicParams->m_spsSixMinusMaxNumMergeCand == 5 && m_vvcPicParams->m_spsFlags1.m_fields.m_spsGpmEnabledFlag)
555         {
556             DECODE_ASSERTMESSAGE("Error detected: sps_six_minus_max_num_merge_cand == 5 && sps_gpm_enabled_flag == 1.\n");
557             return MOS_STATUS_INVALID_PARAMETER;
558         }
559 
560         if (m_vvcPicParams->m_spsChromaFormatIdc == 0 && m_vvcPicParams->m_spsFlags1.m_fields.m_spsCclmEnabledFlag)
561         {
562             DECODE_ASSERTMESSAGE("Error detected: sps_chroma_format_idc ==  0 && sps_cclm_enabled_flag == 1.\n");
563             return MOS_STATUS_INVALID_PARAMETER;
564         }
565 
566         if (m_vvcPicParams->m_spsChromaFormatIdc != 1 &&
567             (m_vvcPicParams->m_spsFlags1.m_fields.m_spsChromaHorizontalCollocatedFlag ||
568              m_vvcPicParams->m_spsFlags1.m_fields.m_spsChromaVerticalCollocatedFlag))
569         {
570             DECODE_ASSERTMESSAGE("Error detected: (sps_chroma_format_idc != 1) && ((sps_chroma_horizontal_collocated_flag != 0) || (sps_chroma_vertical_collocated_flag!=0)).\n");
571             return MOS_STATUS_INVALID_PARAMETER;
572         }
573 
574         if ((m_vvcPicParams->m_spsChromaFormatIdc != 3 || m_vvcPicParams->m_spsFlags0.m_fields.m_spsMaxLumaTransformSize64Flag) &&
575             m_vvcPicParams->m_spsFlags2.m_fields.m_spsActEnabledFlag != 0)
576         {
577             DECODE_ASSERTMESSAGE("Error detected: (sps_chroma_format_idc  !=  3  ||  sps_max_luma_transform_size_64_flag ==1) && (sps_act_enabled_flag != 0).\n");
578             return MOS_STATUS_INVALID_PARAMETER;
579         }
580 
581         if (!m_vvcPicParams->m_spsFlags0.m_fields.m_spsTransformSkipEnabledFlag &&
582             !m_vvcPicParams->m_spsFlags2.m_fields.m_spsPaletteEnabledFlag &&
583             m_vvcPicParams->m_spsMinQpPrimeTs == 1)
584         {
585             DECODE_ASSERTMESSAGE("Error detected: sps_transform_skip_enabled_flag ==0 &&  sps_palette_enabled_flag == 0 && sps_min_qp_prime_ts == 1.\n");
586             return MOS_STATUS_INVALID_PARAMETER;
587         }
588 
589         if ((!m_vvcPicParams->m_spsFlags2.m_fields.m_spsActEnabledFlag || !m_vvcPicParams->m_spsFlags2.m_fields.m_spsExplicitScalingListEnabledFlag) &&
590             m_vvcPicParams->m_spsFlags2.m_fields.m_spsScalingMatrixForAlternativeColourSpaceDisabledFlag)
591         {
592             DECODE_ASSERTMESSAGE("Error detected: (sps_act_enabled_flag == 0 ||  sps_explicit_scaling_list_enabled_flag == 0 ) && sps_scaling_matrix_for_alternative_colour_space_disabled_flag == 1.\n");
593             return MOS_STATUS_INVALID_PARAMETER;
594         }
595 
596         if (!m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesEnabledFlag && m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesPresentFlag)
597         {
598             DECODE_ASSERTMESSAGE("Error detected: sps_virtual_boundaries_enabled_flag ==0 && sps_virtual_boundaries_present_flag==1.\n");
599             return MOS_STATUS_INVALID_PARAMETER;
600         }
601 
602         if (m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag &&
603             m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesEnabledFlag &&
604             !m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesPresentFlag)
605         {
606             DECODE_ASSERTMESSAGE("Error concealed: force sps_virtual_boundaries_enabled_flag from 1 to 0.\n");
607             m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesEnabledFlag = 0;
608         }
609 
610         if (!m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesPresentFlag && m_vvcPicParams->m_spsNumVerVirtualBoundaries > 0)
611         {
612             DECODE_ASSERTMESSAGE("Error detected: sps_virtual_boundaries_present_flag == 0 && sps_num_ver_virtual_boundaries > 0.\n");
613             return MOS_STATUS_INVALID_PARAMETER;
614         }
615 
616         if (m_shortFormatInUse && (m_vvcPicParams->m_ppsPicWidthInLumaSamples != m_vvcPicParams->m_spsPicWidthMaxInLumaSamples ||
617              m_vvcPicParams->m_ppsPicHeightInLumaSamples != m_vvcPicParams->m_spsPicHeightMaxInLumaSamples))
618         {
619             if (m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag)
620             {
621                 DECODE_ASSERTMESSAGE("Error detected: (pps_pic_width_in_luma_samples != sps_pic_width_max_in_luma_samples || pps_pic_height_in_luma_samples != sps_pic_height_max_in_luma_samples) && (sps_virtual_boundaries_present_flag == 1 || sps_subpic_info_present_flag == 1).\n");
622                 return MOS_STATUS_INVALID_PARAMETER;
623             }
624 
625             if (m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesPresentFlag)
626             {
627                 DECODE_ASSERTMESSAGE("Error concealed: force sps_virtual_boundaries_present_flag from 1 to 0 when (pps_pic_width_in_luma_samples != sps_pic_width_max_in_luma_samples || pps_pic_height_in_luma_samples != sps_pic_height_max_in_luma_samples).\n");
628                 m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesEnabledFlag = 0;
629             }
630         }
631 
632         if (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRefWraparoundEnabledFlag)
633         {
634             if ((1 << (m_vvcPicParams->m_spsLog2CtuSizeMinus5 + 3 - m_vvcPicParams->m_spsLog2MinLumaCodingBlockSizeMinus2)) > ((m_vvcPicParams->m_ppsPicWidthInLumaSamples >> (m_vvcPicParams->m_spsLog2MinLumaCodingBlockSizeMinus2 + 2)) - 1))
635             {
636                 DECODE_ASSERTMESSAGE("Error detected: pps_ref_wraparound_enabled_flag == 1 && ( CtbSizeY / MinCbSizeY + 1 ) > ( pps_pic_width_in_luma_samples / MinCbSizeY - 1 ).\n");
637                 return MOS_STATUS_INVALID_PARAMETER;
638             }
639         }
640 
641         if (!m_shortFormatInUse)
642         {
643             // Scaling Window
644             int8_t subWidthC = (m_vvcPicParams->m_spsChromaFormatIdc == 0 || m_vvcPicParams->m_spsChromaFormatIdc == 3) ? 1 : 2;
645             int8_t subHeightC = (m_vvcPicParams->m_spsChromaFormatIdc == 0 || m_vvcPicParams->m_spsChromaFormatIdc == 3) ? 1 : ((m_vvcPicParams->m_spsChromaFormatIdc == 1) ? 2 : 1);
646 
647             int32_t value1 = subWidthC * m_vvcPicParams->m_ppsScalingWinLeftOffset;
648             int32_t value2 = subWidthC * m_vvcPicParams->m_ppsScalingWinRightOffset;
649             int32_t min = -15 * m_vvcPicParams->m_ppsPicWidthInLumaSamples;
650             int32_t max = m_vvcPicParams->m_ppsPicWidthInLumaSamples;
651             bool scalWinOutOfHorRange = false;
652 
653             if ((value1 < min || value1 >= max) ||
654                 (value2 < min || value2 >= max) ||
655                 (value1 + value2 < min || value1 + value2 >= max))
656             {
657                 scalWinOutOfHorRange = true;
658             }
659 
660             value1 = subHeightC * m_vvcPicParams->m_ppsScalingWinTopOffset;
661             value2 = subHeightC * m_vvcPicParams->m_ppsScalingWinBottomOffset;
662             min = -15 * m_vvcPicParams->m_ppsPicHeightInLumaSamples;
663             max = m_vvcPicParams->m_ppsPicHeightInLumaSamples;
664             bool scalWinOutOfVerRange = false;
665 
666             if ((value1 < min || value1 >= max) ||
667                 (value2 < min || value2 >= max) ||
668                 (value1 + value2 < min || value1 + value2 >= max))
669             {
670                 scalWinOutOfVerRange = true;
671             }
672 
673             VvcRefFrameAttributes curFrameAttr;
674             DECODE_CHK_STATUS(m_refFrames.GetRefAttrByFrameIndex(
675                 m_vvcPicParams->m_currPic.FrameIdx,
676                     &curFrameAttr));
677 
678             for (uint32_t slc = 0; slc < m_numSlices; slc++)
679             {
680                 CodecVvcSliceParams* curSliceParams = &m_vvcSliceParams[slc];
681                 if (curSliceParams->m_shSliceType != vvcSliceI)
682                 {
683                     if (scalWinOutOfHorRange == true)
684                     {
685                         DECODE_ASSERTMESSAGE("Error detected: pps_scaling_win_left_offset or pps_scaling_win_right_offset out of range.\n");
686                         return MOS_STATUS_INVALID_PARAMETER;
687                     }
688                     if (scalWinOutOfVerRange == true)
689                     {
690                         DECODE_ASSERTMESSAGE("Error detected: pps_scaling_win_top_offset or pps_scaling_win_bottom_offset out of range.\n");
691                         return MOS_STATUS_INVALID_PARAMETER;
692                     }
693 
694                     for (auto i = 0; i < 2; i++)
695                     {
696                         for (auto j = 0; j < curSliceParams->m_numRefIdxActive[i]; j++)
697                         {
698                             uint8_t refPicIdx = curSliceParams->m_refPicList[i][j].FrameIdx;
699                             if (refPicIdx < vvcMaxNumRefFrame)
700                             {
701                                 VvcRefFrameAttributes       refFrameAttr;
702                                 uint8_t refFrameIdx;
703                                 if (m_vvcPicParams->m_refFrameList[refPicIdx].PicFlags != PICTURE_INVALID)
704                                 {
705                                     refFrameIdx = m_vvcPicParams->m_refFrameList[refPicIdx].FrameIdx;
706                                     DECODE_CHK_STATUS(m_refFrames.GetRefAttrByFrameIndex(
707                                         refFrameIdx,
708                                         &refFrameAttr));
709 
710                                     if (((curFrameAttr.m_currPicScalWinWidthL << 1) < refFrameAttr.m_currPicScalWinWidthL) ||
711                                         ((curFrameAttr.m_currPicScalWinHeightL << 1) < refFrameAttr.m_currPicScalWinHeightL) ||
712                                         (curFrameAttr.m_currPicScalWinWidthL > (refFrameAttr.m_currPicScalWinWidthL << 3)) ||
713                                         (curFrameAttr.m_currPicScalWinHeightL > (refFrameAttr.m_currPicScalWinHeightL << 3)))
714                                     {
715                                         DECODE_ASSERTMESSAGE("Error detected: current frame's scaling window width/height out of range against ref frame.\n");
716                                         return MOS_STATUS_INVALID_PARAMETER;
717                                     }
718                                 }
719                             }
720                         }
721                     }
722                 }
723             }
724         }
725         if (m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag && !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRectSliceFlag)
726         {
727             DECODE_ASSERTMESSAGE("Error detected: sps_subpic_info_present_flag == 1 && pps_rect_slice_flag == 0.\n");
728             return MOS_STATUS_INVALID_PARAMETER;
729         }
730 
731         if (m_shortFormatInUse && m_vvcPicParams->m_spsChromaFormatIdc == 0 && m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag)
732         {
733             DECODE_ASSERTMESSAGE("Error detected: sps_chroma_format_idc == 0 &&  pps_chroma_tool_offsets_present_flag == 1.\n");
734             return MOS_STATUS_INVALID_PARAMETER;
735         }
736 
737         if (m_shortFormatInUse && (m_vvcPicParams->m_spsChromaFormatIdc == 0 || !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag) &&
738             (m_vvcPicParams->m_ppsCbQpOffset != 0 ||
739                 m_vvcPicParams->m_ppsCrQpOffset != 0 ||
740                 m_vvcPicParams->m_ppsJointCbcrQpOffsetValue != 0 ||
741                 m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSliceChromaQpOffsetsPresentFlag != 0 ||
742                 m_vvcPicParams->m_ppsFlags.m_fields.m_ppsCuChromaQpOffsetListEnabledFlag != 0))
743         {
744             DECODE_ASSERTMESSAGE("Error concealed: force chroma qp offsets/flags to 0 for (sps_chroma_format_idc == 0 || pps_chroma_tool_offsets_present_flag == 0).\n");
745             m_vvcPicParams->m_ppsCbQpOffset = 0;
746             m_vvcPicParams->m_ppsCrQpOffset = 0;
747             m_vvcPicParams->m_ppsJointCbcrQpOffsetValue = 0;
748             m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSliceChromaQpOffsetsPresentFlag = 0;
749             m_vvcPicParams->m_ppsFlags.m_fields.m_ppsCuChromaQpOffsetListEnabledFlag = 0;
750         }
751 
752         if (m_shortFormatInUse && !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag)
753         {
754             for (auto i = 0; i < 6; i++)
755             {
756                 if (m_vvcPicParams->m_ppsJointCbcrQpOffsetList[i] != 0)
757                 {
758                     DECODE_ASSERTMESSAGE("Error concealed: force pps_joint_cbcr_qp_offset_list[i] to 0 since pps_chroma_tool_offsets_present_flag == 0.\n");
759                     m_vvcPicParams->m_ppsJointCbcrQpOffsetList[i] = 0;
760                 }
761             }
762         }
763 
764         bool partitionFlag = ((m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSingleSlicePerSubpicFlag && m_vvcPicParams->m_spsNumSubpicsMinus1 > 0) ||
765             (!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSingleSlicePerSubpicFlag && m_vvcPicParams->m_ppsNumSlicesInPicMinus1 > 0) ||
766             m_tileRows > 0 || m_tileCols > 0 );
767         if ((!partitionFlag || (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsDeblockingFilterOverrideEnabledFlag == 0)) &&
768             (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsDbfInfoInPhFlag == 1))
769         {
770             DECODE_ASSERTMESSAGE("Error concealed: force pps_dbf_info_in_ph_flag to 0 when (!pps_no_pic_partition_flag && pps_deblocking_filter_override_enabled_flag) is false.\n");
771             m_vvcPicParams->m_ppsFlags.m_fields.m_ppsDbfInfoInPhFlag = 0;
772         }
773 
774         if (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsDeblockingFilterDisabledFlag &&
775             (m_vvcPicParams->m_ppsLumaBetaOffsetDiv2 != 0 || m_vvcPicParams->m_ppsLumaTcOffsetDiv2 != 0))
776         {
777             DECODE_ASSERTMESSAGE("Error concealed: force luma_beta_offset_div2 and luma_tc_offset_div2 to 0 when pps_deblocking_filter_disabled_flag is true.\n");
778             m_vvcPicParams->m_ppsLumaBetaOffsetDiv2 = 0;
779             m_vvcPicParams->m_ppsLumaTcOffsetDiv2 = 0;
780         }
781 
782         if (m_shortFormatInUse && !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag &&
783             (m_vvcPicParams->m_phCbBetaOffsetDiv2 != m_vvcPicParams->m_phLumaBetaOffsetDiv2 ||
784              m_vvcPicParams->m_phCbTcOffsetDiv2 != m_vvcPicParams->m_phLumaTcOffsetDiv2 ||
785              m_vvcPicParams->m_phCrBetaOffsetDiv2 != m_vvcPicParams->m_phLumaBetaOffsetDiv2 ||
786              m_vvcPicParams->m_phCrTcOffsetDiv2 != m_vvcPicParams->m_phLumaTcOffsetDiv2))
787         {
788             DECODE_ASSERTMESSAGE("Error concealed: force chroma beta/tc offsets to the same syntax of luma when pps_chroma_tool_offsets_present_flag is 0.\n");
789             m_vvcPicParams->m_phCbBetaOffsetDiv2    = m_vvcPicParams->m_phLumaBetaOffsetDiv2;
790             m_vvcPicParams->m_phCbTcOffsetDiv2      = m_vvcPicParams->m_phLumaTcOffsetDiv2;
791             m_vvcPicParams->m_phCrBetaOffsetDiv2    = m_vvcPicParams->m_phLumaBetaOffsetDiv2;
792             m_vvcPicParams->m_phCrTcOffsetDiv2      = m_vvcPicParams->m_phLumaTcOffsetDiv2;
793         }
794 
795         if (m_shortFormatInUse && ((!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsWeightedPredFlag && !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsWeightedBipredFlag) ||
796             !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRplInfoInPhFlag) && m_vvcPicParams->m_ppsFlags.m_fields.m_ppsWpInfoInPhFlag)
797         {
798             DECODE_ASSERTMESSAGE("Error concealed: force pps_wp_info_in_ph_flag = 0 when ((pps_weighted_pred_flag == 0 &&  pps_weighted_bipred_flag ==0) || pps_rpl_info_in_ph_flag == 0 ).\n");
799             m_vvcPicParams->m_ppsFlags.m_fields.m_ppsWpInfoInPhFlag = 0;
800         }
801 
802         if ((!m_vvcPicParams->m_spsFlags0.m_fields.m_spsAlfEnabledFlag ||
803             !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsAlfInfoInPhFlag) &&
804             m_vvcPicParams->m_phFlags.m_fields.m_phAlfEnabledFlag)
805         {
806             DECODE_ASSERTMESSAGE("Error concealed: force ph_alf_enabled_flag = 0 when (sps_alf_enabled_flag == 0 || pps_alf_info_in_ph_flag == 0) is true\n");
807             m_vvcPicParams->m_phFlags.m_fields.m_phAlfEnabledFlag = 0;
808         }
809 
810         if (!m_vvcPicParams->m_spsFlags0.m_fields.m_spsCcalfEnabledFlag)
811         {
812             for (auto i = 0; i < vvcMaxAlfNum; i++)
813             {
814                 if (m_activeAlfMask & (1 << i))
815                 {
816                     if (m_alfApsArray[i].m_alfFlags.m_fields.m_alfCcCbFilterSignalFlag ||
817                         m_alfApsArray[i].m_alfFlags.m_fields.m_alfCcCrFilterSignalFlag)
818                     {
819                         DECODE_ASSERTMESSAGE("Error concealed: force alf_cc_cb_filter_signal_flag = 0, alf_cc_cr_filter_signal_flag = 0 when sps_ccalf_enabled_flag is 0\n");
820                         m_alfApsArray[i].m_alfFlags.m_fields.m_alfCcCbFilterSignalFlag = 0;
821                         m_alfApsArray[i].m_alfFlags.m_fields.m_alfCcCrFilterSignalFlag = 0;
822                     }
823                 }
824             }
825         }
826 
827         if (!m_vvcPicParams->m_phFlags.m_fields.m_phAlfEnabledFlag &&
828             (m_vvcPicParams->m_phFlags.m_fields.m_phAlfCbEnabledFlag ||
829              m_vvcPicParams->m_phFlags.m_fields.m_phAlfCrEnabledFlag))
830         {
831             DECODE_ASSERTMESSAGE("Error concealed: force ph_alf_cb_enabled_flag = 0, ph_alf_cr_enabled_flag = 0 when ph_alf_enabled_flag = 0.\n");
832             m_vvcPicParams->m_phFlags.m_fields.m_phAlfCbEnabledFlag = 0;
833             m_vvcPicParams->m_phFlags.m_fields.m_phAlfCrEnabledFlag = 0;
834         }
835 
836         if (!m_vvcPicParams->m_spsFlags0.m_fields.m_spsCcalfEnabledFlag &&
837             (m_vvcPicParams->m_phFlags.m_fields.m_phAlfCcCbEnabledFlag ||
838              m_vvcPicParams->m_phFlags.m_fields.m_phAlfCcCrEnabledFlag))
839         {
840             DECODE_ASSERTMESSAGE("Error concealed: force ph_alf_cc_cb_enabled_flag = 0, ph_alf_cc_cr_enabled_flag = 0 when sps_ccalf_enabled_flag = 0.\n");
841             m_vvcPicParams->m_phFlags.m_fields.m_phAlfCcCbEnabledFlag = 0;
842             m_vvcPicParams->m_phFlags.m_fields.m_phAlfCcCrEnabledFlag = 0;
843         }
844 
845         if (!m_vvcPicParams->m_spsFlags0.m_fields.m_spsLmcsEnabledFlag && m_vvcPicParams->m_phFlags.m_fields.m_phLmcsEnabledFlag)
846         {
847             DECODE_ASSERTMESSAGE("Error concealed: force ph_lmcs_enabled_flag = 0 when sps_lmcs_enabled_flag = 0.\n");
848             m_vvcPicParams->m_phFlags.m_fields.m_phLmcsEnabledFlag = 0;
849         }
850 
851         if (!m_vvcPicParams->m_phFlags.m_fields.m_phLmcsEnabledFlag && m_vvcPicParams->m_phFlags.m_fields.m_phChromaResidualScaleFlag)
852         {
853             DECODE_ASSERTMESSAGE("Error concealed: force ph_chroma_residual_scale_flag = 0 when ph_lmcs_enabled_flag = 0.\n");
854             m_vvcPicParams->m_phFlags.m_fields.m_phChromaResidualScaleFlag = 0;
855         }
856 
857         if (!m_vvcPicParams->m_spsFlags2.m_fields.m_spsExplicitScalingListEnabledFlag &&
858             m_vvcPicParams->m_phFlags.m_fields.m_phExplicitScalingListEnabledFlag)
859         {
860             DECODE_ASSERTMESSAGE("Error concealed: force ph_explicit_scaling_list_enabled_flag = 0 when sps_explicit_scaling_list_enabled_flag = 0.\n");
861             m_vvcPicParams->m_phFlags.m_fields.m_phExplicitScalingListEnabledFlag = 0;
862         }
863 
864         if ((!m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesEnabledFlag ||
865              m_vvcPicParams->m_spsFlags2.m_fields.m_spsVirtualBoundariesPresentFlag) &&
866             m_vvcPicParams->m_phFlags.m_fields.m_phVirtualBoundariesPresentFlag)
867         {
868             DECODE_ASSERTMESSAGE("Error concealed: force ph_virtual_boundaries_present_flag = 0 when (sps_virtual_boundaries_enabled_flag == 0 || sps_virtual_boundaries_present_flag == 1) is true.\n");
869             m_vvcPicParams->m_phFlags.m_fields.m_phVirtualBoundariesPresentFlag = 0;
870         }
871 
872         if (!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsCuQpDeltaEnabledFlag &&
873             m_vvcPicParams->m_phCuQpDeltaSubdivIntraSlice != 0)
874         {
875             DECODE_ASSERTMESSAGE("Error concealed: force ph_cu_qp_delta_subdiv_intra_slice = 0 when pps_cu_qp_delta_enabled_flag is 0.\n");
876             m_vvcPicParams->m_phCuQpDeltaSubdivIntraSlice = 0;
877         }
878 
879         if (!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsCuChromaQpOffsetListEnabledFlag &&
880             m_vvcPicParams->m_phCuChromaQpOffsetSubdivIntraSlice != 0)
881         {
882             DECODE_ASSERTMESSAGE("Error concealed: force ph_cu_chroma_qp_offset_subdiv_intra_slice = 0 when pps_cu_chroma_qp_offset_list_enabled_flag is 0.\n");
883             m_vvcPicParams->m_phCuChromaQpOffsetSubdivIntraSlice = 0;
884         }
885 
886         if (!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsCuQpDeltaEnabledFlag &&
887             m_vvcPicParams->m_phCuQpDeltaSubdivInterSlice != 0)
888         {
889             DECODE_ASSERTMESSAGE("Error concealed: force ph_cu_qp_delta_subdiv_inter_slice = 0 when pps_cu_qp_delta_enabled_flag is 0.\n");
890             m_vvcPicParams->m_phCuQpDeltaSubdivInterSlice = 0;
891         }
892 
893         if (!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsCuChromaQpOffsetListEnabledFlag &&
894             m_vvcPicParams->m_phCuChromaQpOffsetSubdivInterSlice != 0)
895         {
896             DECODE_ASSERTMESSAGE("Error concealed: force ph_cu_chroma_qp_offset_subdiv_inter_slice = 0 when pps_cu_chroma_qp_offset_list_enabled_flag is 0.\n");
897             m_vvcPicParams->m_phCuChromaQpOffsetSubdivInterSlice = 0;
898         }
899 
900         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsTemporalMvpEnabledFlag &&
901             m_vvcPicParams->m_phFlags.m_fields.m_phTemporalMvpEnabledFlag)
902         {
903             DECODE_ASSERTMESSAGE("Error concealed: force ph_temporal_mvp_enabled_flag = 0 when sps_temporal_mvp_enabled_flag is 0.\n");
904             m_vvcPicParams->m_phFlags.m_fields.m_phTemporalMvpEnabledFlag = 0;
905         }
906 
907         if (m_vvcPicParams->m_phFlags.m_fields.m_phTemporalMvpEnabledFlag == 1)
908         {
909             VvcRefFrameAttributes curFrameAttr;
910             DECODE_CHK_STATUS(m_refFrames.GetRefAttrByFrameIndex(
911                 m_vvcPicParams->m_currPic.FrameIdx,
912                     &curFrameAttr));
913 
914             bool allDiffFlag = true;
915             uint8_t frameIdx = 0;
916             VvcRefFrameAttributes refFrameAttr;
917             for (uint8_t i = 0; i < vvcMaxNumRefFrame; i++)
918             {
919                 if (m_vvcPicParams->m_refFrameList[i].PicFlags != PICTURE_INVALID)
920                 {
921                     frameIdx = m_vvcPicParams->m_refFrameList[i].FrameIdx;
922                     DECODE_CHK_STATUS(m_refFrames.GetRefAttrByFrameIndex(
923                         frameIdx,
924                         &refFrameAttr));
925 
926                     allDiffFlag &= (curFrameAttr.m_refpicwidth               != refFrameAttr.m_refpicwidth) ||
927                                    (curFrameAttr.m_refpicheight              != refFrameAttr.m_refpicheight) ||
928                                    (curFrameAttr.m_refscalingwinbottomoffset != refFrameAttr.m_refscalingwinbottomoffset) ||
929                                    (curFrameAttr.m_refscalingwintopoffset    != refFrameAttr.m_refscalingwintopoffset) ||
930                                    (curFrameAttr.m_refscalingwinleftoffset   != refFrameAttr.m_refscalingwinleftoffset) ||
931                                    (curFrameAttr.m_refscalingwinrightoffset  != refFrameAttr.m_refscalingwinrightoffset);
932 
933                     if (!allDiffFlag)
934                     {
935                         DECODE_NORMALMESSAGE("Found a ref pic in the DPB has the same spatial resolution and the same scaling window offsets as the current picture.\n");
936                         break;
937                     }
938                 }
939             }
940 
941             if (allDiffFlag)
942             {
943                 DECODE_ASSERTMESSAGE("Error concealed: force ph_temporal_mvp_enabled_flag = 0 if no reference picture in the DPB has the same spatial resolution and the same scaling window offsets as the current picture.\n");
944                 m_vvcPicParams->m_phFlags.m_fields.m_phTemporalMvpEnabledFlag = 0;
945             }
946         }
947 
948         if (m_shortFormatInUse && m_vvcPicParams->m_phFlags.m_fields.m_phInterSliceAllowedFlag && m_vvcPicParams->m_phFlags.m_fields.m_phTemporalMvpEnabledFlag &&
949             m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRplInfoInPhFlag &&
950             !m_vvcPicParams->m_phFlags.m_fields.m_numRefEntries1RplIdx1LargerThan0 &&
951             !m_vvcPicParams->m_phFlags.m_fields.m_phCollocatedFromL0Flag)
952         {
953             DECODE_ASSERTMESSAGE("Error detected: ph_collocated_from_l0_flag = 0 when (ph_temporal_mvp_enabled_flag == 1 && pps_rpl_info_in_ph_flag == 1 && num_ref_entries[ 1 ][ RplsIdx[ 1 ] ] == 0) is true.\n");
954             return MOS_STATUS_INVALID_PARAMETER;
955         }
956 
957         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsMmvdFullpelOnlyEnabledFlag &&
958             m_vvcPicParams->m_phFlags.m_fields.m_phMmvdFullpelOnlyFlag)
959         {
960             DECODE_ASSERTMESSAGE("Error concealed: force ph_mmvd_fullpel_only_flag = 0 when sps_mmvd_fullpel_only_enabled_flag is 0.\n");
961             m_vvcPicParams->m_phFlags.m_fields.m_phMmvdFullpelOnlyFlag = 0;
962         }
963 
964         uint32_t bdofDisabledFlag = m_vvcPicParams->m_spsFlags1.m_fields.m_spsBdofControlPresentInPhFlag ? 1 : (1 - m_vvcPicParams->m_spsFlags1.m_fields.m_spsBdofEnabledFlag);
965         uint32_t dmvrDisabledFlag = m_vvcPicParams->m_spsFlags1.m_fields.m_spsDmvrControlPresentInPhFlag ? 1 : (1-m_vvcPicParams->m_spsFlags1.m_fields.m_spsDmvrEnabledFlag);
966 
967         if (m_shortFormatInUse && m_vvcPicParams->m_phFlags.m_fields.m_phInterSliceAllowedFlag && m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRplInfoInPhFlag &&
968             !m_vvcPicParams->m_phFlags.m_fields.m_numRefEntries1RplIdx1LargerThan0 &&
969             (!m_vvcPicParams->m_phFlags.m_fields.m_phMvdL1ZeroFlag ||
970              m_vvcPicParams->m_phFlags.m_fields.m_phBdofDisabledFlag != bdofDisabledFlag ||
971              m_vvcPicParams->m_phFlags.m_fields.m_phDmvrDisabledFlag != dmvrDisabledFlag))
972         {
973             if (!m_vvcPicParams->m_phFlags.m_fields.m_phMvdL1ZeroFlag)
974             {
975                 DECODE_ASSERTMESSAGE("Error detected: ph_mvd_l1_zero_flag = 0 when pps_rpl_info_in_ph_flag = 1 && num_ref_entries[ 1 ][ RplsIdx[ 1 ] ] = 0;\n");
976                 return MOS_STATUS_INVALID_PARAMETER;
977             }
978             else
979             {
980                 DECODE_ASSERTMESSAGE("Error concealed: since pps_rpl_info_in_ph_flag = 1 && num_ref_entries[ 1 ][ RplsIdx[ 1 ] ] = 0, do concealment:\n\
981                 Force ph_bdof_disabled_flag = sps_bdof_control_present_in_ph_flag == 0? 1 - sps_bdof_enabled_flag : 1;\n\
982                 Force ph_dmvr_disabled_flag = sps_dmvr_control_present_in_ph_flag == 0 ? 1 - sps_dmvr_enabled_flag : 1;\n");
983 
984                 m_vvcPicParams->m_phFlags.m_fields.m_phBdofDisabledFlag = bdofDisabledFlag;
985                 m_vvcPicParams->m_phFlags.m_fields.m_phDmvrDisabledFlag = dmvrDisabledFlag;
986             }
987         }
988 
989         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsBdofControlPresentInPhFlag &&
990             m_vvcPicParams->m_phFlags.m_fields.m_phBdofDisabledFlag != bdofDisabledFlag)
991         {
992             DECODE_ASSERTMESSAGE("Error concealed: Force ph_bdof_disabled_flag = sps_bdof_control_present_in_ph_flag == 0? 1 - sps_bdof_enabled_flag : 1;\n");
993             m_vvcPicParams->m_phFlags.m_fields.m_phBdofDisabledFlag = bdofDisabledFlag;
994         }
995 
996         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsDmvrControlPresentInPhFlag &&
997             m_vvcPicParams->m_phFlags.m_fields.m_phDmvrDisabledFlag != dmvrDisabledFlag)
998         {
999             DECODE_ASSERTMESSAGE("Error concealed: force ph_dmvr_disabled_flag = sps_dmvr_control_present_in_ph_flag == 0 ? 1 - sps_dmvr_enabled_flag : 1;\n");
1000             m_vvcPicParams->m_phFlags.m_fields.m_phDmvrDisabledFlag = dmvrDisabledFlag;
1001         }
1002 
1003         if (m_shortFormatInUse && !m_vvcPicParams->m_spsFlags1.m_fields.m_spsProfControlPresentInPhFlag &&
1004             m_vvcPicParams->m_phFlags.m_fields.m_phProfDisabledFlag != 1 - m_vvcPicParams->m_spsFlags1.m_fields.m_spsAffineProfEnabledFlag)
1005         {
1006             DECODE_ASSERTMESSAGE("Error concealed: force ph_prof_disabled_flag = 1-sps_affine_prof_enabled_flag when sps_prof_control_present_in_ph_flag = 0.\n");
1007             m_vvcPicParams->m_phFlags.m_fields.m_phProfDisabledFlag = 1 - m_vvcPicParams->m_spsFlags1.m_fields.m_spsAffineProfEnabledFlag;
1008         }
1009 
1010         if ((!m_vvcPicParams->m_spsFlags0.m_fields.m_spsSaoEnabledFlag || !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSaoInfoInPhFlag) &&
1011             m_vvcPicParams->m_phFlags.m_fields.m_phSaoLumaEnabledFlag)
1012         {
1013             DECODE_ASSERTMESSAGE("Error concealed: force ph_sao_luma_enabled_flag = 0 when (sps_sao_enabled_flag == 0 ||  pps_sao_info_in_ph_flag == 0) is true.\n");
1014             m_vvcPicParams->m_phFlags.m_fields.m_phSaoLumaEnabledFlag = 0;
1015         }
1016 
1017         if ((!m_vvcPicParams->m_spsFlags0.m_fields.m_spsSaoEnabledFlag ||
1018             !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSaoInfoInPhFlag ||
1019             m_vvcPicParams->m_spsChromaFormatIdc == 0) &&
1020             m_vvcPicParams->m_phFlags.m_fields.m_phSaoChromaEnabledFlag)
1021         {
1022             DECODE_ASSERTMESSAGE("Error concealed: force ph_sao_chroma_enabled_flag = 0 when (sps_sao_enabled_flag == 0 ||  pps_sao_info_in_ph_flag == 0 || sps_chroma_format_idc  ==  0) is true.\n");
1023             m_vvcPicParams->m_phFlags.m_fields.m_phSaoChromaEnabledFlag = 0;
1024         }
1025 
1026         // Deblocking filter - luma
1027         if(m_shortFormatInUse && (!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsDbfInfoInPhFlag ||
1028             m_vvcPicParams->m_phFlags.m_fields.m_phDeblockingFilterDisabledFlag) &&
1029            (m_vvcPicParams->m_phLumaBetaOffsetDiv2 != m_vvcPicParams->m_ppsLumaBetaOffsetDiv2 ||
1030             m_vvcPicParams->m_phLumaTcOffsetDiv2 != m_vvcPicParams->m_ppsLumaTcOffsetDiv2))
1031         {
1032             DECODE_ASSERTMESSAGE("Error concealed: force ph_luma_beta_offset_div2=pps_luma_beta_offset_div2, ph_luma_tc_offset_div2 = pps_luma_tc_offset_div2 when (pps_dbf_info_in_ph_flag == 0 || ph_deblocking_filter_disabled_flag == 1) is true.\n");
1033             m_vvcPicParams->m_phLumaBetaOffsetDiv2 = m_vvcPicParams->m_ppsLumaBetaOffsetDiv2;
1034             m_vvcPicParams->m_phLumaTcOffsetDiv2 = m_vvcPicParams->m_ppsLumaTcOffsetDiv2;
1035         }
1036 
1037         if (m_shortFormatInUse)
1038         {
1039             // Deblocking filter - chroma
1040             int8_t cbBetaOffsetDiv2 = m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag ? m_vvcPicParams->m_ppsCbBetaOffsetDiv2 : m_vvcPicParams->m_phLumaBetaOffsetDiv2;
1041             int8_t cbTcOffsetDiv2   = m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag ? m_vvcPicParams->m_ppsCbTcOffsetDiv2 : m_vvcPicParams->m_phLumaTcOffsetDiv2;
1042             int8_t crBetaOffsetDiv2 = m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag ? m_vvcPicParams->m_ppsCrBetaOffsetDiv2 : m_vvcPicParams->m_phLumaBetaOffsetDiv2;
1043             int8_t crTcOffsetDiv2   = m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag ? m_vvcPicParams->m_ppsCrTcOffsetDiv2 : m_vvcPicParams->m_phLumaTcOffsetDiv2;
1044 
1045             if ((!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsDbfInfoInPhFlag ||
1046                     m_vvcPicParams->m_phFlags.m_fields.m_phDeblockingFilterDisabledFlag ||
1047                     !m_vvcPicParams->m_ppsFlags.m_fields.m_ppsChroma_toolOffsetsPresentFlag) &&
1048                 (m_vvcPicParams->m_phCbBetaOffsetDiv2 != cbBetaOffsetDiv2 ||
1049                     m_vvcPicParams->m_phCbTcOffsetDiv2 != cbTcOffsetDiv2 ||
1050                     m_vvcPicParams->m_phCrBetaOffsetDiv2 != crBetaOffsetDiv2 ||
1051                     m_vvcPicParams->m_phCrTcOffsetDiv2 != crTcOffsetDiv2))
1052             {
1053                 DECODE_ASSERTMESSAGE(
1054                     "Error concealed: force the following since (pps_dbf_info_in_ph_flag == 0 || ph_deblocking_filter_disabled_flag == 1 || pps_chroma_tool_offsets_present_flag == 0) is true: \n\
1055                 ph_cb_beta_offset_div2  = pps_chroma_tool_offsets_present_flag == 1? pps_cb_beta_offset_div2 : ph_luma_beta_offset_div2;\n\
1056                 ph_cb_tc_offset_div2    = pps_chroma_tool_offsets_present_flag == 1? pps_cb_tc_offset_div2 : ph_luma_tc_offset_div2;\n\
1057                 ph_cr_beta_offset_div2  = pps_chroma_tool_offsets_present_flag == 1 ? pps_cr_beta_offset_div2 : ph_luma_beta_offset_div2;\n\
1058                 ph_cr_tc_offset_div2    = pps_chroma_tool_offsets_present_flag == 1 ? pps_cr_tc_offset_div2 : ph_luma_tc_offset_div2;\n");
1059                 m_vvcPicParams->m_phCbBetaOffsetDiv2 = cbBetaOffsetDiv2;
1060                 m_vvcPicParams->m_phCbTcOffsetDiv2   = cbTcOffsetDiv2;
1061                 m_vvcPicParams->m_phCrBetaOffsetDiv2 = crBetaOffsetDiv2;
1062                 m_vvcPicParams->m_phCrTcOffsetDiv2   = crTcOffsetDiv2;
1063             }
1064         }
1065         // detection + concealment for slice duplication + reorder for Long Format decoding
1066         if (!m_shortFormatInUse)
1067         {
1068             DECODE_CHK_STATUS(SliceErrorHandlingLF());
1069         }
1070 
1071         return MOS_STATUS_SUCCESS;
1072     }
1073 
SetRequiredBitstreamSize(uint32_t requiredSize)1074     MOS_STATUS VvcBasicFeature::SetRequiredBitstreamSize(uint32_t requiredSize)
1075     {
1076         DECODE_FUNC_CALL();
1077         if (requiredSize > m_dataSize)
1078         {
1079             m_dataOffset = 0;
1080             m_dataSize   = MOS_ALIGN_CEIL(requiredSize, CODEC_BITSTREAM_ALIGN_SIZE_VVC);
1081         }
1082         DECODE_NORMALMESSAGE("Estimate bitstream size in this Frame: %u", requiredSize);
1083         return MOS_STATUS_SUCCESS;
1084     }
1085 
GetSubPicIdxFromSubPicId(uint16_t subPicId)1086     int16_t VvcBasicFeature::GetSubPicIdxFromSubPicId(uint16_t subPicId)
1087     {
1088         DECODE_FUNC_CALL();
1089 
1090         if (m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag &&
1091             m_vvcPicParams->m_spsNumSubpicsMinus1 > 0)
1092         {
1093             DECODE_CHK_NULL(m_subPicParams);
1094 
1095             for (int16_t idx = 0; idx < m_vvcPicParams->m_spsNumSubpicsMinus1 + 1; idx++)
1096             {
1097                 if(m_subPicParams[idx].m_subpicIdVal == subPicId)
1098                 {
1099                     return idx;
1100                 }
1101             }
1102         }
1103 
1104         return 0;
1105     }
1106 
SetSubPicStruct()1107     MOS_STATUS VvcBasicFeature::SetSubPicStruct()
1108     {
1109         DECODE_FUNC_CALL();
1110 
1111         DECODE_CHK_NULL(m_vvcPicParams);
1112         DECODE_CHK_NULL(m_subPicParams);
1113 
1114         if (m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag && m_vvcPicParams->m_spsNumSubpicsMinus1 > 0)
1115         {
1116             DECODE_CHK_NULL(m_subPicParams);
1117             DECODE_CHK_COND(m_vvcPicParams->m_spsNumSubpicsMinus1 >= vvcMaxSubpicNum, "Error detected: subpic number out of range!\n");
1118 
1119             MOS_ZeroMemory(m_sliceIdxInPicScanOrder, sizeof(m_sliceIdxInPicScanOrder));
1120             uint32_t accNumCtu = 0;
1121             for (auto i = 0; i < m_vvcPicParams->m_spsNumSubpicsMinus1 + 1; i++)
1122             {
1123                 CodecVvcSubpicParam* subPic = &m_subPicParams[i];
1124                 subPic->m_endCtbX = subPic->m_spsSubpicCtuTopLeftX + subPic->m_spsSubpicWidthMinus1;
1125                 subPic->m_endCtbY = subPic->m_spsSubpicCtuTopLeftY + subPic->m_spsSubpicHeightMinus1;
1126                 subPic->m_numSlices = 0;
1127                 subPic->m_sliceIdx = &m_sliceIdxInPicScanOrder[0];
1128 
1129                 accNumCtu += (subPic->m_spsSubpicWidthMinus1 + 1) * (subPic->m_spsSubpicHeightMinus1 + 1);
1130                 DECODE_CHK_COND(subPic->m_endCtbX > m_picWidthInCtu - 1, "Error detected: subpic hor boundary out of pic!\n");
1131                 DECODE_CHK_COND(subPic->m_endCtbY > m_picHeightInCtu - 1, "Error detected: subpic vert boundary out of pic!\n");
1132             }
1133             DECODE_CHK_COND(accNumCtu != m_picWidthInCtu * m_picHeightInCtu, "Error detected: subpictures have gap/overlap!\n");
1134         }
1135 
1136         return MOS_STATUS_SUCCESS;
1137     }
1138 
ReconstructTile()1139     MOS_STATUS VvcBasicFeature::ReconstructTile()
1140     {
1141         DECODE_FUNC_CALL();
1142 
1143         MOS_ZeroMemory(m_tileRow, sizeof(m_tileRow));
1144         MOS_ZeroMemory(m_tileCol, sizeof(m_tileCol));
1145 
1146         uint16_t accWidth = 0, accHeight = 0;
1147         uint16_t col = 0, row = 0;
1148         uint16_t ctuSize = 1 << (m_vvcPicParams->m_spsLog2CtuSizeMinus5 + 5);
1149 
1150         //column
1151         for (col = 0; col <= m_vvcPicParams->m_ppsNumExpTileColumnsMinus1; col++)
1152         {
1153             m_tileCol[col].m_startCtbX = accWidth;
1154             m_tileCol[col].m_widthInCtb = m_tileParams[col].m_tileDimension + 1;
1155             m_tileCol[col].m_endCtbX = m_tileCol[col].m_startCtbX + m_tileCol[col].m_widthInCtb - 1;
1156             accWidth += m_tileParams[col].m_tileDimension + 1;
1157             DECODE_CHK_COND(accWidth > m_picWidthInCtu, "Error Detected: Tile hor boundary out of pic.\n");
1158         }
1159 
1160         uint16_t uniformWidthInCtb = m_tileParams[m_vvcPicParams->m_ppsNumExpTileColumnsMinus1].m_tileDimension + 1;
1161         for (; accWidth + uniformWidthInCtb <= m_picWidthInCtu; col++)
1162         {
1163             m_tileCol[col].m_startCtbX = accWidth;
1164             m_tileCol[col].m_widthInCtb = uniformWidthInCtb;
1165             m_tileCol[col].m_endCtbX = m_tileCol[col].m_startCtbX + m_tileCol[col].m_widthInCtb - 1;
1166             accWidth += uniformWidthInCtb;
1167         }
1168         if (accWidth < m_picWidthInCtu)
1169         {
1170             m_tileCol[col].m_startCtbX = accWidth;
1171             m_tileCol[col].m_widthInCtb = m_picWidthInCtu - accWidth;
1172             m_tileCol[col].m_endCtbX = m_picWidthInCtu - 1;
1173             col++;
1174         }
1175 
1176         m_tileCols = col;
1177         DECODE_CHK_COND(m_tileCols > vvcMaxTileColNum || m_tileCols == 0, "Error detected: tile column number out of range!\n");
1178 
1179         // row
1180         for (row = 0; row <= m_vvcPicParams->m_ppsNumExpTileRowsMinus1; row++)
1181         {
1182             m_tileRow[row].m_startCtbY   = accHeight;
1183             m_tileRow[row].m_heightInCtb = m_tileParams[m_vvcPicParams->m_ppsNumExpTileColumnsMinus1 + 1 + row].m_tileDimension + 1;
1184             m_tileRow[row].m_endCtbY     = m_tileRow[row].m_startCtbY + m_tileRow[row].m_heightInCtb - 1;
1185             accHeight += m_tileParams[m_vvcPicParams->m_ppsNumExpTileColumnsMinus1 + 1 + row].m_tileDimension + 1;
1186             DECODE_CHK_COND(accHeight > m_picHeightInCtu, "Error Detected: Tile vert boundary out of pic.\n");
1187         }
1188         uint16_t lastIdx = m_vvcPicParams->m_ppsNumExpTileRowsMinus1 + m_vvcPicParams->m_ppsNumExpTileColumnsMinus1 + 1;
1189         uint16_t uniformHeightInCtb = m_tileParams[lastIdx].m_tileDimension + 1;
1190         for (; accHeight + uniformHeightInCtb <= m_picHeightInCtu; row++)
1191         {
1192             m_tileRow[row].m_startCtbY   = accHeight;
1193             m_tileRow[row].m_heightInCtb = uniformHeightInCtb;
1194             m_tileRow[row].m_endCtbY     = m_tileRow[row].m_startCtbY + m_tileRow[row].m_heightInCtb - 1;
1195             accHeight += uniformHeightInCtb;
1196         }
1197         if (accHeight < m_picHeightInCtu)
1198         {
1199             m_tileRow[row].m_startCtbY = accHeight;
1200             m_tileRow[row].m_heightInCtb = m_picHeightInCtu - accHeight;
1201             m_tileRow[row].m_endCtbY = m_picHeightInCtu - 1;
1202             row++;
1203         }
1204         m_tileRows = row;
1205         DECODE_CHK_COND((m_tileRows * m_tileCols > vvcMaxTileNum) || m_tileRows == 0, "Error detected: tile number out of range!\n");
1206 
1207         m_maxTileWidth = 0;
1208         for (col = 0; col <= m_vvcPicParams->m_ppsNumExpTileColumnsMinus1; col++)
1209         {
1210             if (m_tileParams[col].m_tileDimension + 1 > m_maxTileWidth)
1211             {
1212                 m_maxTileWidth = m_tileParams[col].m_tileDimension + 1;
1213             }
1214         }
1215 
1216         if (((ctuSize == vvcCtu32) && (m_maxTileWidth > vvcMaxTileWCtb32)) ||
1217             ((ctuSize == vvcCtu64) && (m_maxTileWidth > vvcMaxTileWCtb64)) ||
1218             ((ctuSize == vvcCtu128) && (m_maxTileWidth > vvcMaxTileWCtb128)))
1219         {
1220             DECODE_ASSERTMESSAGE("Tile width exceeds maximum allowed value.\n");
1221             return MOS_STATUS_INVALID_PARAMETER;
1222         }
1223 
1224         return MOS_STATUS_SUCCESS;
1225     }
1226 
ReconstructSlice()1227     MOS_STATUS VvcBasicFeature::ReconstructSlice()
1228     {
1229         DECODE_FUNC_CALL();
1230 
1231         DECODE_CHK_NULL(m_vvcPicParams);
1232         DECODE_CHK_NULL(m_vvcSliceParams);
1233 
1234         MOS_ZeroMemory(m_sliceDesc, sizeof(m_sliceDesc));
1235 
1236         // Partition - reconstruct Slices
1237         if (!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRectSliceFlag)
1238         {
1239             //Category1: Raster Scan Slice
1240             uint16_t col, row;
1241             for (uint32_t i = 0; i < m_numSlices; i++)
1242             {
1243                 uint16_t start = m_vvcSliceParams[i].m_shSliceAddress;
1244                 uint16_t end = start + m_vvcSliceParams[i].m_shNumTilesInSliceMinus1;
1245 
1246                 uint32_t numCtus = 0;
1247                 for (auto idx = start; idx <= end; idx++)
1248                 {
1249                     col = idx % m_tileCols;
1250                     row = idx / m_tileCols;
1251 
1252                     numCtus += m_tileCol[col].m_widthInCtb * m_tileRow[row].m_heightInCtb;
1253                 }
1254                 m_sliceDesc[i].m_numCtusInCurrSlice = numCtus;
1255 
1256                 col = start % m_tileCols;
1257                 row = start / m_tileCols;
1258                 m_sliceDesc[i].m_startTileX     = col;
1259                 m_sliceDesc[i].m_startTileY     = row;
1260                 m_sliceDesc[i].m_sliceStartCtbx = m_tileCol[col].m_startCtbX;
1261                 m_sliceDesc[i].m_sliceStartCtby = m_tileRow[row].m_startCtbY;
1262             }
1263         }
1264         else if(!m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSingleSlicePerSubpicFlag)
1265         {
1266             // Category2: Most general rect slice case,  subpic v.s. slice partition is not the same
1267             DECODE_CHK_NULL(m_sliceStructParams);
1268 
1269             uint16_t tileIdx = 0;
1270             int32_t slcStructIdx = -1;//index to slice structure
1271             CodecVvcSliceStructure* slcStruct = nullptr;
1272             DECODE_ASSERT(m_sliceStructParams[0].m_sliceTopLeftTileIdx == 0);
1273 
1274             // Go through rectangular slice parameters
1275             int32_t i = 0;
1276             for( i = 0; i < m_vvcPicParams->m_ppsNumSlicesInPicMinus1; i++ )
1277             {
1278                 slcStructIdx++;
1279                 if (slcStructIdx > m_vvcPicParams->m_numSliceStructsMinus1)
1280                 {
1281                     DECODE_ASSERTMESSAGE("Incomplete slice structures received.\n");
1282                     return MOS_STATUS_INVALID_PARAMETER;
1283                 }
1284                 slcStruct = &m_sliceStructParams[slcStructIdx];
1285                 DECODE_CHK_COND(slcStruct->m_sliceTopLeftTileIdx >= m_tileCols * m_tileRows,"Error Detected: error slice structure params, SliceTopLeftTileIdx exceeds the max tile index in the picture!\n");
1286                 tileIdx = slcStruct->m_sliceTopLeftTileIdx;
1287                 m_sliceDesc[i].m_tileIdx = tileIdx;
1288 
1289                 // complete tiles within a single slice
1290                 DECODE_CHK_COND((tileIdx % m_tileCols) + slcStruct->m_ppsSliceWidthInTilesMinus1 >= m_tileCols, "Error Detected: rect slice right border exceeds picture boundary.\n");
1291                 DECODE_CHK_COND((tileIdx / m_tileCols) + slcStruct->m_ppsSliceHeightInTilesMinus1 >= m_tileRows, "Error Detected: rect slice bottom border exceeds picture boundary.\n");
1292                 m_sliceDesc[i].m_sliceWidthInTiles = slcStruct->m_ppsSliceWidthInTilesMinus1 + 1;
1293                 m_sliceDesc[i].m_sliceHeightInTiles = slcStruct->m_ppsSliceHeightInTilesMinus1 + 1;
1294 
1295                 // Derived variables on slice v.s. CTU
1296                 m_sliceDesc[i].m_sliceStartCtbx = m_tileCol[tileIdx % m_tileCols].m_startCtbX;
1297                 m_sliceDesc[i].m_sliceStartCtby = m_tileRow[tileIdx / m_tileCols].m_startCtbY;
1298 
1299                 // multiple slices within a single tile special case
1300                 if( m_sliceDesc[i].m_sliceWidthInTiles == 1 && m_sliceDesc[i].m_sliceHeightInTiles == 1)
1301                 {
1302                     if((m_tileRow[tileIdx/m_tileCols].m_heightInCtb == 1) ||
1303                         (slcStruct->m_ppsExpSliceHeightInCtusMinus1 + 1 == m_tileRow[tileIdx / m_tileCols].m_heightInCtb))
1304                     {
1305                         m_sliceDesc[i].m_numSlicesInTile = 1;
1306                         m_sliceDesc[i].m_sliceHeightInCtu = slcStruct->m_ppsExpSliceHeightInCtusMinus1 + 1;
1307                     }
1308                     else
1309                     {
1310                         uint16_t remTileRowHeight = m_tileRow[tileIdx / m_tileCols].m_heightInCtb;
1311                         int j = 0;
1312                         for (;;j++)
1313                         {
1314                             DECODE_CHK_COND(slcStruct->m_ppsExpSliceHeightInCtusMinus1 + 1 > remTileRowHeight || slcStruct->m_ppsExpSliceHeightInCtusMinus1 + 1 == 0, "Error Detected: Accumulated rect slice height of multiple slices in one tile case exceeds the tile height.\n");
1315                             m_sliceDesc[i+j].m_sliceHeightInCtu = slcStruct->m_ppsExpSliceHeightInCtusMinus1 + 1;
1316                             remTileRowHeight -= m_sliceDesc[i+j].m_sliceHeightInCtu;
1317 
1318                             slcStructIdx++;
1319                             if (slcStructIdx > m_vvcPicParams->m_numSliceStructsMinus1)
1320                             {
1321                                 slcStructIdx--;
1322                                 break;
1323                             }
1324                             slcStruct = &m_sliceStructParams[slcStructIdx];
1325                             if (slcStruct->m_sliceTopLeftTileIdx != tileIdx)
1326                             {
1327                                 slcStructIdx--;
1328                                 break;
1329                             }
1330                         }
1331 
1332                         uint16_t uniformSliceHeight = m_sliceDesc[i + j].m_sliceHeightInCtu;
1333 
1334                         uint16_t deriveNum = MOS_ROUNDUP_DIVIDE(remTileRowHeight, uniformSliceHeight);
1335                         DECODE_CHK_COND(i + j + deriveNum > m_vvcPicParams->m_ppsNumSlicesInPicMinus1, "Error detected: Derived slice index exceeds the the last slice index in pic!\n");
1336 
1337                         while( remTileRowHeight >= uniformSliceHeight )
1338                         {
1339                             j++;
1340                             m_sliceDesc[i + j].m_sliceHeightInCtu = uniformSliceHeight;
1341                             remTileRowHeight -= uniformSliceHeight;
1342                         }
1343                         if( remTileRowHeight > 0 )
1344                         {
1345                             j++;
1346                             m_sliceDesc[i + j].m_sliceHeightInCtu = remTileRowHeight;
1347                         }
1348 
1349                         for( int k = 0; k < j + 1; k++ )
1350                         {
1351                             m_sliceDesc[i + k].m_numSlicesInTile = j + 1;
1352                             m_sliceDesc[i + k].m_sliceWidthInTiles = 1;
1353                             m_sliceDesc[i + k].m_sliceHeightInTiles = 1;
1354                             m_sliceDesc[i + k].m_tileIdx = tileIdx;
1355 
1356                             //derived variables
1357                             if (k > 0)
1358                             {
1359                                 m_sliceDesc[i + k].m_sliceStartCtby = m_sliceDesc[i + k - 1].m_sliceStartCtby + m_sliceDesc[i + k - 1].m_sliceHeightInCtu;
1360                             }
1361                             m_sliceDesc[i + k].m_sliceStartCtbx = m_tileCol[tileIdx % m_tileCols].m_startCtbX;
1362                         }
1363                         m_sliceDesc[i].m_topSliceInTileFlag = 1;
1364                         m_sliceDesc[i + j].m_bottomSliceInTileFlag = 1;
1365                         i += j;
1366                     }
1367                 }
1368             }
1369 
1370             // The last slice not covered in multi-slice tile
1371             if (i == m_vvcPicParams->m_ppsNumSlicesInPicMinus1)
1372             {
1373                 slcStructIdx++;
1374                 if (slcStructIdx != m_vvcPicParams->m_numSliceStructsMinus1)
1375                 {
1376                     DECODE_ASSERTMESSAGE("Incorrect slice structures received.\n");
1377                     return MOS_STATUS_INVALID_PARAMETER;
1378                 }
1379                 slcStruct = &m_sliceStructParams[slcStructIdx];
1380                 m_sliceDesc[i].m_tileIdx = slcStruct->m_sliceTopLeftTileIdx;
1381 
1382                 //Derive other params
1383                 m_sliceDesc[i].m_numSlicesInTile    = 1;
1384                 m_sliceDesc[i].m_sliceStartCtbx     = m_tileCol[m_sliceDesc[i].m_tileIdx % m_tileCols].m_startCtbX;
1385                 m_sliceDesc[i].m_sliceStartCtby     = m_tileRow[m_sliceDesc[i].m_tileIdx / m_tileCols].m_startCtbY;
1386                 m_sliceDesc[i].m_sliceHeightInCtu   = m_picHeightInCtu - m_sliceDesc[i].m_sliceStartCtby;
1387                 m_sliceDesc[i].m_sliceHeightInTiles = m_tileRows - (m_sliceDesc[i].m_tileIdx / m_tileCols);
1388                 m_sliceDesc[i].m_sliceWidthInTiles  = m_tileCols - (m_sliceDesc[i].m_tileIdx % m_tileCols);
1389             }
1390 
1391             //Derived variables on SubPic v.s. Slice
1392             if (m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag && m_vvcPicParams->m_spsNumSubpicsMinus1 > 0)
1393             {
1394                 for (auto slc = 0; slc < m_vvcPicParams->m_ppsNumSlicesInPicMinus1 + 1; slc++)
1395                 {
1396                     for (uint16_t sp = 0; sp < m_vvcPicParams->m_spsNumSubpicsMinus1 + 1; sp++)
1397                     {
1398                         if ((m_sliceDesc[slc].m_sliceStartCtbx >= m_subPicParams[sp].m_spsSubpicCtuTopLeftX) &&
1399                             (m_sliceDesc[slc].m_sliceStartCtbx <= m_subPicParams[sp].m_endCtbX) &&
1400                             (m_sliceDesc[slc].m_sliceStartCtby >= m_subPicParams[sp].m_spsSubpicCtuTopLeftY) &&
1401                             (m_sliceDesc[slc].m_sliceStartCtby <= m_subPicParams[sp].m_endCtbY))
1402                         {
1403                             m_sliceDesc[slc].m_subPicIdx = sp;
1404                             m_sliceDesc[slc].m_sliceIdxInSubPic = m_subPicParams[sp].m_numSlices;
1405 
1406                             m_subPicParams[sp].m_numSlices++;
1407 
1408                             break;
1409                         }
1410                     }
1411                 }
1412                 int32_t accSlice = 0;
1413                 for (auto sp = 0; sp < m_vvcPicParams->m_spsNumSubpicsMinus1 + 1; sp++)
1414                 {
1415                     m_subPicParams[sp].m_sliceIdx = &m_sliceIdxInPicScanOrder[accSlice];
1416                     accSlice += m_subPicParams[sp].m_numSlices;
1417                 }
1418                 for (auto sp = 0; sp < m_vvcPicParams->m_spsNumSubpicsMinus1 + 1; sp++)
1419                 {
1420                     m_subPicParams[sp].m_numSlices = 0;
1421                 }
1422                 for (uint16_t slc = 0; slc < m_vvcPicParams->m_ppsNumSlicesInPicMinus1 + 1; slc++)
1423                 {
1424                     int32_t sp = m_sliceDesc[slc].m_subPicIdx;
1425 
1426                     m_subPicParams[sp].m_numSlices++;
1427                     m_subPicParams[sp].m_sliceIdx[m_subPicParams[sp].m_numSlices - 1] = slc;
1428                 }
1429             }
1430 
1431             for (uint16_t slc = 0; slc < m_vvcPicParams->m_ppsNumSlicesInPicMinus1 + 1; slc++)
1432             {
1433                 //Derive other params
1434                 m_sliceDesc[slc].m_multiSlicesInTileFlag = (m_sliceDesc[slc].m_numSlicesInTile > 1) ? 1 : 0;
1435                 m_sliceDesc[slc].m_startTileX = m_sliceDesc[slc].m_tileIdx % m_tileCols;
1436                 m_sliceDesc[slc].m_startTileY = m_sliceDesc[slc].m_tileIdx / m_tileCols;
1437 
1438                 uint16_t startTile = 0;
1439                 uint16_t endTile = 0;
1440                 uint16_t sliceWidthInCtu = 0;
1441                 uint16_t sliceHeightInCtu = 0;
1442                 if (m_sliceDesc[slc].m_numSlicesInTile > 1)
1443                 {
1444                     startTile = m_sliceDesc[slc].m_startTileX;
1445                     sliceWidthInCtu = m_tileCol[startTile].m_widthInCtb;
1446                     sliceHeightInCtu = m_sliceDesc[slc].m_sliceHeightInCtu;
1447                 }
1448                 else
1449                 {
1450                     startTile = m_sliceDesc[slc].m_startTileX;
1451                     endTile = m_sliceDesc[slc].m_sliceWidthInTiles + startTile - 1;
1452                     sliceWidthInCtu = m_tileCol[endTile].m_endCtbX + 1 - m_tileCol[startTile].m_startCtbX;
1453 
1454                     startTile = m_sliceDesc[slc].m_startTileY;
1455                     endTile = m_sliceDesc[slc].m_sliceHeightInTiles + startTile - 1;
1456                     sliceHeightInCtu = m_tileRow[endTile].m_endCtbY + 1 - m_tileRow[startTile].m_startCtbY;
1457                     m_sliceDesc[slc].m_sliceHeightInCtu = sliceHeightInCtu;
1458                 }
1459                 m_sliceDesc[slc].m_numCtusInCurrSlice = sliceWidthInCtu * sliceHeightInCtu;
1460             }
1461         }
1462         else if(m_vvcPicParams->m_ppsFlags.m_fields.m_ppsSingleSlicePerSubpicFlag)
1463         {
1464             //Category3/4: slice & subpic have the same partition
1465             if (m_vvcPicParams->m_spsNumSubpicsMinus1 == 0 || !m_vvcPicParams->m_spsFlags0.m_fields.m_spsSubpicInfoPresentFlag)
1466             {
1467                 //Category4: only one slice/subpic
1468                 m_sliceDesc[0].m_numCtusInCurrSlice     = m_picWidthInCtu * m_picHeightInCtu;
1469                 m_sliceDesc[0].m_tileIdx                = 0;
1470                 m_sliceDesc[0].m_sliceWidthInTiles      = m_tileCols;
1471                 m_sliceDesc[0].m_sliceHeightInTiles     = m_tileRows;
1472                 m_sliceDesc[0].m_numSlicesInTile        = 1;
1473                 m_sliceDesc[0].m_sliceHeightInCtu       = m_picHeightInCtu;
1474                 m_sliceDesc[0].m_sliceStartCtbx         = 0;
1475                 m_sliceDesc[0].m_sliceStartCtby         = 0;
1476                 m_sliceDesc[0].m_subPicIdx              = 0;
1477                 m_sliceDesc[0].m_sliceIdxInSubPic       = 0;
1478                 m_sliceDesc[0].m_multiSlicesInTileFlag  = 0;
1479                 m_sliceDesc[0].m_startTileX             = 0;
1480                 m_sliceDesc[0].m_startTileY             = 0;
1481             }
1482             else
1483             {
1484                 //Category3: multiple slice/subpic
1485                 uint16_t startCtu = 0, endCtu = 0;
1486                 int16_t startTileX = 0, startTileY = 0, endTile = 0;
1487                 for (uint16_t i = 0; i < m_vvcPicParams->m_spsNumSubpicsMinus1 + 1; i++)
1488                 {
1489                     startCtu   = m_subPicParams[i].m_spsSubpicCtuTopLeftX;
1490                     endCtu     = m_subPicParams[i].m_endCtbX;
1491                     m_sliceDesc[i].m_sliceWidthInTiles = GetSubpicWidthInTile(startCtu, endCtu, startTileX, endTile);
1492 
1493                     if ((m_sliceDesc[i].m_sliceWidthInTiles == -1) || (startTileX == -1) || (endTile == -1))
1494                     {
1495                         DECODE_ASSERTMESSAGE("Incorrect derived results.\n");
1496                         return MOS_STATUS_INVALID_PARAMETER;
1497                     }
1498 
1499                     startCtu    = m_subPicParams[i].m_spsSubpicCtuTopLeftY;
1500                     endCtu      = m_subPicParams[i].m_endCtbY;
1501                     m_sliceDesc[i].m_sliceHeightInTiles = GetSubpicHeightInTile(startCtu, endCtu, startTileY, endTile);
1502 
1503                     if ((m_sliceDesc[i].m_sliceHeightInTiles == -1) || (startTileY == -1) || (endTile == -1))
1504                     {
1505                         DECODE_ASSERTMESSAGE("Incorrect derived results.\n");
1506                         return MOS_STATUS_INVALID_PARAMETER;
1507                     }
1508 
1509                     if (m_sliceDesc[i].m_sliceHeightInTiles == 1 &&
1510                         m_subPicParams[i].m_spsSubpicHeightMinus1 + 1 < m_tileRow[startTileY].m_heightInCtb)
1511                     {
1512                         m_sliceDesc[i].m_multiSlicesInTileFlag = 1;
1513                         m_sliceDesc[i].m_topSliceInTileFlag    = (startCtu == m_tileRow[startTileY].m_startCtbY) ? true : false;
1514                         m_sliceDesc[i].m_bottomSliceInTileFlag = (endCtu == m_tileRow[endTile].m_endCtbY) ? true : false;
1515                     }
1516                     else
1517                     {
1518                         m_sliceDesc[i].m_multiSlicesInTileFlag = 0;
1519                         m_sliceDesc[i].m_topSliceInTileFlag    = 0;
1520                         m_sliceDesc[i].m_bottomSliceInTileFlag = 0;
1521                     }
1522 
1523                     m_sliceDesc[i].m_startTileX         = startTileX;
1524                     m_sliceDesc[i].m_startTileY         = startTileY;
1525                     m_sliceDesc[i].m_tileIdx            = startTileX + startTileY * m_tileCols;
1526                     m_sliceDesc[i].m_sliceHeightInCtu   = m_subPicParams[i].m_spsSubpicHeightMinus1 + 1;
1527                     m_sliceDesc[i].m_sliceStartCtbx     = m_subPicParams[i].m_spsSubpicCtuTopLeftX;
1528                     m_sliceDesc[i].m_sliceStartCtby     = m_subPicParams[i].m_spsSubpicCtuTopLeftY;
1529                     m_sliceDesc[i].m_subPicIdx          = i;
1530                     m_sliceDesc[i].m_sliceIdxInSubPic   = 0;
1531 
1532                     //Derive other params
1533                     m_sliceDesc[i].m_numCtusInCurrSlice = (m_subPicParams[i].m_spsSubpicHeightMinus1 + 1) * (m_subPicParams[i].m_spsSubpicWidthMinus1 + 1);
1534                     m_sliceDesc[i].m_numSlicesInTile    = 0;
1535                     m_subPicParams[i].m_sliceIdx        = &m_sliceIdxInPicScanOrder[i];
1536                     m_subPicParams[i].m_sliceIdx[0]     = i;
1537                     m_subPicParams[i].m_numSlices       = 1;
1538                 }
1539             }
1540         }
1541 
1542         return MOS_STATUS_SUCCESS;
1543     }
1544 
ReconstructPartition(CodechalDecodeParams * decodeParams)1545     MOS_STATUS VvcBasicFeature::ReconstructPartition(CodechalDecodeParams* decodeParams)
1546     {
1547         DECODE_FUNC_CALL();
1548 
1549         DECODE_CHK_NULL(m_vvcPicParams);
1550         DECODE_CHK_NULL(m_vvcSliceParams);
1551 
1552         // Tile
1553         DECODE_CHK_STATUS(ReconstructTile());
1554 
1555         // SubPic
1556         DECODE_CHK_STATUS(SetSubPicStruct());
1557 
1558         // Slice
1559         DECODE_CHK_STATUS(ReconstructSlice());
1560 
1561         return MOS_STATUS_SUCCESS;
1562     }
1563 
SetPictureStructs(CodechalDecodeParams * decodeParams)1564     MOS_STATUS VvcBasicFeature::SetPictureStructs(CodechalDecodeParams *decodeParams)
1565     {
1566         DECODE_FUNC_CALL();
1567 
1568         m_curRenderPic                  = m_vvcPicParams->m_currPic;
1569         m_width                         = (uint32_t)m_vvcPicParams->m_ppsPicWidthInLumaSamples;
1570         m_height                        = (uint32_t)m_vvcPicParams->m_ppsPicHeightInLumaSamples;
1571         m_picWidthInCtu                 = MOS_ROUNDUP_SHIFT(m_vvcPicParams->m_ppsPicWidthInLumaSamples, m_vvcPicParams->m_spsLog2CtuSizeMinus5 + 5);
1572         m_picHeightInCtu                = MOS_ROUNDUP_SHIFT(m_vvcPicParams->m_ppsPicHeightInLumaSamples, m_vvcPicParams->m_spsLog2CtuSizeMinus5 + 5);
1573         m_frameWidthAlignedMinBlk       = MOS_ALIGN_CEIL(m_vvcPicParams->m_ppsPicWidthInLumaSamples, vvcMinBlockWidth);
1574         m_frameHeightAlignedMinBlk      = MOS_ALIGN_CEIL(m_vvcPicParams->m_ppsPicHeightInLumaSamples, vvcMinBlockHeight);
1575 
1576         m_refFrameIndexList.clear();
1577         for (auto i = 0; i < vvcMaxNumRefFrame; i++)
1578         {
1579             uint8_t index = m_vvcPicParams->m_refFrameList[i].FrameIdx;
1580             if (index < CODEC_MAX_DPB_NUM_VVC)
1581             {
1582                 m_refFrameIndexList.push_back(index);
1583             }
1584         }
1585 
1586         DECODE_CHK_STATUS(m_refFrames.UpdatePicture(*m_vvcPicParams));
1587         DECODE_CHK_STATUS(m_mvBuffers.UpdatePicture(m_vvcPicParams->m_currPic.FrameIdx, m_refFrameIndexList));
1588 
1589         m_pictureCodingType = m_vvcPicParams->m_picMiscFlags.m_fields.m_intraPicFlag ? I_TYPE : MIXED_TYPE;
1590 
1591         return MOS_STATUS_SUCCESS;
1592     }
1593 
UpdateNumRefForList()1594     MOS_STATUS VvcBasicFeature::UpdateNumRefForList()
1595     {
1596         DECODE_FUNC_CALL();
1597         if (m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRplInfoInPhFlag > 0)
1598         {
1599             //List0:
1600             if (!m_vvcPicParams->m_phFlags.m_fields.m_rplSpsFlag0)
1601             {
1602                 m_numRefForList0 = m_rplParams[vvcPhRpl0Offset].m_numRefEntries;
1603             }
1604             else
1605             {
1606                 m_numRefForList0 = m_rplParams[m_vvcPicParams->m_rplSpsIndex0].m_numRefEntries;
1607             }
1608             //List1:
1609             if (!m_vvcPicParams->m_phFlags.m_fields.m_rplSpsFlag1)
1610             {
1611                 m_numRefForList1 = m_rplParams[vvcPhRpl1Offset].m_numRefEntries;
1612             }
1613             else
1614             {
1615                 m_numRefForList1 = m_rplParams[m_vvcPicParams->m_rplSpsIndex1 + vvcSpsCandidateRpl1Offset].m_numRefEntries;
1616             }
1617         }
1618 
1619         if (m_vvcPicParams->m_phFlags.m_fields.m_phInterSliceAllowedFlag && m_vvcPicParams->m_ppsFlags.m_fields.m_ppsRplInfoInPhFlag)
1620         {
1621             m_vvcPicParams->m_phFlags.m_fields.m_numRefEntries0RplIdx0LargerThan0 = m_numRefForList0 > 0 ? 1 : 0;
1622             m_vvcPicParams->m_phFlags.m_fields.m_numRefEntries1RplIdx1LargerThan0 = m_numRefForList1 > 0 ? 1 : 0;
1623         }
1624 
1625         return MOS_STATUS_SUCCESS;
1626     }
1627 
GetSubpicWidthInTile(uint16_t startCtu,uint16_t endCtu,int16_t & startTile,int16_t & endTile)1628     int16_t VvcBasicFeature::GetSubpicWidthInTile(uint16_t startCtu, uint16_t endCtu, int16_t &startTile, int16_t &endTile)
1629     {
1630         DECODE_FUNC_CALL();
1631 
1632         if ((endCtu < startCtu) ||
1633             (endCtu > m_picWidthInCtu) ||
1634             (startCtu > m_picWidthInCtu))
1635         {
1636             DECODE_ASSERT(endCtu >= startCtu);
1637         }
1638 
1639         startTile = -1;
1640         for (int16_t i = 0; i < m_tileCols; i++)
1641         {
1642             if (startCtu >= m_tileCol[i].m_startCtbX && startCtu <= m_tileCol[i].m_endCtbX)
1643             {
1644                 startTile = i;
1645                 break;
1646             }
1647         }
1648 
1649         endTile = -1;
1650         if ((startTile > -1))
1651         {
1652             for (int16_t i = startTile; i < m_tileCols; i++)
1653             {
1654                 if (endCtu >= m_tileCol[i].m_startCtbX && endCtu <= m_tileCol[i].m_endCtbX)
1655                 {
1656                     endTile = i;
1657                     break;
1658                 }
1659             }
1660         }
1661 
1662         return ((endTile > -1) ? (endTile + 1 - startTile) : 1);
1663     }
1664 
GetSubpicHeightInTile(uint16_t startCtu,uint16_t endCtu,int16_t & startTile,int16_t & endTile)1665     int16_t VvcBasicFeature::GetSubpicHeightInTile(uint16_t startCtu, uint16_t endCtu, int16_t &startTile, int16_t &endTile)
1666     {
1667         DECODE_FUNC_CALL();
1668 
1669         if ((endCtu < startCtu) ||
1670             (endCtu > m_picHeightInCtu) ||
1671             (startCtu > m_picHeightInCtu))
1672         {
1673             DECODE_ASSERT(endCtu >= startCtu);
1674         }
1675 
1676         startTile = -1;
1677         for (int16_t i = 0; i < m_tileRows; i++)
1678         {
1679             if (startCtu >= m_tileRow[i].m_startCtbY && startCtu <= m_tileRow[i].m_endCtbY)
1680             {
1681                 startTile = i;
1682                 break;
1683             }
1684         }
1685 
1686         endTile = -1;
1687         if ((startTile > -1))
1688         {
1689             for (int16_t i = startTile; i < m_tileRows; i++)
1690             {
1691                 if (endCtu >= m_tileRow[i].m_startCtbY && endCtu <= m_tileRow[i].m_endCtbY)
1692                 {
1693                     endTile = i;
1694                     break;
1695                 }
1696             }
1697         }
1698 
1699         return ((endTile > -1) ? (endTile + 1 - startTile) : 1);
1700     }
1701 
1702 }  // namespace decode
1703