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 encode_av1_segmentation.cpp 24 //! \brief Defines the common interface for encode av1 segmentation feature 25 //! 26 27 #include "encode_av1_segmentation.h" 28 #include "encode_av1_basic_feature.h" 29 #include "encode_av1_stream_in.h" 30 31 namespace encode 32 { Av1Segmentation(MediaFeatureManager * featureManager,EncodeAllocator * allocator,void * constSettings)33 Av1Segmentation::Av1Segmentation( 34 MediaFeatureManager *featureManager, 35 EncodeAllocator *allocator, 36 void *constSettings) : 37 MediaFeature(constSettings), 38 m_allocator(allocator) 39 { 40 ENCODE_FUNC_CALL(); 41 ENCODE_CHK_NULL_NO_STATUS_RETURN(featureManager); 42 43 m_basicFeature = dynamic_cast<Av1BasicFeature *>(featureManager->GetFeature(Av1FeatureIDs::basicFeature)); 44 m_featureManager = featureManager; 45 ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature); 46 } 47 ~Av1Segmentation()48 Av1Segmentation::~Av1Segmentation() 49 { 50 ENCODE_FUNC_CALL(); 51 } 52 GetBlockSize(uint32_t blockSizeId)53 inline uint8_t GetBlockSize(uint32_t blockSizeId) 54 { 55 switch (blockSizeId) 56 { 57 case 0: return 16; 58 case 1: return 32; 59 case 2: return 64; 60 case 3: return 8; 61 default: 62 ENCODE_ASSERTMESSAGE("Block size for segment map must be set"); 63 return 16; 64 } 65 } 66 Update(void * params)67 MOS_STATUS Av1Segmentation::Update(void *params) 68 { 69 ENCODE_FUNC_CALL(); 70 ENCODE_CHK_NULL_RETURN(params); 71 72 EncoderParamsAV1 *encodeParams = (EncoderParamsAV1 *)params; 73 74 const auto av1PicParams = static_cast<PCODEC_AV1_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams); 75 ENCODE_CHK_NULL_RETURN(av1PicParams); 76 77 const auto av1SeqParams = static_cast<PCODEC_AV1_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams); 78 ENCODE_CHK_NULL_RETURN(av1SeqParams); 79 80 m_targetUsage = av1SeqParams->TargetUsage; 81 82 const auto& ddiSegments = av1PicParams->stAV1Segments; 83 84 MOS_ZeroMemory(&m_segmentParams, sizeof(m_segmentParams)); 85 for (auto i = 0; i < av1MaxSegments; i++) 86 { 87 // set QM related to default value. 88 m_segmentParams.m_qmLevelU[i] = m_segmentParams.m_qmLevelV[i] = m_segmentParams.m_qmLevelY[i] = 15; 89 90 if (av1PicParams->wQMatrixFlags.fields.using_qmatrix) 91 { 92 m_segmentParams.m_qmLevelY[i] = av1PicParams->wQMatrixFlags.fields.qm_y; 93 m_segmentParams.m_qmLevelU[i] = av1PicParams->wQMatrixFlags.fields.qm_u; 94 m_segmentParams.m_qmLevelV[i] = av1PicParams->wQMatrixFlags.fields.qm_v; 95 } 96 } 97 98 m_segmentParams.m_enabled = ddiSegments.SegmentFlags.fields.segmentation_enabled; 99 m_segmentParams.m_updateMap = ddiSegments.SegmentFlags.fields.update_map; 100 m_segmentParams.m_temporalUpdate = ddiSegments.SegmentFlags.fields.temporal_update; 101 102 m_segmentNum = ddiSegments.SegmentFlags.fields.SegmentNumber; 103 104 m_segmentMapBlockSize = GetBlockSize(av1PicParams->PicFlags.fields.SegIdBlockSize); 105 106 m_hasZeroSegmentQIndex = false; 107 108 const auto currRefList = m_basicFeature->m_ref.GetCurrRefList(); 109 ENCODE_CHK_NULL_RETURN(currRefList); 110 if (av1PicParams->PicFlags.fields.frame_type == keyFrame) 111 { 112 memset(m_segmenBufferinUse, 0, sizeof(m_segmenBufferinUse)); 113 memset(m_ucScalingIdtoSegID, -1, sizeof(m_ucScalingIdtoSegID)); 114 } 115 if (!m_basicFeature->m_av1PicParams->PicFlags.fields.DisableFrameRecon && 116 m_ucScalingIdtoSegID[currRefList->ucScalingIdx] != -1) 117 { 118 m_segmenBufferinUse[m_ucScalingIdtoSegID[currRefList->ucScalingIdx]]--; 119 } 120 121 if (m_segmentParams.m_enabled) 122 { 123 ENCODE_CHK_STATUS_RETURN(SetSegmentIdParams(av1PicParams, &ddiSegments)); 124 125 m_pSegmentMap = nullptr; 126 m_segmentMapProvided = false; 127 m_segmentMapDataSize = 0; 128 129 if (encodeParams->pSegmentMap) 130 { 131 m_pSegmentMap = encodeParams->pSegmentMap; 132 m_segmentMapProvided = encodeParams->bSegmentMapProvided; 133 m_segmentMapDataSize = encodeParams->segmentMapDataSize; 134 } 135 136 if (m_segmentParams.m_temporalUpdate != 0) 137 { 138 if (!m_segmentParams.m_updateMap) 139 { 140 ENCODE_ASSERTMESSAGE("\"Temporal_update\" is set when \"update_map\" is zero"); 141 return MOS_STATUS_INVALID_PARAMETER; 142 } 143 144 const auto primRefList = m_basicFeature->m_ref.GetPrimaryRefList(); 145 ENCODE_CHK_NULL_RETURN(primRefList); 146 147 const uint8_t ft = av1PicParams->PicFlags.fields.frame_type; 148 if (ft == keyFrame || ft == intraOnlyFrame || !primRefList->m_segmentEnable) 149 { 150 ENCODE_ASSERTMESSAGE("Temporal update for segmentation map cannot be applied"); 151 return MOS_STATUS_INVALID_PARAMETER; 152 } 153 } 154 155 ENCODE_CHK_STATUS_RETURN(CheckQPAndLossless()); 156 157 if (m_segmentMapProvided) 158 { 159 m_streamIn = m_basicFeature->GetStreamIn(); 160 ENCODE_CHK_NULL_RETURN(m_streamIn); 161 ENCODE_CHK_STATUS_RETURN(m_streamIn->Update()); 162 ENCODE_CHK_STATUS_RETURN(SetupSegmentationMap()); 163 } 164 } 165 else 166 { 167 if (m_segmentParams.m_updateData || m_segmentParams.m_temporalUpdate) 168 { 169 ENCODE_ASSERTMESSAGE("\"Update_map\" or \"temporal_update\" is enabled when segmentation is disabled."); 170 return MOS_STATUS_INVALID_PARAMETER; 171 } 172 173 // even if segmentation is disabled, segment params for segment 0 are still passed to HW 174 // lossless flag should be set correctly for segment 0 175 m_segmentParams.m_losslessFlag[0] = IsFrameLossless(*av1PicParams); 176 177 m_hasZeroSegmentQIndex = av1PicParams->base_qindex == 0; 178 } 179 180 return MOS_STATUS_SUCCESS; 181 } 182 CheckQPAndLossless()183 MOS_STATUS Av1Segmentation::CheckQPAndLossless() 184 { 185 ENCODE_FUNC_CALL(); 186 187 const auto* picPar = m_basicFeature->m_av1PicParams; 188 189 ENCODE_CHK_NULL_RETURN(picPar); 190 191 if (IsFrameLossless(*picPar)) 192 { 193 ENCODE_ASSERTMESSAGE("Segmentation can't be enabled for lossless frame."); 194 return MOS_STATUS_INVALID_PARAMETER; 195 } 196 197 for (uint8_t i = 0; i < m_segmentNum; i++) 198 { 199 const int16_t segQP = picPar->base_qindex + m_segmentParams.m_featureData[i][segLvlAltQ]; 200 201 if (segQP < 0) 202 { 203 ENCODE_ASSERTMESSAGE("segQP < 0 is not supported."); 204 return MOS_STATUS_INVALID_PARAMETER; 205 } 206 207 const uint8_t clippedSegQP = static_cast<uint8_t>(CodecHal_Clip3(0, 255, segQP)); 208 209 if (clippedSegQP == 0) 210 { 211 if (DeltaQIsZero(*picPar)) 212 { 213 ENCODE_ASSERTMESSAGE("Lossless segment isn't supported."); 214 return MOS_STATUS_INVALID_PARAMETER; 215 } 216 217 m_hasZeroSegmentQIndex = true; 218 } 219 220 m_segmentParams.m_featureData[i][segLvlAltQ] = clippedSegQP - picPar->base_qindex; 221 } 222 223 return MOS_STATUS_SUCCESS; 224 } 225 SetSegmentIdParams(const PCODEC_AV1_ENCODE_PICTURE_PARAMS ddiPicParams,const CODEC_Intel_Seg_AV1 * ddiSegParams)226 MOS_STATUS Av1Segmentation::SetSegmentIdParams( 227 const PCODEC_AV1_ENCODE_PICTURE_PARAMS ddiPicParams, 228 const CODEC_Intel_Seg_AV1 *ddiSegParams) 229 { 230 ENCODE_FUNC_CALL(); 231 232 ENCODE_CHK_NULL_RETURN(ddiPicParams); 233 ENCODE_CHK_NULL_RETURN(ddiSegParams); 234 ENCODE_CHK_NULL_RETURN(m_basicFeature); 235 236 for (auto i = 0; i < av1MaxSegments; i++) 237 { 238 if (ddiPicParams->wQMatrixFlags.fields.using_qmatrix) 239 { 240 m_segmentParams.m_qmLevelU[i] = ddiPicParams->wQMatrixFlags.fields.qm_u; 241 m_segmentParams.m_qmLevelV[i] = ddiPicParams->wQMatrixFlags.fields.qm_v; 242 m_segmentParams.m_qmLevelY[i] = ddiPicParams->wQMatrixFlags.fields.qm_y; 243 } 244 } 245 246 MOS_SecureMemcpy( 247 m_segmentParams.m_featureData, 248 sizeof(m_segmentParams.m_featureData), 249 ddiSegParams->feature_data, 250 sizeof(m_segmentParams.m_featureData)); 251 252 MOS_SecureMemcpy( 253 m_segmentParams.m_featureMask, 254 sizeof(m_segmentParams.m_featureMask), 255 ddiSegParams->feature_mask, 256 sizeof(m_segmentParams.m_featureMask)); 257 258 for (uint8_t seg = 0; seg < av1MaxSegments; seg++) 259 { 260 for (int lvl = 0; lvl < segLvlMax; lvl++) 261 { 262 if (m_segmentParams.m_featureMask[seg] & (1 << lvl)) 263 { 264 m_segmentParams.m_preSkipSegmentIdFlag |= (lvl >= segLvlRefFrame); 265 m_segmentParams.m_lastActiveSegmentId = seg; 266 } 267 } 268 } 269 270 // Configure Segment ID read buffer and SegmentMapIsZeroFlag 271 m_segmentParams.m_segmentMapIsZeroFlag = false; 272 // pass AVP seg map stream-in only in case of segmentation_temporal_update = 1 273 m_segmentParams.m_segIdBufStreamInEnable = m_segmentParams.m_temporalUpdate ? true : false; 274 // pass AVP seg map stream-out only if segmentation_update_map = 1 275 m_segmentParams.m_segIdBufStreamOutEnable = m_segmentParams.m_updateMap ? true : false; 276 277 const bool usePrimaryMap = !m_segmentParams.m_updateMap || m_segmentParams.m_temporalUpdate; 278 279 if (usePrimaryMap) 280 { 281 if (!m_basicFeature->m_ref.CheckSegmentForPrimeFrame()) 282 { 283 m_segmentParams.m_segmentMapIsZeroFlag = true; 284 m_segmentParams.m_segIdBufStreamInEnable = false; 285 } 286 } 287 288 if (!m_basicFeature->m_av1PicParams->PicFlags.fields.DisableFrameRecon) 289 { 290 const auto currRefList = m_basicFeature->m_ref.GetCurrRefList(); 291 ENCODE_CHK_NULL_RETURN(currRefList); 292 if (!m_segmentParams.m_segIdBufStreamOutEnable) 293 { 294 const auto primRefList = m_basicFeature->m_ref.GetPrimaryRefList(); 295 ENCODE_CHK_NULL_RETURN(primRefList); 296 currRefList->m_segIdBufIdx = primRefList->m_segIdBufIdx; 297 } 298 else 299 { 300 //the maximum DPB length of AV1 is 8, free IDs will always be found. 301 for (uint8_t i = 0; i < av1TotalRefsPerFrame; i++) 302 { 303 if (m_segmenBufferinUse[i] == 0) 304 { 305 currRefList->m_segIdBufIdx = i; 306 break; 307 } 308 } 309 } 310 if (m_segmentMapBuffer[currRefList->m_segIdBufIdx] == nullptr) 311 { 312 ENCODE_CHK_STATUS_RETURN(AllocateSegmentationMapBuffer(currRefList->m_segIdBufIdx)); 313 } 314 m_segmenBufferinUse[currRefList->m_segIdBufIdx]++; 315 m_ucScalingIdtoSegID[currRefList->ucScalingIdx] = currRefList->m_segIdBufIdx; 316 } 317 318 return MOS_STATUS_SUCCESS; 319 } 320 SetupSegmentationMap()321 MOS_STATUS Av1Segmentation::SetupSegmentationMap() 322 { 323 ENCODE_FUNC_CALL(); 324 325 ENCODE_CHK_STATUS_RETURN(CheckSegmentationMap()); 326 327 auto streamInData = m_streamIn->GetStreamInBuffer(); 328 ENCODE_CHK_STATUS_RETURN(FillSegmentationMap((VdencStreamInState *)streamInData)); 329 330 ENCODE_CHK_STATUS_RETURN(m_streamIn->ReturnStreamInBuffer()); 331 332 return MOS_STATUS_SUCCESS; 333 } 334 CheckSegmentationMap() const335 MOS_STATUS Av1Segmentation::CheckSegmentationMap() const 336 { 337 ENCODE_CHK_NULL_RETURN(m_basicFeature->m_av1PicParams); 338 339 auto CurFrameWidth = m_basicFeature->m_av1PicParams->frame_width_minus1 + 1; 340 auto CurFrameHeight = m_basicFeature->m_av1PicParams->frame_height_minus1 + 1; 341 342 const uint32_t segMapPitch = MOS_ALIGN_CEIL(CurFrameWidth, m_segmentMapBlockSize) / m_segmentMapBlockSize; 343 const uint32_t segMapHeight = MOS_ALIGN_CEIL(CurFrameHeight, m_segmentMapBlockSize) / m_segmentMapBlockSize; 344 345 const uint64_t minSegmentMapDataSize = (uint64_t)segMapPitch * (uint64_t)segMapHeight; // 1 byte per segment Id 346 347 if (m_segmentMapDataSize < minSegmentMapDataSize) 348 { 349 ENCODE_ASSERTMESSAGE("Size of segmentation map data provided by app isn't enough for frame resolution"); 350 return MOS_STATUS_INVALID_PARAMETER; 351 } 352 353 return MOS_STATUS_SUCCESS; 354 } 355 ScaleCoord(uint32_t coord,uint32_t oldUnit,uint32_t newUnit)356 inline uint32_t ScaleCoord(uint32_t coord, uint32_t oldUnit, uint32_t newUnit) 357 { 358 ENCODE_ASSERT(newUnit); 359 return (coord * oldUnit) / newUnit; 360 } 361 FillSegmentationMap(VdencStreamInState * streamInData) const362 MOS_STATUS Av1Segmentation::FillSegmentationMap(VdencStreamInState* streamInData) const 363 { 364 ENCODE_FUNC_CALL(); 365 ENCODE_CHK_NULL_RETURN(streamInData); 366 ENCODE_CHK_NULL_RETURN(m_basicFeature->m_av1PicParams); 367 368 const uint8_t blockSize = Av1StreamIn::m_streamInBlockSize; 369 auto CurFrameWidth = m_basicFeature->m_av1PicParams->frame_width_minus1 + 1; 370 auto CurFrameHeight = m_basicFeature->m_av1PicParams->frame_height_minus1 + 1; 371 372 uint16_t FrameWidthInStreamInBlocks = MOS_ALIGN_CEIL(CurFrameWidth, blockSize) / blockSize; 373 uint16_t FrameHeightInStreamInBlocks = MOS_ALIGN_CEIL(CurFrameHeight, blockSize) / blockSize; 374 375 for (int yIdx = 0; yIdx < FrameHeightInStreamInBlocks; yIdx++) 376 { 377 for (uint32_t xIdx = 0; xIdx < FrameWidthInStreamInBlocks; xIdx++) 378 { 379 const uint32_t IdxBlockInStreamIn = m_streamIn->GetCuOffset(xIdx, yIdx); 380 const uint32_t segMapPitch = MOS_ALIGN_CEIL(CurFrameWidth, m_segmentMapBlockSize) / m_segmentMapBlockSize; 381 const uint32_t segMapY = ScaleCoord(yIdx, blockSize, m_segmentMapBlockSize); 382 const uint32_t segMapX = ScaleCoord(xIdx, blockSize, m_segmentMapBlockSize); 383 384 ENCODE_ASSERT(m_pSegmentMap); 385 386 const uint8_t segId = m_pSegmentMap[segMapY * segMapPitch + segMapX]; 387 388 streamInData[IdxBlockInStreamIn].DW7.SegIDEnable = 1; 389 // Minimum size for a SegID is a 32x32 block. 390 // All four 16x16 blocks within a 32x32 should share the same Segmentation ID. 391 streamInData[IdxBlockInStreamIn].DW7.SegID = segId | (segId << 4) | (segId << 8) | (segId << 12); 392 393 } 394 } 395 return MOS_STATUS_SUCCESS; 396 } 397 AllocateSegmentationMapBuffer(uint8_t segmentBufid)398 MOS_STATUS Av1Segmentation::AllocateSegmentationMapBuffer(uint8_t segmentBufid) 399 { 400 if (segmentBufid >= av1TotalRefsPerFrame) 401 { 402 ENCODE_ASSERTMESSAGE("segment map number exceed."); 403 return MOS_STATUS_INVALID_PARAMETER; 404 } 405 if (m_segmentMapBuffer[segmentBufid] != nullptr) 406 { 407 return MOS_STATUS_SUCCESS; 408 } 409 410 uint32_t totalSbPerFrame = (m_basicFeature->m_picWidthInSb) * (m_basicFeature->m_picHeightInSb); 411 const uint16_t num4x4BlocksIn64x64Sb = 256; 412 const uint16_t num4x4BlocksIn128x128Sb = 1024; 413 const uint32_t sizeOfSegmentIdMap = ((m_basicFeature->m_isSb128x128) ? num4x4BlocksIn128x128Sb : num4x4BlocksIn64x64Sb) * totalSbPerFrame; 414 415 MOS_ALLOC_GFXRES_PARAMS allocParams; 416 MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS)); 417 allocParams.Type = MOS_GFXRES_BUFFER; 418 allocParams.TileType = MOS_TILE_LINEAR; 419 allocParams.Format = Format_Buffer; 420 allocParams.Flags.bNotLockable = false; 421 allocParams.dwBytes = sizeOfSegmentIdMap; 422 allocParams.pBufName = "segmentIdStreamOutBuffer"; 423 allocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE; 424 m_segmentMapBuffer[segmentBufid] = m_allocator->AllocateResource(allocParams, false); 425 426 ENCODE_CHK_NULL_RETURN(m_segmentMapBuffer[segmentBufid]); 427 428 return MOS_STATUS_SUCCESS; 429 } 430 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,Av1Segmentation)431 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, Av1Segmentation) 432 { 433 params.segmentMapStreamInBuffer = nullptr; 434 params.segmentMapStreamOutBuffer = nullptr; 435 436 if (m_segmentParams.m_enabled && !m_segmentParams.m_updateMap) 437 { 438 // when segmentation_update_map is 0, send prime_ref_frame's AVP stream out buffer as VDEnc stream in 439 const auto primRefList = m_basicFeature->m_ref.GetPrimaryRefList(); 440 ENCODE_CHK_NULL_RETURN(primRefList); 441 442 params.segmentMapStreamInBuffer = m_segmentMapBuffer[primRefList->m_segIdBufIdx]; 443 } 444 445 return MOS_STATUS_SUCCESS; 446 } 447 MHW_SETPAR_DECL_SRC(AVP_PIC_STATE,Av1Segmentation)448 MHW_SETPAR_DECL_SRC(AVP_PIC_STATE, Av1Segmentation) 449 { 450 MOS_SecureMemcpy( 451 ¶ms.segmentParams, 452 sizeof(params.segmentParams), 453 &m_segmentParams, 454 sizeof(params.segmentParams)); 455 456 if (m_basicFeature->m_av1PicParams->PicFlags.fields.DisableFrameRecon) 457 { 458 params.segmentParams.m_segIdBufStreamOutEnable = false; 459 } 460 461 462 return MOS_STATUS_SUCCESS; 463 } 464 MHW_SETPAR_DECL_SRC(AVP_SEGMENT_STATE,Av1Segmentation)465 MHW_SETPAR_DECL_SRC(AVP_SEGMENT_STATE, Av1Segmentation) 466 { 467 if (m_segmentNum > av1MaxSegments) 468 { 469 ENCODE_ASSERTMESSAGE("The Segment number exceeds the max value."); 470 return MOS_STATUS_USER_CONTROL_MAX_NAME_SIZE; 471 } 472 473 params.numSegments = m_segmentNum; 474 475 MOS_SecureMemcpy( 476 ¶ms.av1SegmentParams, 477 sizeof(params.av1SegmentParams), 478 &m_segmentParams, 479 sizeof(params.av1SegmentParams)); 480 481 return MOS_STATUS_SUCCESS; 482 } 483 MHW_SETPAR_DECL_SRC(AVP_PIPE_BUF_ADDR_STATE,Av1Segmentation)484 MHW_SETPAR_DECL_SRC(AVP_PIPE_BUF_ADDR_STATE, Av1Segmentation) 485 { 486 ENCODE_CHK_NULL_RETURN(m_basicFeature); 487 488 if (m_segmentParams.m_segIdBufStreamInEnable) 489 { 490 const auto primRefList = m_basicFeature->m_ref.GetPrimaryRefList(); 491 ENCODE_CHK_NULL_RETURN(primRefList); 492 ENCODE_CHK_NULL_RETURN(m_segmentMapBuffer[primRefList->m_segIdBufIdx]); 493 params.segmentIdReadBuffer = m_segmentMapBuffer[primRefList->m_segIdBufIdx]; 494 } 495 496 if (!m_basicFeature->m_av1PicParams->PicFlags.fields.DisableFrameRecon && m_segmentParams.m_segIdBufStreamOutEnable) 497 { 498 const auto currRefList = m_basicFeature->m_ref.GetCurrRefList(); 499 ENCODE_CHK_NULL_RETURN(currRefList); 500 ENCODE_CHK_NULL_RETURN(m_segmentMapBuffer[currRefList->m_segIdBufIdx]); 501 params.segmentIdWriteBuffer = m_segmentMapBuffer[currRefList->m_segIdBufIdx]; 502 } 503 504 return MOS_STATUS_SUCCESS; 505 } 506 MHW_SETPAR_DECL_SRC(VDENC_CMD2,Av1Segmentation)507 MHW_SETPAR_DECL_SRC(VDENC_CMD2, Av1Segmentation) 508 { 509 const auto* picPar = m_basicFeature->m_av1PicParams; 510 ENCODE_CHK_NULL_RETURN(picPar); 511 512 params.segmentation = m_segmentParams.m_enabled; 513 514 if (params.segmentation) 515 { 516 // for VP9 VDEnc this is bit used for programming of "segmentation_temporal_update" 517 // for AV1 VDEnc this bit indicates negative of "segmentation_update_map" 518 params.segmentationTemporal = m_segmentParams.m_updateMap ? false : true; 519 #if _MEDIA_RESERVED 520 params.vdencCmd2Par113 = true; 521 #else 522 params.extSettings.emplace_back( 523 [this](uint32_t *data) { 524 data[54] |= 1 << 15; 525 return MOS_STATUS_SUCCESS; 526 }); 527 #endif // _MEDIA_RESERVED 528 } 529 530 for (auto i = 0; i < av1MaxSegments; i++) 531 { 532 if (i < m_segmentNum && 533 m_segmentParams.m_enabled && 534 (m_segmentParams.m_featureMask[i] & 0x1 /*SEG_LVL_ALT_Q*/)) 535 { 536 uint16_t tempSegQp = picPar->base_qindex + m_segmentParams.m_featureData[i][0]; 537 params.qpForSegs[i] = static_cast<uint8_t> (CodecHal_Clip3(1, 255, tempSegQp)); 538 539 #if _MEDIA_RESERVED 540 params.vdencCmd2Par99 = 1; 541 #else 542 params.extSettings.emplace_back( 543 [this](uint32_t *data) { 544 data[54] |= 1; 545 return MOS_STATUS_SUCCESS; 546 }); 547 #endif // _MEDIA_RESERVED 548 } 549 else 550 { 551 params.qpForSegs[i] = static_cast<uint8_t>(picPar->base_qindex); 552 } 553 } 554 555 return MOS_STATUS_SUCCESS; 556 } 557 558 } // namespace encode 559