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