1 /*
2 * Copyright (c) 2019-2022, 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_hevc_basic_feature.cpp
24 //! \brief    Defines the common interface for decode hevc parameter
25 //!
26 
27 #include <set>
28 #include "decode_hevc_basic_feature.h"
29 #include "decode_utils.h"
30 #include "decode_allocator.h"
31 
32 namespace decode
33 {
34 
Init(void * setting)35 MOS_STATUS HevcBasicFeature::Init(void *setting)
36 {
37     DECODE_FUNC_CALL();
38     DECODE_CHK_NULL(setting);
39     DECODE_CHK_NULL(m_hwInterface);
40 
41     m_shortFormatInUse = ((CodechalSetting*)setting)->shortFormatInUse;
42 
43     DECODE_CHK_STATUS(DecodeBasicFeature::Init(setting));
44 
45     DECODE_CHK_STATUS(m_refFrames.Init(this, *m_allocator));
46     DECODE_CHK_STATUS(m_mvBuffers.Init(m_hwInterface, *m_allocator, *this,
47                                        CODEC_NUM_HEVC_INITIAL_MV_BUFFERS));
48     DECODE_CHK_STATUS(m_tileCoding.Init(this, (CodechalSetting*)setting));
49 
50     return MOS_STATUS_SUCCESS;
51 }
52 
~HevcBasicFeature()53 HevcBasicFeature::~HevcBasicFeature()
54 {
55     if (m_allocator != nullptr)
56     {
57         m_allocator->Destroy(m_referenceBeforeLoopFilter);
58     }
59 }
60 
Update(void * params)61 MOS_STATUS HevcBasicFeature::Update(void *params)
62 {
63     DECODE_FUNC_CALL();
64 
65     PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL);
66 
67     DECODE_CHK_NULL(params);
68 
69     DECODE_CHK_STATUS(DecodeBasicFeature::Update(params));
70 
71     CodechalDecodeParams* decodeParams = (CodechalDecodeParams*)params;
72     DECODE_CHK_NULL(decodeParams->m_picParams);
73     DECODE_CHK_NULL(decodeParams->m_sliceParams);
74     DECODE_CHK_NULL(decodeParams->m_iqMatrixBuffer);
75 
76     m_hevcPicParams      = static_cast<PCODEC_HEVC_PIC_PARAMS>(decodeParams->m_picParams);
77     m_hevcSliceParams    = static_cast<PCODEC_HEVC_SLICE_PARAMS>(decodeParams->m_sliceParams);
78     m_hevcIqMatrixParams = static_cast<PCODECHAL_HEVC_IQ_MATRIX_PARAMS>(decodeParams->m_iqMatrixBuffer);
79 
80     m_hevcRextPicParams  = static_cast<PCODEC_HEVC_EXT_PIC_PARAMS>(decodeParams->m_extPicParams);
81     m_hevcRextSliceParams= static_cast<PCODEC_HEVC_EXT_SLICE_PARAMS>(decodeParams->m_extSliceParams);
82     m_hevcSccPicParams   = static_cast<PCODEC_HEVC_SCC_PIC_PARAMS>(decodeParams->m_advPicParams);
83     m_hevcSubsetParams   = static_cast<PCODEC_HEVC_SUBSET_PARAMS>(decodeParams->m_subsetParams);
84 
85     DECODE_CHK_STATUS(SetPictureStructs());
86     DECODE_CHK_STATUS(SetSliceStructs());
87 
88     return MOS_STATUS_SUCCESS;
89 }
90 
ErrorDetectAndConceal()91 MOS_STATUS HevcBasicFeature::ErrorDetectAndConceal()
92 {
93 
94     DECODE_FUNC_CALL();
95 
96     DECODE_CHK_COND(m_curRenderPic.FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC,
97         "currPic.FrameIdx is out of range!");
98 
99     DECODE_CHK_COND(m_hevcPicParams->PicHeightInMinCbsY == 0 || m_hevcPicParams->PicWidthInMinCbsY == 0,
100         "picture Weight/Height equals to 0!");
101 
102     // check LCU size
103     // LCU is restricted based on the picture size.
104     // LCU 16x16 can only be used with picture width and height both fewer than or equal to 4222 pixels
105     if (m_width > CODECHAL_HEVC_MAX_DIM_FOR_MIN_LCU ||
106         m_height > CODECHAL_HEVC_MAX_DIM_FOR_MIN_LCU)
107     {
108         DECODE_CHK_COND(m_ctbSize == CODECHAL_HEVC_MIN_LCU, "Invalid LCU size.");
109     }
110 
111     // Todo: The maximum support picture size is 16384 pixels for both encoder and decoder.
112     // check if slice number is valid
113     DECODE_CHK_COND(m_numSlices > CODECHAL_HEVC_MAX_NUM_SLICES_LVL_6 || m_numSlices == 0,
114         "slice number is out of range!");
115 
116     // check if min CtbSize is valid
117     if (!(m_minCtbSize == 8 || m_minCtbSize == 16 || m_minCtbSize == 32 || m_minCtbSize == 64))
118     {
119         DECODE_ASSERTMESSAGE("MinCtbSize is invalid\n");
120         return MOS_STATUS_INVALID_PARAMETER;
121     }
122 
123     // check if CtbSize is valid
124     if (!(m_ctbSize == 16 || m_ctbSize == 32 || m_ctbSize == 64))
125     {
126         DECODE_ASSERTMESSAGE("CtbSize is invalid\n");
127         return MOS_STATUS_INVALID_PARAMETER;
128     }
129 
130     if (m_hevcPicParams->tiles_enabled_flag)
131     {
132         // check if tile_columns and tile_rows is valid
133         DECODE_CHK_COND((m_hevcPicParams->num_tile_columns_minus1 + 1 > HEVC_NUM_MAX_TILE_COLUMN) ||
134                             (m_hevcPicParams->num_tile_rows_minus1 + 1 > HEVC_NUM_MAX_TILE_ROW),
135             "num_tile_columns_minus1 or num_tile_rows_minus1 is out of range!");
136 
137         // valid range is [0, m_widthInCtb - 1]
138         if (m_hevcPicParams->num_tile_columns_minus1 > m_widthInCtb - 1)
139         {
140             DECODE_ASSERTMESSAGE("num_tile_columns_minus1 out of range: %d\n",
141                 m_hevcPicParams->num_tile_columns_minus1);
142 
143             return MOS_STATUS_INVALID_PARAMETER;
144         }
145 
146         // valid range is [0, m_heightInCtb - 1]
147         if (m_hevcPicParams->num_tile_rows_minus1 > m_heightInCtb - 1)
148         {
149             DECODE_ASSERTMESSAGE("num_tile_rows_minus1 out of range: %d\n",
150                 m_hevcPicParams->num_tile_rows_minus1);
151 
152             return MOS_STATUS_INVALID_PARAMETER;
153         }
154     }
155 
156     if (m_hevcPicParams->tiles_enabled_flag && !m_hevcPicParams->uniform_spacing_flag)
157     {
158         uint8_t  num_tile_columns_minus1                = m_hevcPicParams->num_tile_columns_minus1;
159         uint8_t  num_tile_rows_minus1                   = m_hevcPicParams->num_tile_rows_minus1;
160         uint16_t tileColWidth[HEVC_NUM_MAX_TILE_COLUMN] = {0};  //!< Table of tile column width
161         uint16_t tileRowHeight[HEVC_NUM_MAX_TILE_ROW]   = {0};  //!< Table of tile row height
162 
163         tileColWidth[num_tile_columns_minus1]           = m_widthInCtb & 0xffff;
164         for (auto i = 0; i < num_tile_columns_minus1; i++)
165         {
166             tileColWidth[i]                       = m_hevcPicParams->column_width_minus1[i] + 1;
167             DECODE_CHK_COND(tileColWidth[i] == 0,
168                 "column_width_minus1 is invalid");
169             DECODE_CHK_COND(tileColWidth[i] > tileColWidth[num_tile_columns_minus1],
170                 "column_width_minus1 is out of range");
171             tileColWidth[num_tile_columns_minus1] -= tileColWidth[i];
172         }
173 
174         tileRowHeight[num_tile_rows_minus1] = m_heightInCtb & 0xffff;
175         for (auto i = 0; i < num_tile_rows_minus1; i++)
176         {
177             tileRowHeight[i]                    = m_hevcPicParams->row_height_minus1[i] + 1;
178             DECODE_CHK_COND(tileRowHeight[i] == 0,
179                 "row_height_minus1 is invalid");
180             DECODE_CHK_COND(tileRowHeight[i] > tileRowHeight[num_tile_rows_minus1],
181                 "row_height_minus1 is out of range");
182             tileRowHeight[num_tile_rows_minus1] -= tileRowHeight[i];
183         }
184     }
185 
186     // diff_cu_qp_delta_depth range is [0, log2_diff_max_min_luma_coding_block_size]
187     if (m_hevcPicParams->diff_cu_qp_delta_depth > m_hevcPicParams->log2_diff_max_min_luma_coding_block_size)
188     {
189         DECODE_ASSERTMESSAGE("diff_cu_qp_delta_depth %d is invalid\n", m_hevcPicParams->diff_cu_qp_delta_depth);
190         m_hevcPicParams->diff_cu_qp_delta_depth = 0;
191     }
192 
193     // cb_qp_offset range is [-12, 12]
194     if (m_hevcPicParams->pps_cb_qp_offset > 12 || m_hevcPicParams->pps_cb_qp_offset < -12)
195     {
196         DECODE_ASSERTMESSAGE("cb_qp_offset is invalid\n", m_hevcPicParams->pps_cb_qp_offset);
197         return MOS_STATUS_INVALID_PARAMETER;
198     }
199 
200     // cr_qp_offset range is [-12, 12]
201     if (m_hevcPicParams->pps_cr_qp_offset > 12 || m_hevcPicParams->pps_cr_qp_offset < -12)
202     {
203         DECODE_ASSERTMESSAGE("cr_qp_offset is invalid\n", m_hevcPicParams->pps_cr_qp_offset);
204         return MOS_STATUS_INVALID_PARAMETER;
205     }
206 
207     // log2_parallel_merge_level_minus2 is in range [0, 4]
208     if (m_hevcPicParams->log2_parallel_merge_level_minus2 > 4)
209     {
210         DECODE_ASSERTMESSAGE("log2_parallel_merge_level_minus2 is out of range\n");
211         return MOS_STATUS_INVALID_PARAMETER;
212     }
213 
214     // The value of log2_parallel_merge_level_minus2 shall be in the range of 0 to CtbLog2SizeY - 2
215     if (m_hevcPicParams->log2_parallel_merge_level_minus2 >
216         (m_hevcPicParams->log2_min_luma_coding_block_size_minus3 + 1 + m_hevcPicParams->log2_diff_max_min_luma_coding_block_size))
217     {
218         DECODE_ASSERTMESSAGE("log2_parallel_merge_level_minus2 is out of range\n");
219         return MOS_STATUS_INVALID_PARAMETER;
220     }
221 
222     if (m_hevcPicParams->entropy_coding_sync_enabled_flag && m_hevcPicParams->tiles_enabled_flag)
223     {
224         // check for non-scc
225         if (m_hevcSccPicParams == nullptr)
226         {
227             DECODE_ASSERTMESSAGE("Only SCC 4:4:4 allows both tiles_enabled_flag and entropy_coding_sync_enabled_flag to be on at the same time\n");
228         }
229     }
230 
231     // Todo: check error detect for Rext
232     if (m_hevcRextPicParams != nullptr)
233     {
234         if (m_hevcPicParams->transform_skip_enabled_flag == 0)
235         {
236             m_hevcRextPicParams->log2_max_transform_skip_block_size_minus2 = 0;
237             DECODE_ASSERTMESSAGE("log2_max_transform_skip_block_size_minus2 should equal to 0 when transform_skip_enabled_flag not present\n");
238         }
239 
240         if (m_hevcRextPicParams->diff_cu_chroma_qp_offset_depth > m_hevcPicParams->log2_diff_max_min_luma_coding_block_size)
241         {
242             DECODE_ASSERTMESSAGE("diff_cu_chroma_qp_offset_depth is out of range\n");
243         }
244 
245         // only for 4:4:4 it can be program to non-zero
246         if (m_hevcPicParams->chroma_format_idc != 3)
247         {
248             DECODE_ASSERTMESSAGE("chroma_qp_offset_list_enabled_flag is only supported in 4:4:4\n");
249         }
250 
251         // chroma_qp_offset_list_len_minus1 range is [0, 5]
252         if (m_hevcRextPicParams->chroma_qp_offset_list_len_minus1 > 5)
253         {
254             DECODE_ASSERTMESSAGE("chroma_qp_offset_list_len_minus1 is out of range [0, 5]\n");
255         }
256 
257         // check if TU size is valid
258         auto maxTUSize = m_hevcPicParams->log2_diff_max_min_transform_block_size + m_hevcPicParams->log2_min_transform_block_size_minus2;
259         if (m_hevcRextPicParams->log2_max_transform_skip_block_size_minus2 > maxTUSize)
260         {
261             DECODE_ASSERTMESSAGE("log2_max_transform_skip_block_size_minus2 is out of range\n");
262         }
263     }
264 
265     // Todo: check error detect for SCC
266     if (m_hevcSccPicParams != nullptr)
267     {
268         if (m_hevcPicParams->chroma_format_idc != 3)
269         {
270             if (m_hevcPicParams->entropy_coding_sync_enabled_flag && m_hevcPicParams->tiles_enabled_flag)
271             {
272                 DECODE_ASSERTMESSAGE("Only SCC 4:4:4 allows both tiles_enabled_flag and entropy_coding_sync_enabled_flag to be on at the same time\n");
273             }
274         }
275     }
276 
277     if (!m_shortFormatInUse)
278     {
279         for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++)
280         {
281             for (uint32_t i = 0; i < 2; i++)
282             {
283                 for (uint32_t j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; j++)
284                 {
285                     if (m_hevcSliceParams->RefPicList[i][j].FrameIdx > 0x7f)
286                     {
287                         DECODE_ASSERTMESSAGE("Reference frame index is out of range\n");
288                         return MOS_STATUS_INVALID_PARAMETER;
289                     }
290                 }
291             }
292         }
293     }
294 
295     return MOS_STATUS_SUCCESS;
296 }
297 
SliceDataSizeCheck(uint32_t sliceIdx)298 MOS_STATUS HevcBasicFeature::SliceDataSizeCheck(uint32_t sliceIdx)
299 {
300     DECODE_FUNC_CALL();
301 
302     if (m_hevcSliceParams[sliceIdx].slice_data_offset + m_hevcSliceParams[sliceIdx].slice_data_size > m_dataSize)
303     {
304         DECODE_ASSERTMESSAGE("invalid slice %d, data size overflow\n", sliceIdx);
305         return MOS_STATUS_INVALID_PARAMETER;
306     }
307 
308     /* Check slice missing data size should not be dropped to 0 */
309     if (m_hevcSliceParams[sliceIdx].slice_data_size <= m_hevcSliceParams[sliceIdx].ByteOffsetToSliceData)
310     {
311         DECODE_ASSERTMESSAGE("slice data size %u should be greater than slice header length %u\n", m_hevcSliceParams[sliceIdx].slice_data_size, m_hevcSliceParams[sliceIdx].ByteOffsetToSliceData);
312         return MOS_STATUS_INVALID_PARAMETER;
313     }
314 
315     return MOS_STATUS_SUCCESS;
316 }
317 
SliceSegmentAddressCheck(uint32_t sliceIdx,std::vector<int> & sliceSegmentAddressVector)318 MOS_STATUS HevcBasicFeature::SliceSegmentAddressCheck(uint32_t sliceIdx, std::vector<int> &sliceSegmentAddressVector)
319 {
320     DECODE_FUNC_CALL();
321 
322     /* When sliceIdx = 0, it should be an independent slice, and its slice_segment_address should be 0 */
323     if (sliceIdx == 0)
324     {
325         if (!IsIndependentSlice(sliceIdx) || m_hevcSliceParams[sliceIdx].slice_segment_address != 0)
326         {
327             DECODE_ASSERTMESSAGE("Invalid slice %d, independent slice = %s, slice_segment_address = %d\n",
328                                  sliceIdx, IsIndependentSlice(sliceIdx) ? "True" : "False", m_hevcSliceParams[sliceIdx].slice_segment_address);
329             return MOS_STATUS_INVALID_PARAMETER;
330         }
331     }
332 
333     /* Check slice_segment_address should be in range [0, picSizeInCtbsY - 1] and
334      * shall not be equal to the value of slice_segment_address of any other coded slice segment NAL unit of the same coded picture */
335     uint32_t picSizeInCtbsY = m_widthInCtb * m_heightInCtb;
336     if (sliceIdx != 0) // Previous check has conformed when sliceIdx = 0, slice_segment_address = 0
337     {
338         if ((m_hevcSliceParams[sliceIdx].slice_segment_address >= picSizeInCtbsY))
339         {
340             DECODE_ASSERTMESSAGE("slice segment address %d is out of range [0, %d]\n",
341                                  m_hevcSliceParams[sliceIdx].slice_segment_address, picSizeInCtbsY - 1);
342             return MOS_STATUS_INVALID_PARAMETER;
343         }
344     }
345     sliceSegmentAddressVector.push_back(m_hevcSliceParams[sliceIdx].slice_segment_address);
346     if (std::set<int>(sliceSegmentAddressVector.begin(), sliceSegmentAddressVector.end()).size() != sliceSegmentAddressVector.size()) // Has duplicate slice_segment_address
347     {
348         DECODE_ASSERTMESSAGE("%dth slice_segment_address %d has duplicated.\n", sliceIdx, m_hevcSliceParams[sliceIdx].slice_segment_address);
349         return MOS_STATUS_INVALID_PARAMETER;
350     }
351 
352     return MOS_STATUS_SUCCESS;
353 }
354 
NumEntryPointOffsetsCheck(uint32_t sliceIdx)355 MOS_STATUS HevcBasicFeature::NumEntryPointOffsetsCheck(uint32_t sliceIdx)
356 {
357     DECODE_FUNC_CALL();
358 
359     /* Check num_entry_point_offsets */
360     if (m_hevcPicParams->tiles_enabled_flag || m_hevcPicParams->entropy_coding_sync_enabled_flag)
361     {
362         if (m_hevcPicParams->tiles_enabled_flag == 0 && m_hevcPicParams->entropy_coding_sync_enabled_flag == 1)
363         {
364             if (m_hevcSliceParams[sliceIdx].num_entry_point_offsets > m_hevcPicParams->PicHeightInMinCbsY - 1)
365             {
366                 DECODE_ASSERTMESSAGE("num_entry_point_offsets %d is out of range [0, %d]\n",
367                                      m_hevcSliceParams[sliceIdx].num_entry_point_offsets, m_hevcPicParams->PicHeightInMinCbsY - 1);
368                 return MOS_STATUS_INVALID_PARAMETER;
369             }
370         }
371         else if (m_hevcPicParams->tiles_enabled_flag == 1 && m_hevcPicParams->entropy_coding_sync_enabled_flag == 0)
372         {
373             if (m_hevcSliceParams[sliceIdx].num_entry_point_offsets > ((m_hevcPicParams->num_tile_columns_minus1 + 1) * (m_hevcPicParams->num_tile_rows_minus1 + 1) - 1))
374             {
375                 DECODE_ASSERTMESSAGE("num_entry_point_offsets %d is out of range [0, %d]\n",
376                                      m_hevcSliceParams[sliceIdx].num_entry_point_offsets, (m_hevcPicParams->num_tile_columns_minus1 + 1) * (m_hevcPicParams->num_tile_rows_minus1 + 1) - 1);
377                 return MOS_STATUS_INVALID_PARAMETER;
378             }
379         }
380         else
381         {
382             if (m_hevcSliceParams[sliceIdx].num_entry_point_offsets > ((m_hevcPicParams->num_tile_columns_minus1 + 1) * m_hevcPicParams->PicHeightInMinCbsY - 1))
383             {
384                 DECODE_ASSERTMESSAGE("num_entry_point_offsets %d is out of range [0, %d]\n",
385                                      m_hevcSliceParams[sliceIdx].num_entry_point_offsets, (m_hevcPicParams->num_tile_columns_minus1 + 1) * m_hevcPicParams->PicHeightInMinCbsY - 1);
386                 return MOS_STATUS_INVALID_PARAMETER;
387             }
388         }
389     }
390     return MOS_STATUS_SUCCESS;
391 }
392 
ReferenceParamCheck(uint32_t sliceIdx)393 MOS_STATUS HevcBasicFeature::ReferenceParamCheck(uint32_t sliceIdx)
394 {
395     DECODE_FUNC_CALL();
396 
397     /* If it's P or B slice, the num_ref_idx_lx_active_minus1 should be in range [0, 14] */
398     if (decodeHevcISlice != m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.slice_type)
399     {
400         if (m_hevcSliceParams[sliceIdx].num_ref_idx_l0_active_minus1 >= CODEC_MAX_NUM_REF_FRAME_HEVC )
401         {
402             DECODE_ASSERTMESSAGE("num_ref_idx_l0_active_minus1 %d is out of range [0, 14]\n", m_hevcSliceParams[sliceIdx].num_ref_idx_l0_active_minus1);
403             return MOS_STATUS_INVALID_PARAMETER;
404         }
405         if (decodeHevcBSlice == m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.slice_type)
406         {
407             if (m_hevcSliceParams[sliceIdx].num_ref_idx_l1_active_minus1 >= CODEC_MAX_NUM_REF_FRAME_HEVC)
408             {
409                 DECODE_ASSERTMESSAGE("num_ref_idx_l1_active_minus1 %d is out of range [0, 14]\n", m_hevcSliceParams[sliceIdx].num_ref_idx_l1_active_minus1);
410                 return MOS_STATUS_INVALID_PARAMETER;
411             }
412         }
413     }
414 
415     /* Check RefPicList[listIdx][refIdx].FrameIdx */
416     uint32_t num_ref_idx_active_minus1[2] = {0};
417     num_ref_idx_active_minus1[0] = m_hevcSliceParams[sliceIdx].num_ref_idx_l0_active_minus1;
418     num_ref_idx_active_minus1[1] = m_hevcSliceParams[sliceIdx].num_ref_idx_l1_active_minus1;
419     bool hasRefPic[2] = {false};
420     uint8_t reflistNum = 0;
421 
422     switch (m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.slice_type)
423     {
424     case decodeHevcISlice:
425         reflistNum = 0;
426         break;
427     case decodeHevcPSlice:
428         reflistNum = 1;
429         break;
430     case decodeHevcBSlice:
431         reflistNum = 2;
432         break;
433     default:
434         break;
435     }
436 
437     for (uint8_t listIdx = 0; listIdx < reflistNum; listIdx++)
438     {
439         /* If num_ref_idx_lx_active_minus1 is in [0, 14], it should have at least 1 reference picture. */
440         for (uint8_t refListIdx = 0; refListIdx <= num_ref_idx_active_minus1[listIdx]; refListIdx++)
441         {
442             if (m_hevcSliceParams[sliceIdx].RefPicList[listIdx][refListIdx].FrameIdx < CODEC_MAX_NUM_REF_FRAME_HEVC)
443             {
444                 hasRefPic[listIdx] = true;
445                 break;
446             }
447         }
448 
449         if (false == hasRefPic[listIdx])
450         {
451             DECODE_ASSERTMESSAGE("num_ref_idx_active_minus1[%d] = %d, RefPicList[%d].FrameIdx is all 127\n",
452                                  listIdx, num_ref_idx_active_minus1[listIdx], listIdx);
453             return MOS_STATUS_INVALID_PARAMETER;
454         }
455     }
456     return MOS_STATUS_SUCCESS;
457 }
458 
CollocatedRefIdxCheck(uint32_t sliceIdx)459 MOS_STATUS HevcBasicFeature::CollocatedRefIdxCheck(uint32_t sliceIdx)
460 {
461     DECODE_FUNC_CALL();
462 
463     if (m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.slice_temporal_mvp_enabled_flag)
464     {
465         /* Check collocated_ref_idx */
466         if (((m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.slice_type == decodeHevcPSlice) || (m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.slice_type == decodeHevcBSlice))
467             && m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.collocated_from_l0_flag)
468         {
469             if (m_hevcSliceParams[sliceIdx].collocated_ref_idx > m_hevcSliceParams[sliceIdx].num_ref_idx_l0_active_minus1)
470             {
471                 DECODE_ASSERTMESSAGE("collocated_ref_idx %d is out of range [%d, %d]\n", m_hevcSliceParams[sliceIdx].collocated_ref_idx, 0, m_hevcSliceParams[sliceIdx].num_ref_idx_l0_active_minus1);
472                 return MOS_STATUS_INVALID_PARAMETER;
473             }
474         }
475         if ((m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.slice_type == decodeHevcBSlice) && (m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.collocated_from_l0_flag == 0))
476         {
477             if (m_hevcSliceParams[sliceIdx].collocated_ref_idx > m_hevcSliceParams[sliceIdx].num_ref_idx_l1_active_minus1)
478             {
479                 DECODE_ASSERTMESSAGE("collocated_ref_idx %d is out of range [%d, %d]\n", m_hevcSliceParams[sliceIdx].collocated_ref_idx, 0, m_hevcSliceParams[sliceIdx].num_ref_idx_l1_active_minus1);
480                 return MOS_STATUS_INVALID_PARAMETER;
481             }
482         }
483     }
484 
485     return MOS_STATUS_SUCCESS;
486 }
487 
ErrorDetectAndConcealForLongFormat()488 MOS_STATUS HevcBasicFeature::ErrorDetectAndConcealForLongFormat()
489 {
490     DECODE_FUNC_CALL();
491 
492     std::vector<int> sliceSegmentAddressVector;
493 
494     for (uint32_t sliceIdx = 0; sliceIdx < m_numSlices; sliceIdx++)
495     {
496         DECODE_CHK_STATUS(SliceDataSizeCheck(sliceIdx));
497 
498         DECODE_CHK_STATUS(SliceSegmentAddressCheck(sliceIdx, sliceSegmentAddressVector));
499 
500         DECODE_CHK_STATUS(NumEntryPointOffsetsCheck(sliceIdx));
501 
502         DECODE_CHK_STATUS(ReferenceParamCheck(sliceIdx));
503 
504         DECODE_CHK_STATUS(CollocatedRefIdxCheck(sliceIdx));
505     }
506 
507     return MOS_STATUS_SUCCESS;
508 }
509 
IsLastSlice(uint32_t sliceIdx)510 bool HevcBasicFeature::IsLastSlice(uint32_t sliceIdx)
511 {
512     return (sliceIdx == (m_numSlices-1)) ||
513            m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.LastSliceOfPic;
514 }
515 
IsIndependentSlice(uint32_t sliceIdx)516 bool HevcBasicFeature::IsIndependentSlice(uint32_t sliceIdx)
517 {
518     return (sliceIdx == 0) ||
519            (! m_hevcSliceParams[sliceIdx].LongSliceFlags.fields.dependent_slice_segment_flag);
520 }
521 
SetRequiredBitstreamSize(uint32_t requiredSize)522 MOS_STATUS HevcBasicFeature::SetRequiredBitstreamSize(uint32_t requiredSize)
523 {
524     DECODE_FUNC_CALL();
525     if (requiredSize > m_dataSize)
526     {
527         m_dataOffset = 0;
528         m_dataSize   = MOS_ALIGN_CEIL(requiredSize, MHW_CACHELINE_SIZE);
529     }
530     DECODE_NORMALMESSAGE("Estimate bitstream size in this Frame: %u", requiredSize);
531     return MOS_STATUS_SUCCESS;
532 }
533 
SetPictureStructs()534 MOS_STATUS HevcBasicFeature::SetPictureStructs()
535 {
536     DECODE_FUNC_CALL();
537 
538     m_minCtbSize = 1 << (m_hevcPicParams->log2_min_luma_coding_block_size_minus3 + 3);
539     m_width      = m_hevcPicParams->PicWidthInMinCbsY * m_minCtbSize;
540     m_height     = m_hevcPicParams->PicHeightInMinCbsY * m_minCtbSize;
541 
542     m_ctbSize     = 1 << (m_hevcPicParams->log2_diff_max_min_luma_coding_block_size +
543                       m_hevcPicParams->log2_min_luma_coding_block_size_minus3 + 3);
544     m_widthInCtb  = MOS_ROUNDUP_DIVIDE(m_width, m_ctbSize);
545     m_heightInCtb = MOS_ROUNDUP_DIVIDE(m_height, m_ctbSize);
546 
547     m_curRenderPic = m_hevcPicParams->CurrPic;
548 
549     // Do error detection and concealment
550     DECODE_CHK_STATUS(ErrorDetectAndConceal());
551 
552     m_secondField = CodecHal_PictureIsBottomField(m_curRenderPic);
553 
554     m_isWPPMode = m_hevcPicParams->entropy_coding_sync_enabled_flag;
555 
556     if (m_hevcSccPicParams == nullptr)
557     {
558         m_isSCCIBCMode = false;
559         m_isSCCPLTMode = false;
560         m_isSCCACTMode = false;
561     }
562     else
563     {
564         m_isSCCIBCMode = m_hevcSccPicParams->PicSCCExtensionFlags.fields.pps_curr_pic_ref_enabled_flag;
565         m_isSCCPLTMode = m_hevcSccPicParams->PicSCCExtensionFlags.fields.palette_mode_enabled_flag;
566         m_isSCCACTMode = m_hevcSccPicParams->PicSCCExtensionFlags.fields.residual_adaptive_colour_transform_enabled_flag;
567     }
568 
569     if (m_isSCCIBCMode)
570     {
571         DECODE_CHK_STATUS(CreateReferenceBeforeLoopFilter());
572     }
573 
574     m_refFrameIndexList.clear();
575     for(uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
576     {
577         if (m_hevcPicParams->RefFrameList[i].FrameIdx < m_maxFrameIndex)
578         {
579             m_refFrameIndexList.push_back(m_hevcPicParams->RefFrameList[i].FrameIdx);
580         }
581     }
582 
583     m_reportFrameCrc = m_hevcPicParams->RequestCRC;
584 
585     DECODE_CHK_STATUS(m_refFrames.UpdatePicture(*m_hevcPicParams, m_isSCCIBCMode));
586     if (m_osInterface->pfnIsMismatchOrderProgrammingSupported())
587     {
588         for (auto &refFrameIdx : m_refFrameIndexList)
589         {
590             DECODE_CHK_STATUS(m_mvBuffers.ActiveCurBuffer(refFrameIdx));
591         }
592         DECODE_CHK_STATUS(m_mvBuffers.ActiveCurBuffer(m_curRenderPic.FrameIdx));
593     }
594     else
595     {
596         DECODE_CHK_STATUS(m_mvBuffers.UpdatePicture(m_curRenderPic.FrameIdx, m_refFrameIndexList));
597     }
598     DECODE_CHK_STATUS(m_tileCoding.UpdatePicture(*m_hevcPicParams));
599 
600     // Not possible to determine whether P or B is used for short format.
601     // For long format iterating through all of the slices to determine P vs
602     // B, so in order to avoid this, declare all other pictures MIXED_TYPE.
603     m_pictureCodingType = m_refFrames.m_curIsIntra ? I_TYPE : MIXED_TYPE;
604 
605     // Clean dummy reference slot, will be upated by Hevc picture packet accrodingly
606     MOS_ZeroMemory(m_dummyReferenceSlot, sizeof(m_dummyReferenceSlot));
607 
608     return MOS_STATUS_SUCCESS;
609 }
610 
SetSliceStructs()611 MOS_STATUS HevcBasicFeature::SetSliceStructs()
612 {
613     DECODE_FUNC_CALL();
614 
615     DECODE_CHK_STATUS(m_tileCoding.UpdateSlice(*m_hevcPicParams, m_hevcSliceParams));
616 
617     if (m_numSlices > 0)
618     {
619         PCODEC_HEVC_SLICE_PARAMS lastSlice = m_hevcSliceParams + (m_numSlices - 1);
620         DECODE_CHK_STATUS(SetRequiredBitstreamSize(lastSlice->slice_data_offset + lastSlice->slice_data_size));
621     }
622 
623     if (!m_shortFormatInUse)
624     {
625         DECODE_CHK_STATUS(ErrorDetectAndConcealForLongFormat());
626     }
627 
628     return MOS_STATUS_SUCCESS;
629 }
630 
CreateReferenceBeforeLoopFilter()631 MOS_STATUS HevcBasicFeature::CreateReferenceBeforeLoopFilter()
632 {
633     if (m_destSurface.dwWidth  == 0 ||
634         m_destSurface.dwHeight == 0)
635     {
636         return MOS_STATUS_SUCCESS;
637     }
638 
639     if (m_referenceBeforeLoopFilter == nullptr)
640     {
641         m_referenceBeforeLoopFilter = m_allocator->AllocateSurface(
642             m_destSurface.dwWidth, m_destSurface.dwHeight, "Reference before loop filter",
643             m_destSurface.Format, m_destSurface.bCompressible, resourceOutputPicture, notLockableVideoMem);
644         DECODE_CHK_NULL(m_referenceBeforeLoopFilter);
645     }
646     else
647     {
648         DECODE_CHK_STATUS(m_allocator->Resize(m_referenceBeforeLoopFilter, m_destSurface.dwWidth, m_destSurface.dwHeight,
649             notLockableVideoMem, false, "Reference before loop filter"));
650     }
651     return MOS_STATUS_SUCCESS;
652 }
653 
654 }  // namespace encode
655