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