1 /* 2 * Copyright (c) 2021-2024, 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_scc.cpp 24 //! \brief SCC feature 25 //! 26 27 #include "encode_av1_scc.h" 28 #include "encode_av1_vdenc_const_settings.h" 29 #include "encode_av1_tile.h" 30 #include "encode_av1_segmentation.h" 31 32 namespace encode 33 { 34 Av1Scc(EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings,MediaFeatureManager * featureManager)35 Av1Scc::Av1Scc(EncodeAllocator *allocator, 36 CodechalHwInterfaceNext *hwInterface, 37 void *constSettings, 38 MediaFeatureManager *featureManager) 39 : MediaFeature(constSettings, hwInterface ? hwInterface->GetOsInterface() : nullptr) 40 { 41 ENCODE_FUNC_CALL(); 42 43 ENCODE_CHK_NULL_NO_STATUS_RETURN(featureManager); 44 m_featureManager = featureManager; 45 46 m_basicFeature = dynamic_cast<Av1BasicFeature *>(featureManager->GetFeature(Av1FeatureIDs::basicFeature)); 47 ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature); 48 49 m_segmentation = dynamic_cast<Av1Segmentation *>(featureManager->GetFeature(Av1FeatureIDs::av1Segmentation)); 50 ENCODE_CHK_NULL_NO_STATUS_RETURN(m_segmentation); 51 52 m_allocator = allocator; 53 54 if (hwInterface) 55 { 56 m_osInterface = hwInterface->GetOsInterface(); 57 } 58 } 59 ~Av1Scc()60 Av1Scc::~Av1Scc() 61 { 62 ENCODE_FUNC_CALL(); 63 } 64 CheckIBCParams(const CODEC_AV1_ENCODE_PICTURE_PARAMS & picParams)65 inline MOS_STATUS CheckIBCParams(const CODEC_AV1_ENCODE_PICTURE_PARAMS &picParams) 66 { 67 if (picParams.PicFlags.fields.allow_intrabc) 68 { 69 const auto &lr = picParams.LoopRestorationFlags.fields; 70 if (!AV1_KEY_OR_INRA_FRAME(picParams.PicFlags.fields.frame_type) 71 || picParams.filter_level[0] || picParams.filter_level[1] 72 || picParams.cdef_bits 73 || picParams.PicFlags.fields.use_superres 74 || lr.yframe_restoration_type || lr.cbframe_restoration_type || lr.crframe_restoration_type) 75 { 76 ENCODE_ASSERTMESSAGE("All loop filters MUST be disabled when IBC is enabled"); 77 return MOS_STATUS_INVALID_PARAMETER; 78 } 79 } 80 81 return MOS_STATUS_SUCCESS; 82 } 83 MakeCdfTrackedBufferLockable()84 MOS_STATUS Av1Scc::MakeCdfTrackedBufferLockable() 85 { 86 MOS_ALLOC_GFXRES_PARAMS allocParams; 87 MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS)); 88 allocParams.Type = MOS_GFXRES_BUFFER; 89 allocParams.TileType = MOS_TILE_LINEAR; 90 allocParams.Format = Format_Buffer; 91 allocParams.Flags.bNotLockable = 0; 92 93 allocParams.dwBytes = MOS_ALIGN_CEIL(m_basicFeature->m_cdfMaxNumBytes, CODECHAL_PAGE_SIZE); 94 allocParams.pBufName = "bwdAdaptCdfBuffer"; 95 allocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE; 96 ENCODE_CHK_STATUS_RETURN(m_basicFeature->m_trackedBuf->RegisterParam(encode::BufferType::bwdAdaptCdfBuffer, allocParams)); 97 98 return MOS_STATUS_SUCCESS; 99 } 100 ResetMvProbsToDefault()101 MOS_STATUS Av1Scc::ResetMvProbsToDefault() 102 { 103 PMOS_RESOURCE cdfTrackedBuf = m_basicFeature->m_trackedBuf->GetBuffer(BufferType::bwdAdaptCdfBuffer, 0); 104 ENCODE_CHK_NULL_RETURN(cdfTrackedBuf); 105 106 auto data = (uint16_t *)m_allocator->LockResourceForWrite(cdfTrackedBuf); 107 ENCODE_CHK_NULL_RETURN(data); 108 ENCODE_CHK_STATUS_RETURN(InitDefaultFrameContextBuffer(data, 0, mvJointType, interintra)); 109 ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(cdfTrackedBuf)); 110 111 m_resetMvProbs = false; 112 113 return MOS_STATUS_SUCCESS; 114 } 115 Update(void * params)116 MOS_STATUS Av1Scc::Update(void *params) 117 { 118 ENCODE_FUNC_CALL(); 119 120 EncoderParams *encodeParams = (EncoderParams *)params; 121 ENCODE_CHK_NULL_RETURN(encodeParams); 122 123 auto av1PicParams = static_cast<PCODEC_AV1_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams); 124 ENCODE_CHK_NULL_RETURN(av1PicParams); 125 126 m_enablePalette = av1PicParams->PicFlags.fields.PaletteModeEnable; 127 128 ENCODE_CHK_STATUS_RETURN(CheckIBCParams(*av1PicParams)); 129 130 m_enableIBC = av1PicParams->PicFlags.fields.allow_intrabc; 131 m_IBCPossible = m_IBCPossible || m_enableIBC; 132 133 if (m_resetMvProbs) 134 { 135 ResetMvProbsToDefault(); 136 } 137 138 if (m_IBCPossible && m_basicFeature->m_resolutionChanged) 139 { 140 // Defines 2 sets of MV probabilities: set 0 for regular Inter blocks, set 1 for IBC blocks 141 // HW CDF table contains single set of MV probabilities instead of 2 142 // when IBC is enabled PAK will update MV probabilities during encoding of KEY frame 143 // Inter frame which follows KEY frame requires default (not updated) MV probabilities 144 // CPU-lockable CDF table tracked buffer is needed to reset MV probs back to defaults 145 // tracked buffer is forced to be CPU-lockable 146 ENCODE_CHK_STATUS_RETURN(MakeCdfTrackedBufferLockable()); 147 } 148 149 if (m_enableIBC) 150 { 151 // need to reset MV probs to default values after each KEY frame with IBC enabled 152 m_resetMvProbs = true; 153 if (m_intrabcReconSurface == nullptr) 154 { 155 MOS_ALLOC_GFXRES_PARAMS allocParams; 156 MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS)); 157 allocParams.Type = MOS_GFXRES_2D; 158 allocParams.TileType = MOS_TILE_Y; 159 allocParams.Format = (10 == m_basicFeature->m_bitDepth) ? Format_P010 : Format_NV12; 160 allocParams.dwWidth = MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, av1SuperBlockWidth); 161 allocParams.dwHeight = MOS_ALIGN_CEIL(m_basicFeature->m_frameHeight, av1SuperBlockHeight); 162 allocParams.pBufName = "Intra Block Copy output buffer"; 163 allocParams.bIsCompressible = false; 164 allocParams.CompressionMode = MOS_MMC_DISABLED; 165 166 if (m_basicFeature->m_outputChromaFormat == AVP_CHROMA_FORMAT_YUV444) 167 { 168 if (!m_basicFeature->m_is10Bit) 169 { 170 allocParams.Format = Format_AYUV; 171 allocParams.dwWidth = MOS_ALIGN_CEIL(allocParams.dwWidth, 512 / 4); 172 allocParams.dwHeight = MOS_ALIGN_CEIL(allocParams.dwHeight * 3 / 4, 8); 173 } 174 else 175 { 176 allocParams.Format = Format_Y410; 177 //Y410Viriant surface is same as Y416Viriant 178 allocParams.dwWidth = MOS_ALIGN_CEIL(allocParams.dwWidth, 256 / 4); 179 allocParams.dwHeight = MOS_ALIGN_CEIL(allocParams.dwHeight * 3 / 2, 8); 180 } 181 } 182 else if (m_basicFeature->m_outputChromaFormat == AVP_CHROMA_FORMAT_YUV422) 183 { 184 if (!m_basicFeature->m_is10Bit) 185 { 186 // allocated as YUY2, but used by HW as YUY2 Variant, which is 187 // twice the height and half the width of the YUY2 source surface 188 allocParams.Format = Format_YUY2; 189 allocParams.dwWidth = MOS_ALIGN_CEIL(allocParams.dwWidth >> 1, 128); 190 allocParams.dwHeight = MOS_ALIGN_CEIL(allocParams.dwHeight << 1, 8); 191 } 192 else 193 { 194 // allocated as Y210, but used by HW as Y210 Variant, which is 195 // twice the height and half the width of the Y210 source surface 196 allocParams.Format = Format_Y210; 197 allocParams.dwWidth = MOS_ALIGN_CEIL(allocParams.dwWidth >> 1, 128 >> 1); // HW requires 128 byte aligned width, 2 bytes per pixel 198 allocParams.dwHeight = MOS_ALIGN_CEIL(allocParams.dwHeight << 1, 8); 199 } 200 } 201 202 m_intrabcReconSurface = m_allocator->AllocateSurface(allocParams, false, MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE); 203 m_allocator->GetSurfaceInfo(m_intrabcReconSurface); 204 } 205 } 206 207 ENCODE_CHK_STATUS_RETURN(UpdateIBCStatusForCurrentTile()); 208 209 return MOS_STATUS_SUCCESS; 210 } 211 212 const uint32_t INTRABC_DELAY_SB64 = 4; 213 UpdateIBCStatusForCurrentTile()214 MOS_STATUS Av1Scc::UpdateIBCStatusForCurrentTile() 215 { 216 uint32_t wSB64 = MOS_ROUNDUP_DIVIDE(m_basicFeature->m_frameWidth, 64); 217 218 auto tileFeature = dynamic_cast<Av1EncodeTile *>(m_featureManager->GetFeature(Av1FeatureIDs::encodeTile)); 219 220 if (tileFeature) 221 { 222 Av1TileInfo tileInfo = {}; 223 tileFeature->GetTileInfo(&tileInfo); 224 225 wSB64 = tileInfo.tileWidthInSbMinus1 + 1; 226 } 227 228 m_IBCEnabledForCurrentTile = m_enableIBC && (wSB64 > (INTRABC_DELAY_SB64 + 1)); 229 return MOS_STATUS_SUCCESS; 230 } 231 MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE,Av1Scc)232 MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE, Av1Scc) 233 { 234 bool m_is10Bit = m_basicFeature->m_is10Bit; 235 uint16_t qp = (m_basicFeature->m_av1PicParams->base_qindex) / 4; 236 237 uint8_t tableIdx = 0; 238 if (qp <= 12) 239 tableIdx = 0; 240 else if (qp > 12 && qp <= 17) 241 tableIdx = 1; 242 else if (qp > 17 && qp <= 22) 243 tableIdx = 2; 244 else if (qp > 22 && qp <= 27) 245 tableIdx = 3; 246 else if (qp > 27 && qp <= 32) 247 tableIdx = 4; 248 else if (qp > 32 && qp <= 37) 249 tableIdx = 5; 250 else if (qp > 37 && qp <= 42) 251 tableIdx = 6; 252 else if (qp > 42 && qp <= 47) 253 tableIdx = 7; 254 else if (qp > 47 && qp <= 49) 255 tableIdx = 8; 256 else 257 tableIdx = 9; 258 259 if (m_enablePalette) 260 { 261 params.VdencHEVCVP9TileSlicePar8 = AV1table[tableIdx][0]; 262 params.VdencHEVCVP9TileSlicePar9 = AV1table[tableIdx][1]; 263 params.VdencHEVCVP9TileSlicePar5 = AV1table[tableIdx][2]; 264 params.VdencHEVCVP9TileSlicePar22 = 64; 265 params.paletteModeEnable = 1; 266 267 if (m_is10Bit) 268 { 269 params.VdencHEVCVP9TileSlicePar5 = AV1table[tableIdx][2] + 2; 270 } 271 } 272 273 if (m_IBCEnabledForCurrentTile) 274 { 275 params.ibcControl = IBC_ENABLED; 276 params.VdencHEVCVP9TileSlicePar0 = 0; 277 } 278 279 auto numTiles = m_basicFeature->m_av1PicParams->tile_rows * m_basicFeature->m_av1PicParams->tile_cols; 280 if (numTiles > 1) 281 { 282 auto waTable = m_osInterface->pfnGetWaTable(m_osInterface); 283 if (MEDIA_IS_WA(waTable, Wa_15014143531)) 284 { 285 params.ibcControl = IBC_DISABLED; 286 } 287 } 288 289 return MOS_STATUS_SUCCESS; 290 } 291 MHW_SETPAR_DECL_SRC(VDENC_CMD2,Av1Scc)292 MHW_SETPAR_DECL_SRC(VDENC_CMD2, Av1Scc) 293 { 294 if (m_IBCEnabledForCurrentTile) 295 { 296 params.frameIdxL0Ref0 = 0; 297 } 298 299 #if _MEDIA_RESERVED 300 if (m_IBCEnabledForCurrentTile) 301 { 302 params.vdencCmd2Par3 = vdencCmd2Par3Value2; 303 params.vdencCmd2Par136 = vdencCmd2Par136Value1; 304 params.vdencCmd2Par102 = false; 305 params.vdencCmd2Par101 = false; 306 307 if (params.vdencCmd2Par135[1] == vdencCmd2Par135Value2) 308 { 309 params.vdencCmd2Par135[1] = vdencCmd2Par135Value1; 310 } 311 } 312 313 if (m_segmentation->HasZeroSegmentQIndex()) 314 { 315 params.vdencCmd2Par133 = false; 316 } 317 318 if (m_enablePalette && (m_basicFeature->m_targetUsage == 7)) 319 { 320 params.vdencCmd2Par134[1] = 1; 321 } 322 #else 323 params.extSettings.emplace_back( 324 [this](uint32_t *data) { 325 if (m_IBCEnabledForCurrentTile) 326 { 327 data[2] = data[2] & 0xFFFFFFFC | 0x2; 328 data[37] = data[37] & 0xFFFFFF9F | 0x40; 329 data[54] &= 0xFFFFFF3F; 330 331 if (((data[51] >> 10) & 0b11) == vdencCmd2Par135Value1) 332 { 333 data[51] = data[51] & 0xFFFFF3FF | 0x400; 334 } 335 } 336 337 if (m_segmentation->HasZeroSegmentQIndex()) 338 { 339 data[2] &= 0xFFFFFFBF; 340 } 341 342 if (m_enablePalette && (m_basicFeature->m_targetUsage == 7)) 343 { 344 data[51] = data[51] & 0xFFFFFF3F | 0x40; 345 } 346 347 return MOS_STATUS_SUCCESS; 348 }); 349 #endif // _MEDIA_RESERVED 350 351 return MOS_STATUS_SUCCESS; 352 } 353 MHW_SETPAR_DECL_SRC(VDENC_CMD1,Av1Scc)354 MHW_SETPAR_DECL_SRC(VDENC_CMD1, Av1Scc) 355 { 356 auto setting = static_cast<Av1VdencFeatureSettings*>(m_constSettings); 357 ENCODE_CHK_NULL_RETURN(setting); 358 359 if (m_IBCEnabledForCurrentTile) 360 { 361 362 std::fill_n(¶ms.vdencCmd1Par15[0], 4, (uint8_t)158); 363 std::fill_n(¶ms.vdencCmd1Par14[0], 4, (uint8_t)146); 364 std::fill_n(¶ms.vdencCmd1Par13[0], 4, (uint8_t)146); 365 std::fill_n(¶ms.vdencCmd1Par12[0], 4, (uint8_t)143); 366 std::fill_n(¶ms.vdencCmd1Par11[0], 4, (uint8_t)140); 367 std::fill_n(¶ms.vdencCmd1Par10[0], 4, (uint8_t)134); 368 std::fill_n(¶ms.vdencCmd1Par9[0], 4, (uint8_t)134); 369 std::fill_n(¶ms.vdencCmd1Par8[0], 4, (uint8_t)131); 370 371 params.vdencCmd1Par5 = 8; 372 params.vdencCmd1Par6 = 4; 373 params.vdencCmd1Par7 = 12; 374 375 params.vdencCmd1Par16 = 229; 376 params.vdencCmd1Par17 = 146; 377 params.vdencCmd1Par18 = 230; 378 params.vdencCmd1Par19 = 144; 379 params.vdencCmd1Par20 = 145; 380 381 params.vdencCmd1Par90 = 0; 382 params.vdencCmd1Par91 = 0; 383 params.vdencCmd1Par92 = 0; 384 params.vdencCmd1Par94 = 24; 385 } 386 387 return MOS_STATUS_SUCCESS; 388 } 389 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,Av1Scc)390 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, Av1Scc) 391 { 392 if (m_enableIBC) 393 { 394 params.refs[0] = &m_intrabcReconSurface->OsResource; 395 params.refsDsStage2[0] = nullptr; 396 params.refsDsStage1[0] = nullptr; 397 398 params.numActiveRefL0 = 1; 399 } 400 401 return MOS_STATUS_SUCCESS; 402 } 403 MHW_SETPAR_DECL_SRC(AVP_PIC_STATE,Av1Scc)404 MHW_SETPAR_DECL_SRC(AVP_PIC_STATE, Av1Scc) 405 { 406 if (m_enableIBC || m_enablePalette) 407 { 408 params.allowScreenContentTools = true; 409 params.allowIntraBC = m_enableIBC; 410 411 if (m_enableIBC) 412 { 413 params.enableCDEF = false; 414 params.enableRestoration = false; 415 } 416 } 417 418 return MOS_STATUS_SUCCESS; 419 } 420 MHW_SETPAR_DECL_SRC(AVP_PIPE_BUF_ADDR_STATE,Av1Scc)421 MHW_SETPAR_DECL_SRC(AVP_PIPE_BUF_ADDR_STATE, Av1Scc) 422 { 423 if (m_enableIBC) 424 { 425 params.intrabcDecodedOutputFrameBuffer = &m_intrabcReconSurface->OsResource; 426 } 427 428 return MOS_STATUS_SUCCESS; 429 } 430 MHW_SETPAR_DECL_SRC(AVP_SURFACE_STATE,Av1Scc)431 MHW_SETPAR_DECL_SRC(AVP_SURFACE_STATE, Av1Scc) 432 { 433 MOS_MEMCOMP_STATE mmcState = {}; 434 if (m_enableIBC && params.surfaceStateId == intrabcDecodedFrame) 435 { 436 if (m_basicFeature->m_outputChromaFormat == AVP_CHROMA_FORMAT_YUV420) 437 { 438 params.pitch = m_basicFeature->m_reconSurface.dwPitch; 439 params.uOffset = m_basicFeature->m_reconSurface.YoffsetForUplane; 440 params.vOffset = m_basicFeature->m_reconSurface.YoffsetForVplane; 441 } 442 else if (m_basicFeature->m_outputChromaFormat == AVP_CHROMA_FORMAT_YUV444) 443 { 444 if (!m_basicFeature->m_is10Bit) 445 { 446 params.pitch = m_basicFeature->m_reconSurface.dwPitch / 4; 447 params.uOffset = (uint16_t)m_basicFeature->m_rawSurface.dwHeight; 448 params.vOffset = (uint16_t)m_basicFeature->m_rawSurface.dwHeight << 1; 449 } 450 else 451 { 452 params.pitch = m_basicFeature->m_reconSurface.dwPitch / 2; 453 params.uOffset = (uint16_t)m_basicFeature->m_rawSurface.dwHeight; 454 params.vOffset = (uint16_t)m_basicFeature->m_rawSurface.dwHeight << 1; 455 } 456 } 457 else if (m_basicFeature->m_outputChromaFormat == AVP_CHROMA_FORMAT_YUV422) 458 { 459 params.pitch = m_basicFeature->m_reconSurface.dwPitch; 460 params.uOffset = params.vOffset = m_basicFeature->m_rawSurface.dwHeight; 461 } 462 463 m_basicFeature->GetSurfaceMmcInfo(m_intrabcReconSurface, mmcState, params.compressionFormat); 464 std::fill(std::begin(params.mmcState), std::end(params.mmcState), mmcState); 465 } 466 return MOS_STATUS_SUCCESS; 467 } 468 469 } // namespace encode 470