1 /*
2 * Copyright (c) 2020-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 //!
24 //! \file     decode_avc_basic_features.cpp
25 //! \brief    Defines the common interface for decode avc basic feature
26 //!
27 #include "decode_avc_basic_feature.h"
28 #include "decode_utils.h"
29 #include "decode_allocator.h"
30 
31 namespace decode {
32 
~AvcBasicFeature()33     AvcBasicFeature::~AvcBasicFeature()
34     {
35         if (m_allocator != nullptr && m_resMonoPicChromaBuffer != nullptr)
36         {
37             m_allocator->Destroy(m_resMonoPicChromaBuffer);
38         }
39     }
40 
Init(void * setting)41     MOS_STATUS AvcBasicFeature::Init(void *setting)
42     {
43         DECODE_FUNC_CALL();
44 
45         PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL);
46 
47         DECODE_CHK_NULL(setting);
48 
49         DECODE_CHK_STATUS(DecodeBasicFeature::Init(setting));
50         CodechalSetting *codecSettings = (CodechalSetting*)setting;
51         DECODE_CHK_NULL(codecSettings);
52         m_shortFormatInUse = codecSettings->shortFormatInUse;
53 
54         DECODE_CHK_STATUS(m_refFrames.Init(this, *m_allocator));
55         DECODE_CHK_STATUS(m_mvBuffers.Init(m_hwInterface, *m_allocator, *this, CODEC_AVC_NUM_INIT_DMV_BUFFERS));
56 
57         return MOS_STATUS_SUCCESS;
58     }
59 
Update(void * params)60     MOS_STATUS AvcBasicFeature::Update(void *params)
61     {
62         DECODE_FUNC_CALL();
63 
64         PERF_UTILITY_AUTO(__FUNCTION__, PERF_DECODE, PERF_LEVEL_HAL);
65 
66         DECODE_CHK_NULL(params);
67 
68         DECODE_CHK_STATUS(DecodeBasicFeature::Update(params));
69 
70         CodechalDecodeParams* decodeParams = (CodechalDecodeParams*)params;
71         DECODE_CHK_NULL(decodeParams->m_picParams);
72         DECODE_CHK_NULL(decodeParams->m_sliceParams);
73         m_avcPicParams            = (PCODEC_AVC_PIC_PARAMS)decodeParams->m_picParams;
74         m_avcSliceParams          = (PCODEC_AVC_SLICE_PARAMS)decodeParams->m_sliceParams;
75         m_mvcExtPicParams         = (PCODEC_MVC_EXT_PIC_PARAMS)decodeParams->m_extPicParams;
76         m_avcIqMatrixParams       = (PCODEC_AVC_IQ_MATRIX_PARAMS)decodeParams->m_iqMatrixBuffer;
77         m_picIdRemappingInUse     = decodeParams->m_picIdRemappingInUse;
78         m_fullFrameData           = decodeParams->m_bFullFrameData;
79         m_streamOutEnabled        = decodeParams->m_streamOutEnabled;
80         m_externalStreamOutBuffer = decodeParams->m_externalStreamOutBuffer;
81         m_cencBuf                 = decodeParams->m_cencBuf;
82 
83         DECODE_CHK_NULL(m_avcPicParams);
84         DECODE_CHK_NULL(m_avcSliceParams);
85 
86         // Do error detection and concealment
87         DECODE_CHK_STATUS(ErrorDetectAndConceal());
88 
89 
90         MEDIA_FEATURE_TABLE* skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
91         m_usingVeRing = (skuTable != nullptr) ? MEDIA_IS_SKU(skuTable, FtrVERing) : false;
92 
93         if (m_avcPicParams->seq_fields.chroma_format_idc == avcChromaFormatMono &&
94             (m_resMonoPicChromaBuffer == nullptr))
95         {
96             uint32_t pitch  = m_destSurface.dwPitch;
97             uint32_t chromaHeight = m_destSurface.dwHeight >> 1;
98             uint32_t alignedChromaHeight = MOS_ALIGN_CEIL(chromaHeight, MOS_YTILE_H_ALIGNMENT);
99             uint32_t chromaBufSize = MOS_ALIGN_CEIL(pitch * alignedChromaHeight, MHW_PAGE_SIZE);
100             m_resMonoPicChromaBuffer = m_allocator->AllocateBuffer(
101                                             chromaBufSize,
102                                             "MonoPictureChromaBuffer",
103                                             resourceInternalReadWriteCache,
104                                             lockableVideoMem,
105                                             true,
106                                             DECODE_AVC_MONOPIC_CHROMA_DEFAULT);
107         }
108 
109         DECODE_CHK_STATUS(SetPictureStructs());
110         DECODE_CHK_STATUS(SetSliceStructs());
111 
112         return MOS_STATUS_SUCCESS;
113     }
114 
ErrorDetectAndConceal()115     MOS_STATUS AvcBasicFeature::ErrorDetectAndConceal()
116     {
117         /*
118          *Only check the invalid syntax instead of return error to skip decoding since this invalid syntax will not cause critical issue
119          * */
120         DECODE_FUNC_CALL();
121         DECODE_CHK_NULL(m_avcPicParams);
122         DECODE_CHK_NULL(m_avcSliceParams);
123 
124         DECODE_CHK_STATUS(CheckBitDepthAndChromaSampling());
125 
126         if(m_avcPicParams->seq_fields.chroma_format_idc != 3
127             && m_avcPicParams->seq_fields.residual_colour_transform_flag)
128         {
129             DECODE_ASSERTMESSAGE("Conflict with H264 Spec! residual_colour_transform_flag can be set only when chroma_format_idc != 3");
130         }
131 
132         if(m_avcPicParams->seq_fields.frame_mbs_only_flag && m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag != 0)
133         {
134             if(m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag != 0)
135             {
136                 DECODE_ASSERTMESSAGE("Conflict with H264 Spec! mb_adaptive_frame_field_flag should be 0 when frame_mbs_only_flag is set");
137                 m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag = 0;
138             }
139 
140             if(m_avcPicParams->pic_fields.field_pic_flag)
141             {
142                 DECODE_ASSERTMESSAGE("Conflict with H264 Spec! field_pic_flag should be 0 when frame_mbs_only_flag is set");
143             }
144         }
145 
146         if(m_avcPicParams->seq_fields.log2_max_frame_num_minus4 > 12)
147         {
148             DECODE_ASSERTMESSAGE("Conflict with H264 Spec! log2_max_frame_num_minus4 is out of range");
149         }
150 
151         if(m_avcPicParams->seq_fields.pic_order_cnt_type > 2)
152         {
153             DECODE_ASSERTMESSAGE("Conflict with H264 Spec! pic_order_cnt_type is out of range");
154         }
155 
156         if(m_avcPicParams->seq_fields.pic_order_cnt_type == 1 && m_avcPicParams->seq_fields.log2_max_pic_order_cnt_lsb_minus4 != 0)
157         {
158             DECODE_ASSERTMESSAGE("Conflict with H264 Spec!  log2_max_pic_order_cnt_lsb_minus4 should be 0 when pic_order_cnt_type is set");
159             m_avcPicParams->seq_fields.log2_max_pic_order_cnt_lsb_minus4 = 0;
160         }
161 
162         if(m_avcPicParams->seq_fields.pic_order_cnt_type == 0)
163         {
164             if(m_avcPicParams->seq_fields.delta_pic_order_always_zero_flag != 0)
165             {
166                 DECODE_ASSERTMESSAGE("Conflict with H264 Spec! delta_pic_order_always_zero_flag should be 0 when pic_order_cnt_type is not set");
167                 m_avcPicParams->seq_fields.delta_pic_order_always_zero_flag = 0;
168             }
169 
170             if(m_avcPicParams->seq_fields.log2_max_pic_order_cnt_lsb_minus4 > 12)
171             {
172                 DECODE_ASSERTMESSAGE("Conflict with H264 Spec! log2_max_pic_order_cnt_lsb_minus4 is out of range");
173             }
174         }
175 
176         //currently num_slice_groups_minus1, slice_group_map_type and slice_group_change_rate_minus1 are all set to 0 in driver
177         if(m_avcPicParams->num_slice_groups_minus1 > 7)
178         {
179             DECODE_ASSERTMESSAGE("Conflict with H264 Spec! num_slice_groups_minus1 is out of range");
180         }
181         else
182         {
183             if(m_avcPicParams->slice_group_map_type > 6)
184             {
185                 DECODE_ASSERTMESSAGE("Conflict with H264 Spec! slice_group_map_type is out of range");
186             }
187             else if(m_avcPicParams->slice_group_map_type == 3
188                     || m_avcPicParams->slice_group_map_type == 4
189                     || m_avcPicParams->slice_group_map_type == 5)
190             {
191 
192                 if(m_avcPicParams->slice_group_change_rate_minus1 > (m_avcPicParams->pic_width_in_mbs_minus1 + 1) * (m_avcPicParams->pic_height_in_mbs_minus1 + 1))
193                 {
194                     DECODE_ASSERTMESSAGE("Conflict with H264 Spec! slice_group_change_rate_minus1 is out of range");
195                 }
196             }
197             else if(m_avcPicParams->slice_group_change_rate_minus1 != 0)
198             {
199                 DECODE_ASSERTMESSAGE("Conflict with H264 Spec!");
200             }
201         }
202 
203         if(m_avcPicParams->pic_init_qp_minus26 < -(26 + 6 * m_avcPicParams->bit_depth_luma_minus8)
204             || m_avcPicParams->pic_init_qp_minus26 > 25)
205         {
206             DECODE_ASSERTMESSAGE("Conflict with H264 Spec! pic_init_qp_minus26 is out of range");
207         }
208 
209         if(m_avcPicParams->chroma_qp_index_offset < -12
210             || m_avcPicParams->chroma_qp_index_offset > 12)
211         {
212             DECODE_ASSERTMESSAGE("Conflict with H264 Spec! chroma_qp_index_offset is out of range");
213         }
214 
215         if(m_avcPicParams->second_chroma_qp_index_offset < -12
216             || m_avcPicParams->second_chroma_qp_index_offset > 12)
217         {
218             DECODE_ASSERTMESSAGE("Conflict with H264 Spec! second_chroma_qp_index_offset is out of range");
219         }
220 
221         if(m_avcPicParams->pic_fields.weighted_bipred_idc > 2)
222         {
223             DECODE_ASSERTMESSAGE("Conflict with H264 Spec! weighted_bipred_idc is out of range");
224         }
225 
226         if (!m_shortFormatInUse)
227         {
228             for (uint32_t slcIdx = 0; slcIdx < m_numSlices; slcIdx++)
229             {
230                 PCODEC_AVC_SLICE_PARAMS slc = m_avcSliceParams + slcIdx;
231                 if(m_avcPicParams->pic_fields.field_pic_flag == 0)
232                 {
233                     if (slc->num_ref_idx_l0_active_minus1 > 15)
234                     {
235                         slc->num_ref_idx_l0_active_minus1 = 0;
236                         DECODE_ASSERTMESSAGE("Conflict with H264 Spec! num_ref_idx_l0_active_minus1 is out of range");
237                     }
238                     if (slc->num_ref_idx_l1_active_minus1 > 15)
239                     {
240                         slc->num_ref_idx_l1_active_minus1 = 0;
241                         DECODE_ASSERTMESSAGE("Conflict with H264 Spec! num_ref_idx_l1_active_minus1 is out of range");
242                     }
243                 }
244                 else if(m_avcPicParams->pic_fields.field_pic_flag == 1)
245                 {
246                     if (slc->num_ref_idx_l0_active_minus1 > 31)
247                     {
248                         slc->num_ref_idx_l0_active_minus1 = 0;
249                         DECODE_ASSERTMESSAGE("Conflict with H264 Spec! num_ref_idx_l0_active_minus1 is out of range");
250                     }
251                     if (slc->num_ref_idx_l1_active_minus1 > 31)
252                     {
253                         slc->num_ref_idx_l1_active_minus1 = 0;
254                         DECODE_ASSERTMESSAGE("Conflict with H264 Spec! num_ref_idx_l1_active_minus1 is out of range");
255                     }
256                 }
257             }
258         }
259 
260         return MOS_STATUS_SUCCESS;
261     }
262 
SetPictureStructs()263     MOS_STATUS AvcBasicFeature::SetPictureStructs()
264     {
265         DECODE_FUNC_CALL();
266 
267         m_width  = (m_avcPicParams->pic_width_in_mbs_minus1 + 1) * CODECHAL_MACROBLOCK_WIDTH;
268         m_height = (m_avcPicParams->pic_height_in_mbs_minus1 + 1) * CODECHAL_MACROBLOCK_HEIGHT;
269         m_pictureCodingType = m_avcPicParams->pic_fields.IntraPicFlag ? I_TYPE : MIXED_TYPE;
270         m_curRenderPic = m_avcPicParams->CurrPic;
271         DECODE_CHK_COND(m_curRenderPic.FrameIdx >= CODEC_AVC_NUM_UNCOMPRESSED_SURFACE,
272                         "currPic.FrameIdx is out of range!");
273 
274         //reset to default value
275         m_secondField = false;
276         if (m_fullFeildsReceived == (PICTURE_BOTTOM_FIELD | PICTURE_TOP_FIELD))
277         {
278             m_fullFeildsReceived = 0;
279         }
280 
281         if (CodecHal_PictureIsField(m_avcPicParams->CurrPic))
282         {
283            if (CodecHal_PictureIsTopField(m_avcPicParams->CurrPic))
284            {
285                m_fullFeildsReceived |= PICTURE_TOP_FIELD;
286            }
287            if (CodecHal_PictureIsBottomField(m_avcPicParams->CurrPic))
288            {
289                m_fullFeildsReceived |= PICTURE_BOTTOM_FIELD;
290            }
291         }
292         else
293         {
294             m_fullFeildsReceived = 0;
295         }
296 
297         if (m_fullFeildsReceived == (PICTURE_BOTTOM_FIELD | PICTURE_TOP_FIELD))
298         {
299             m_secondField = true;
300         }
301 
302         if (m_shortFormatInUse)
303         {
304             // When HW parses the slice_header, disable_deblocking_filter_idc is not yet known,
305             // so always enable ILDB for this case.
306             m_deblockingEnabled = true;
307         }
308         else
309         {
310             for (uint32_t i = 0; i < m_numSlices; i++)
311             {
312                 if (m_avcSliceParams[i].disable_deblocking_filter_idc != 1)
313                 {
314                     m_deblockingEnabled = true;
315                     break;
316                 }
317             }
318         }
319 
320         m_fixedFrameIdx = 0xff;
321         m_refFrameIndexList.clear();
322         for (uint32_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
323         {
324             if (m_avcPicParams->RefFrameList[i].FrameIdx < m_maxFrameIndex &&
325                 !CodecHal_PictureIsInvalid(m_avcPicParams->RefFrameList[i]))
326             {
327                 m_refFrameIndexList.push_back(m_avcPicParams->RefFrameList[i].FrameIdx);
328                 // For interlaced case, if second field refers to first field in the same frame, need to
329                 // keep the current FrameIdx into the refFrameList, two fields will use the same MV buffer.
330                 if (m_secondField && (m_curRenderPic.FrameIdx == m_avcPicParams->RefFrameList[i].FrameIdx))
331                 {
332                     m_fixedFrameIdx = m_curRenderPic.FrameIdx;
333                 }
334             }
335         }
336 
337         DECODE_CHK_STATUS(m_refFrames.UpdatePicture(*m_avcPicParams));
338 
339         if (!m_isSecondField)
340         {
341             if (m_osInterface->pfnIsMismatchOrderProgrammingSupported())
342             {
343                 for (auto &refFrameIdx : m_refFrameIndexList)
344                 {
345                     DECODE_CHK_STATUS(m_mvBuffers.ActiveCurBuffer(refFrameIdx));
346                 }
347                 DECODE_CHK_STATUS(m_mvBuffers.ActiveCurBuffer(m_avcPicParams->CurrPic.FrameIdx));
348             }
349             else
350             {
351                 DECODE_CHK_STATUS(m_mvBuffers.UpdatePicture(m_avcPicParams->CurrPic.FrameIdx, m_refFrameIndexList, m_fixedFrameIdx));
352             }
353         }
354 
355         return MOS_STATUS_SUCCESS;
356     }
357 
SetSliceStructs()358     MOS_STATUS AvcBasicFeature::SetSliceStructs()
359     {
360         DECODE_FUNC_CALL();
361 
362         PCODEC_AVC_SLICE_PARAMS slc = m_avcSliceParams;
363         uint16_t frameInMbs = (m_avcPicParams->pic_height_in_mbs_minus1 + 1) * (m_avcPicParams->pic_width_in_mbs_minus1 + 1);
364 
365         //reset to default value for incoming new frame
366         bool invalidSlicePresent = false;
367         m_lastValidSlice = false;
368         m_slcOffset = 0;
369         m_slcLength = 0;
370 
371         SliceRecord initialValue = {0};
372         std::fill(m_sliceRecord.begin(), m_sliceRecord.end(), initialValue);
373 
374         if (m_sliceRecord.size() < m_numSlices)
375         {
376             m_sliceRecord.resize(m_numSlices, {0, 0, 0});
377         }
378 
379         for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++)
380         {
381             //For DECE clear bytes calculation: Total bytes in the bit-stream consumed so far
382             m_sliceRecord[slcCount].totalBytesConsumed = slc->slice_data_offset + slc->slice_data_size;
383 
384             if (invalidSlicePresent == true)
385             {
386                 break;
387             }
388 
389             if (m_sliceRecord[slcCount].skip)
390             {
391                 continue;
392             }
393 
394             m_slcLength = slc->slice_data_size;
395 
396             // error handling for garbage data
397             if (((uint64_t)(slc->slice_data_offset) + m_slcLength) > m_dataSize)
398             {
399                 slc++;
400                 m_sliceRecord[slcCount].skip = true;
401                 continue;
402             }
403 
404             if (!m_shortFormatInUse)
405             {
406                 if (slcCount < m_numSlices - 1)
407                 {
408                     // Skip remaining slices if the number of MBs already reaches the total before the last slice or slice overlap occurs.
409                     if (((slc->first_mb_in_slice + slc->NumMbsForSlice >= frameInMbs) || ((slc + 1)->first_mb_in_slice <= slc->first_mb_in_slice)))
410                     {
411                         uint32_t count = slcCount + 1;
412                         slc->first_mb_in_next_slice = 0;
413                         invalidSlicePresent = true;
414 
415                         while (count < m_numSlices)
416                         {
417                             m_sliceRecord[count++].skip = true;
418                         }
419                     }
420                     else
421                     {
422                         slc->first_mb_in_next_slice = (slc + 1)->first_mb_in_slice;
423                     }
424                 }
425                 else
426                 {
427                     //For last slice, set it to 0
428                     slc->first_mb_in_next_slice = 0;
429                 }
430 
431                 m_slcOffset = (slc->slice_data_bit_offset >> 3) + m_osInterface->dwNumNalUnitBytesIncluded;
432 
433                 // For first slice, first_mb_in_slice must be 0, otherwise it's corrupted, skip the slice when first_mb_in_slice corrupted.
434                 if ((m_slcOffset > m_slcLength) || (0 == slcCount && slc->first_mb_in_slice) || (slc->first_mb_in_slice >= frameInMbs)
435                     || (m_avcPicParams->seq_fields.mb_adaptive_frame_field_flag && !m_avcPicParams->pic_fields.field_pic_flag &&
436                     (slc->first_mb_in_slice >= frameInMbs / 2)))
437                 {
438                     slc++;
439                     m_sliceRecord[slcCount].skip = true;
440                     continue;
441                 }
442                 m_slcLength -= m_slcOffset;
443             }
444 
445             m_sliceRecord[slcCount].length = m_slcLength;
446             m_sliceRecord[slcCount].offset = m_slcOffset;
447             m_lastValidSlice = slcCount;
448             slc++;
449         }
450 
451         return MOS_STATUS_SUCCESS;
452     }
453 
CheckBitDepthAndChromaSampling()454     MOS_STATUS AvcBasicFeature::CheckBitDepthAndChromaSampling()
455     {
456         DECODE_FUNC_CALL();
457         DECODE_CHK_NULL(m_avcPicParams);
458 
459         if (m_avcPicParams->seq_fields.chroma_format_idc > avcChromaFormat420
460             || m_avcPicParams->bit_depth_luma_minus8 > 0
461             || m_avcPicParams->bit_depth_chroma_minus8 > 0)
462         {
463             DECODE_ASSERTMESSAGE("Only 4:2:0 8bit is supported!");
464         }
465 
466         return MOS_STATUS_SUCCESS;
467     }
468 
SetRequiredBitstreamSize(uint32_t requiredSize)469     MOS_STATUS AvcBasicFeature::SetRequiredBitstreamSize(uint32_t requiredSize)
470     {
471         DECODE_FUNC_CALL();
472         m_dataSize = requiredSize;
473         DECODE_NORMALMESSAGE("Estimate bitstream size in this Frame: %u", requiredSize);
474         return MOS_STATUS_SUCCESS;
475     }
476 
477 }
478