1 /* 2 * Copyright (c) 2021, 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_vdenc_lpla_analysis.cpp 24 //! \brief Implementation for encode lowpower lookahead(Lookahead Analysis Pass) feature 25 //! 26 27 #include "encode_vdenc_lpla_analysis.h" 28 #include "encode_hevc_vdenc_feature_manager.h" 29 30 namespace encode 31 { VdencLplaAnalysis(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)32 VdencLplaAnalysis::VdencLplaAnalysis( 33 MediaFeatureManager *featureManager, 34 EncodeAllocator *allocator, 35 CodechalHwInterfaceNext *hwInterface, 36 void *constSettings) : 37 MediaFeature(constSettings, hwInterface ? hwInterface->GetOsInterface() : nullptr), 38 m_hwInterface(hwInterface), 39 m_allocator(allocator) 40 { 41 auto encFeatureManager = dynamic_cast<EncodeHevcVdencFeatureManager *>(featureManager); 42 ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager); 43 44 m_basicFeature = dynamic_cast<EncodeBasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature)); 45 ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature); 46 ENCODE_CHK_NULL_NO_STATUS_RETURN(hwInterface); 47 m_osInterface = hwInterface->GetOsInterface(); 48 49 #if (_DEBUG || _RELEASE_INTERNAL) 50 MediaUserSetting::Value outValue; 51 auto statusKey = ReadUserSettingForDebug(m_userSettingPtr, 52 outValue, 53 "lpla ds data address", 54 MediaUserSetting::Group::Sequence); 55 const char *path_buffer = outValue.ConstString().c_str(); 56 57 if (statusKey == MOS_STATUS_SUCCESS && strcmp(path_buffer, "") != 0) 58 m_useDSData = true; 59 60 if (m_useDSData) 61 { 62 std::ifstream fp(path_buffer); 63 if (!fp.is_open()) 64 { 65 m_useDSData = false; 66 ENCODE_ASSERTMESSAGE("lpla ds data load failed!"); 67 return; 68 } 69 70 std::string line = ""; 71 getline(fp, line); 72 for (int i = 0; i < 600; i++) 73 { 74 getline(fp, line); 75 std::string number = ""; 76 std::istringstream readstr(line); 77 getline(readstr, number, ','); 78 getline(readstr, number, ','); 79 getline(readstr, number, ','); 80 m_statsBuffer[i][2] = atoi(number.c_str()); 81 m_statsBuffer[i][2] *= 4; 82 getline(readstr, number, ','); 83 m_statsBuffer[i][0] = atoi(number.c_str()); 84 getline(readstr, number, ','); 85 m_statsBuffer[i][1] = atoi(number.c_str()); 86 m_statsBuffer[i][1] *= 8; 87 } 88 } 89 #endif 90 } 91 ~VdencLplaAnalysis()92 VdencLplaAnalysis::~VdencLplaAnalysis() 93 { 94 if (m_lplaHelper) 95 { 96 MOS_Delete(m_lplaHelper); 97 m_lplaHelper = nullptr; 98 } 99 } 100 Init(void * setting)101 MOS_STATUS VdencLplaAnalysis::Init(void *setting) 102 { 103 ENCODE_FUNC_CALL(); 104 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 105 106 m_hcpItf = m_hwInterface->GetHcpInterfaceNext(); 107 ENCODE_CHK_NULL_RETURN(m_hcpItf); 108 109 m_miItf = m_hwInterface->GetMiInterfaceNext(); 110 ENCODE_CHK_NULL_RETURN(m_miItf); 111 112 m_lplaHelper = MOS_New(EncodeLPLA); 113 ENCODE_CHK_NULL_RETURN(m_lplaHelper); 114 115 ENCODE_CHK_STATUS_RETURN(AllocateResources()); 116 117 return eStatus; 118 } 119 SetSequenceStructs()120 MOS_STATUS VdencLplaAnalysis::SetSequenceStructs() 121 { 122 ENCODE_FUNC_CALL(); 123 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 124 125 if (m_hevcSeqParams->MaxAdaptiveGopPicSize < m_hevcSeqParams->MinAdaptiveGopPicSize) 126 { 127 m_hevcSeqParams->MaxAdaptiveGopPicSize = m_hevcSeqParams->MinAdaptiveGopPicSize; 128 } 129 else if ((m_hevcSeqParams->MaxAdaptiveGopPicSize > 0) && (m_hevcSeqParams->MinAdaptiveGopPicSize == 0)) 130 { 131 m_hevcSeqParams->MinAdaptiveGopPicSize = (m_hevcSeqParams->MaxAdaptiveGopPicSize + 1) >> 1; 132 } 133 134 m_lookaheadAdaptiveI = (m_hevcSeqParams->MaxAdaptiveGopPicSize != m_hevcSeqParams->MinAdaptiveGopPicSize); 135 if (!m_lookaheadAdaptiveI && (m_hevcSeqParams->MaxAdaptiveGopPicSize == 0)) 136 { 137 if (m_hevcSeqParams->GopPicSize > 0) 138 { 139 m_hevcSeqParams->MaxAdaptiveGopPicSize = m_hevcSeqParams->GopPicSize; 140 m_hevcSeqParams->MinAdaptiveGopPicSize = m_hevcSeqParams->GopPicSize; 141 } 142 else 143 { 144 ENCODE_ASSERTMESSAGE("Invalid GopPicSize in LPLA!"); 145 return MOS_STATUS_INVALID_PARAMETER; 146 } 147 } 148 149 ENCODE_CHK_STATUS_RETURN(m_lplaHelper->CheckFrameRate(m_hevcSeqParams->FrameRate.Numerator, 150 m_hevcSeqParams->FrameRate.Denominator, 151 m_hevcSeqParams->TargetBitRate, 152 m_averageFrameSize)); 153 154 ENCODE_CHK_STATUS_RETURN(m_lplaHelper->CheckVBVBuffer(m_hevcSeqParams->VBVBufferSizeInBit, 155 m_hevcSeqParams->InitVBVBufferFullnessInBit)); 156 157 if (m_targetBufferFulness == 0 && m_prevTargetFrameSize == 0) 158 { 159 m_targetBufferFulness = m_hevcSeqParams->VBVBufferSizeInBit - m_hevcSeqParams->InitVBVBufferFullnessInBit; 160 uint32_t initVbvFullnessInFrames = MOS_MIN(m_hevcSeqParams->InitVBVBufferFullnessInBit, m_hevcSeqParams->VBVBufferSizeInBit) / m_averageFrameSize; 161 uint32_t vbvBufferSizeInFrames = m_hevcSeqParams->VBVBufferSizeInBit / m_averageFrameSize; 162 uint32_t encBufferFullness = (vbvBufferSizeInFrames - initVbvFullnessInFrames) * m_averageFrameSize; 163 m_bufferFulnessError = (int32_t)((int64_t)m_targetBufferFulness - (int64_t)encBufferFullness); 164 } 165 166 return eStatus; 167 } 168 EnableStreamIn(bool is1stPass,bool isLastPass,bool & streaminEnabled)169 MOS_STATUS VdencLplaAnalysis::EnableStreamIn(bool is1stPass, bool isLastPass, bool &streaminEnabled) 170 { 171 ENCODE_FUNC_CALL(); 172 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 173 174 if (!m_enabled) 175 { 176 return eStatus; 177 } 178 179 if (m_hevcSeqParams->MaxAdaptiveGopPicSize > 0) 180 { 181 bool forceIntra = m_intraInterval >= m_hevcSeqParams->MaxAdaptiveGopPicSize; 182 if (((!is1stPass && isLastPass) || forceIntra) && (m_hevcPicParams->CodingType != I_TYPE)) 183 { 184 streaminEnabled = true; 185 } 186 187 if (!m_lookaheadAdaptiveI && isLastPass) 188 { 189 m_intraInterval = forceIntra ? 1 : m_intraInterval + 1; 190 } 191 } 192 m_streamInEnabled = m_enabled && streaminEnabled; 193 194 return eStatus; 195 } 196 SetConditionalPass(bool blastPass,bool & condPass)197 MOS_STATUS VdencLplaAnalysis::SetConditionalPass(bool blastPass, bool &condPass) 198 { 199 ENCODE_FUNC_CALL(); 200 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 201 202 if (!m_enabled) 203 { 204 return eStatus; 205 } 206 207 if (m_hevcPicParams->CodingType != I_TYPE && m_lookaheadAdaptiveI) 208 { 209 if (!blastPass) 210 { 211 condPass = false; 212 } 213 } 214 215 return eStatus; 216 } 217 SetupForceIntraStreamIn()218 MOS_STATUS VdencLplaAnalysis::SetupForceIntraStreamIn() 219 { 220 ENCODE_FUNC_CALL(); 221 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 222 223 if (!m_enabled || m_forceIntraSteamInSetupDone) 224 { 225 return eStatus; 226 } 227 228 MOS_LOCK_PARAMS lockFlags; 229 MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS)); 230 lockFlags.WriteOnly = true; 231 232 uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, m_forceIntraStreamInBuf, &lockFlags); 233 ENCODE_CHK_NULL_RETURN(data); 234 235 mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR streaminDataParams; 236 uint32_t streamInWidth = (MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, 64) / 32); 237 uint32_t streamInHeight = (MOS_ALIGN_CEIL(m_basicFeature->m_frameHeight, 64) / 32); 238 239 // lookahead pass should lower QP by 2 to encode force intra frame. 240 MOS_ZeroMemory(&streaminDataParams, sizeof(streaminDataParams)); 241 streaminDataParams.setQpRoiCtrl = true; 242 streaminDataParams.forceQp[0] = m_hevcPicParams->QpY - 2; 243 streaminDataParams.forceQp[1] = m_hevcPicParams->QpY - 2; 244 streaminDataParams.forceQp[2] = m_hevcPicParams->QpY - 2; 245 streaminDataParams.forceQp[3] = m_hevcPicParams->QpY - 2; 246 SetStreaminDataPerRegion(streamInWidth, 0, streamInHeight, 0, streamInWidth, &streaminDataParams, data); 247 248 MOS_ZeroMemory(&streaminDataParams, sizeof(streaminDataParams)); 249 streaminDataParams.puTypeCtrl = 1; //force intra 250 streaminDataParams.maxTuSize = 3; 251 streaminDataParams.maxCuSize = 1; 252 streaminDataParams.numMergeCandidateCu64x64 = 2; 253 streaminDataParams.numMergeCandidateCu32x32 = 2; 254 streaminDataParams.numMergeCandidateCu16x16 = 2; 255 streaminDataParams.numMergeCandidateCu8x8 = 0; 256 streaminDataParams.numImePredictors = 4; 257 258 uint32_t streamInNumCUs = streamInWidth * streamInHeight; 259 for (uint32_t i = 0; i < streamInNumCUs; i++) 260 { 261 SetStreaminDataPerLcu(&streaminDataParams, data + (i * 64)); 262 } 263 264 m_osInterface->pfnUnlockResource(m_osInterface, m_forceIntraStreamInBuf); 265 266 m_forceIntraSteamInSetupDone = true; 267 268 return eStatus; 269 } 270 SetStreaminDataPerRegion(uint32_t streamInWidth,uint32_t top,uint32_t bottom,uint32_t left,uint32_t right,mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR * streaminParams,void * streaminData)271 MOS_STATUS VdencLplaAnalysis::SetStreaminDataPerRegion( 272 uint32_t streamInWidth, uint32_t top, uint32_t bottom, uint32_t left, uint32_t right, 273 mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR *streaminParams, void *streaminData) 274 { 275 ENCODE_FUNC_CALL(); 276 277 uint8_t *data = (uint8_t *)streaminData; 278 279 for (auto y = top; y < bottom; y++) 280 { 281 for (auto x = left; x < right; x++) 282 { 283 //Calculate X Y for the zig zag scan 284 uint32_t offset = 0, xyOffset = 0; 285 StreaminZigZagToLinearMap(streamInWidth, x, y, &offset, &xyOffset); 286 287 SetStreaminDataPerLcu(streaminParams, data + (offset + xyOffset) * 64); 288 } 289 } 290 291 return MOS_STATUS_SUCCESS; 292 } 293 StreaminZigZagToLinearMap(uint32_t streamInWidth,uint32_t x,uint32_t y,uint32_t * offset,uint32_t * xyOffset)294 MOS_STATUS VdencLplaAnalysis::StreaminZigZagToLinearMap( 295 uint32_t streamInWidth, uint32_t x, uint32_t y, 296 uint32_t *offset, uint32_t *xyOffset) 297 { 298 ENCODE_FUNC_CALL(); 299 300 *offset = streamInWidth * y; 301 uint32_t yOffset = 0; 302 uint32_t xOffset = 2 * x; 303 304 //Calculate X Y Offset for the zig zag scan with in each 64x64 LCU 305 //dwOffset gives the 64 LCU row 306 if (y % 2) 307 { 308 *offset = streamInWidth * (y - 1); 309 yOffset = 2; 310 } 311 312 if (x % 2) 313 { 314 xOffset = (2 * x) - 1; 315 } 316 317 *xyOffset = xOffset + yOffset; 318 319 return MOS_STATUS_SUCCESS; 320 } 321 SetStreaminDataPerLcu(mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR * streaminParams,void * streaminData)322 MOS_STATUS VdencLplaAnalysis::SetStreaminDataPerLcu( 323 mhw::vdbox::vdenc::VDENC_STREAMIN_STATE_PAR *streaminParams, 324 void * streaminData) 325 { 326 ENCODE_FUNC_CALL(); 327 328 VdencStreamInState *data = (VdencStreamInState *)streaminData; 329 if (streaminParams->setQpRoiCtrl) 330 { 331 if (0) //(m_vdencNativeROIEnabled || m_brcAdaptiveRegionBoostEnable) 332 { 333 data->DW0.RoiCtrl = streaminParams->roiCtrl; 334 } 335 else 336 { 337 data->DW7.QpEnable = 0xf; 338 data->DW14.ForceQp_0 = streaminParams->forceQp[0]; 339 data->DW14.ForceQp_1 = streaminParams->forceQp[1]; 340 data->DW14.ForceQp_2 = streaminParams->forceQp[2]; 341 data->DW14.ForceQp_3 = streaminParams->forceQp[3]; 342 } 343 } 344 else 345 { 346 data->DW0.MaxTuSize = streaminParams->maxTuSize; 347 data->DW0.MaxCuSize = streaminParams->maxCuSize; 348 data->DW0.NumImePredictors = streaminParams->numImePredictors; 349 data->DW0.PuTypeCtrl = streaminParams->puTypeCtrl; 350 data->DW6.NumMergeCandidateCu64x64 = streaminParams->numMergeCandidateCu64x64; 351 data->DW6.NumMergeCandidateCu32x32 = streaminParams->numMergeCandidateCu32x32; 352 data->DW6.NumMergeCandidateCu16x16 = streaminParams->numMergeCandidateCu16x16; 353 data->DW6.NumMergeCandidateCu8x8 = streaminParams->numMergeCandidateCu8x8; 354 } 355 356 return MOS_STATUS_SUCCESS; 357 } 358 AllocateResources()359 MOS_STATUS VdencLplaAnalysis::AllocateResources() 360 { 361 ENCODE_FUNC_CALL(); 362 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 363 364 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; 365 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); 366 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; 367 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; 368 allocParamsForBufferLinear.Format = Format_Buffer; 369 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE; 370 371 // Buffer to store VDEnc frame statistics for lookahead BRC 372 m_brcLooaheadStatsBufferSize = m_numLaDataEntry * sizeof(VdencHevcLaStats); 373 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_brcLooaheadStatsBufferSize, CODECHAL_PAGE_SIZE); 374 allocParamsForBufferLinear.pBufName = "VDENC Lookahead Statistics Buffer"; 375 m_vdencLaStatsBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true); 376 377 VdencHevcLaStats *lookaheadInfo = (VdencHevcLaStats *)m_allocator->LockResourceForWrite(m_vdencLaStatsBuffer); 378 ENCODE_CHK_NULL_RETURN(lookaheadInfo); 379 MOS_ZeroMemory(lookaheadInfo, allocParamsForBufferLinear.dwBytes); 380 m_allocator->UnLock(m_vdencLaStatsBuffer); 381 382 // Buffer to store lookahead output 383 m_brcLooaheadDataBufferSize = m_numLaDataEntry * sizeof(VdencHevcLaData); 384 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_brcLooaheadDataBufferSize, CODECHAL_PAGE_SIZE); 385 allocParamsForBufferLinear.pBufName = "VDENC Lookahead Data Buffer"; 386 m_vdencLaDataBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true); 387 VdencHevcLaData *lookaheadData = (VdencHevcLaData *)m_allocator->LockResourceForWrite(m_vdencLaDataBuffer); 388 ENCODE_CHK_NULL_RETURN(lookaheadData); 389 MOS_ZeroMemory(lookaheadData, allocParamsForBufferLinear.dwBytes); 390 m_allocator->UnLock(m_vdencLaDataBuffer); 391 392 // Lookahead Init DMEM 393 m_vdencLaInitDmemBufferSize = sizeof(VdencHevcHucLaDmem); 394 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencLaInitDmemBufferSize, CODECHAL_CACHELINE_SIZE); 395 allocParamsForBufferLinear.pBufName = "VDENC Lookahead Init DmemBuffer"; 396 m_vdencLaInitDmemBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true); 397 ENCODE_CHK_NULL_RETURN(m_vdencLaInitDmemBuffer); 398 399 // Lookahead history buffer 400 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_LaHistoryBufSize, CODECHAL_PAGE_SIZE); 401 allocParamsForBufferLinear.pBufName = "VDENC Lookahead History Buffer"; 402 m_vdencLaHistoryBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true); 403 ENCODE_CHK_NULL_RETURN(m_vdencLaHistoryBuffer); 404 405 // Lookahead Update DMEM 406 m_vdencLaUpdateDmemBufferSize = sizeof(VdencHevcHucLaDmem); 407 MOS_RESOURCE *allocatedbuffer; 408 for (auto k = 0; k < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; k++) 409 { 410 for (auto i = 0; i < CODECHAL_LPLA_NUM_OF_PASSES; i++) 411 { 412 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencLaUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE); 413 allocParamsForBufferLinear.pBufName = "VDENC Lookahead update Dmem Buffer"; 414 m_vdencLaUpdateDmemBuffer[k][i] = m_allocator->AllocateResource(allocParamsForBufferLinear, true); 415 ENCODE_CHK_NULL_RETURN(m_vdencLaUpdateDmemBuffer[k][i]); 416 } 417 } 418 419 // streamin Buffer for forced intra encode pass 420 allocParamsForBufferLinear.dwBytes = (MOS_ALIGN_CEIL(m_basicFeature->m_frameWidth, 64) / 32) * (MOS_ALIGN_CEIL(m_basicFeature->m_frameHeight, 64) / 32) * CODECHAL_CACHELINE_SIZE; 421 allocParamsForBufferLinear.pBufName = "ForceIntra Streamin Buffer"; 422 m_forceIntraStreamInBuf = m_allocator->AllocateResource(allocParamsForBufferLinear, true); 423 ENCODE_CHK_NULL_RETURN(m_forceIntraStreamInBuf); 424 425 return eStatus; 426 } 427 Update(void * params)428 MOS_STATUS VdencLplaAnalysis::Update(void *params) 429 { 430 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 431 ENCODE_FUNC_CALL(); 432 433 ENCODE_CHK_NULL_RETURN(params); 434 EncoderParams *encodeParams = (EncoderParams *)params; 435 m_hevcSeqParams = static_cast<PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams); 436 ENCODE_CHK_NULL_RETURN(m_hevcSeqParams); 437 m_lookaheadDepth = m_hevcSeqParams->LookaheadDepth; 438 m_enabled = (m_lookaheadDepth > 0) && m_hevcSeqParams->bLookAheadPhase; 439 if (!m_enabled) 440 { 441 return eStatus; 442 } 443 444 m_hevcPicParams = static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams); 445 ENCODE_CHK_NULL_RETURN(m_hevcPicParams); 446 m_nalUnitParams = encodeParams->ppNALUnitParams; 447 ENCODE_CHK_NULL_RETURN(m_nalUnitParams); 448 m_slcData = (PCODEC_ENCODER_SLCDATA)(encodeParams->pSlcHeaderData); 449 ENCODE_CHK_NULL_RETURN(m_slcData); 450 m_numSlices = encodeParams->dwNumSlices; 451 ENCODE_CHK_STATUS_RETURN(SetSequenceStructs()); 452 m_lastPicInStream = m_hevcPicParams->bLastPicInStream; 453 454 m_hevcSliceParams = static_cast<PCODEC_HEVC_ENCODE_SLICE_PARAMS>(encodeParams->pSliceParams); 455 ENCODE_CHK_STATUS_RETURN(SetupForceIntraStreamIn()); 456 457 if (!m_lastPicInStream) 458 { 459 m_numValidLaRecords++; 460 } 461 462 if (m_lastPicInStream && m_bLastPicFlagFirstIn) 463 { 464 m_currLaDataIdx -= 1; 465 m_bLastPicFlagFirstIn = false; 466 } 467 468 return eStatus; 469 } 470 GetLplaStatusReport(EncodeStatusMfx * encodeStatusMfx,EncodeStatusReportData * statusReportData)471 MOS_STATUS VdencLplaAnalysis::GetLplaStatusReport( 472 EncodeStatusMfx *encodeStatusMfx, 473 EncodeStatusReportData *statusReportData) 474 { 475 ENCODE_FUNC_CALL(); 476 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 477 478 if (!m_enabled) 479 { 480 return eStatus; 481 } 482 483 if (m_lookaheadReport && (encodeStatusMfx->lookaheadStatus.targetFrameSize > 0)) 484 { 485 statusReportData->pLookaheadStatus = &encodeStatusMfx->lookaheadStatus; 486 encodeStatusMfx->lookaheadStatus.isValid = 1; 487 uint64_t targetFrameSize = (uint64_t)encodeStatusMfx->lookaheadStatus.targetFrameSize * m_averageFrameSize; 488 encodeStatusMfx->lookaheadStatus.targetFrameSize = (uint32_t)((targetFrameSize + (32 * 8)) / (64 * 8)); // Convert bits to bytes. 64 is normalized average frame size used in lookahead analysis kernel 489 uint64_t targetBufferFulness = (uint64_t)encodeStatusMfx->lookaheadStatus.targetBufferFulness * m_averageFrameSize; 490 encodeStatusMfx->lookaheadStatus.targetBufferFulness = (uint32_t)((targetBufferFulness + 32) / 64); // 64 is normalized average frame size used in lookahead analysis kernel 491 492 if (encodeStatusMfx->lookaheadStatus.miniGopSize == 2) 493 { 494 encodeStatusMfx->lookaheadStatus.miniGopSize = 2; 495 } 496 else if (encodeStatusMfx->lookaheadStatus.pyramidDeltaQP == 0) 497 { 498 encodeStatusMfx->lookaheadStatus.miniGopSize = 1; 499 } 500 else 501 { 502 if (m_hevcSeqParams->GopRefDist == 1) // LPLA only supports P pyramid for this condition 503 { 504 encodeStatusMfx->lookaheadStatus.miniGopSize = 4; 505 } 506 else 507 { 508 encodeStatusMfx->lookaheadStatus.miniGopSize = m_hevcSeqParams->GopRefDist; 509 } 510 } 511 } 512 513 return eStatus; 514 } 515 516 #if USE_CODECHAL_DEBUG_TOOL DumpLaResource(EncodePipeline * pipeline,bool isInput)517 MOS_STATUS VdencLplaAnalysis::DumpLaResource(EncodePipeline *pipeline, bool isInput) 518 { 519 ENCODE_FUNC_CALL(); 520 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 521 522 if (!m_enabled) 523 { 524 return eStatus; 525 } 526 527 CodechalDebugInterface *debugInterface = pipeline->GetDebugInterface(); 528 ENCODE_CHK_NULL_RETURN(debugInterface); 529 int32_t currentPass = pipeline->GetCurrentPass(); 530 531 ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucDmem( 532 m_vdencLaUpdateDmemBuffer[pipeline->m_currRecycledBufIdx][currentPass], 533 sizeof(VdencHevcHucLaDmem), 534 currentPass, 535 hucRegionDumpLAUpdate)); 536 537 ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucRegion( 538 m_vdencLaHistoryBuffer, 539 0, 540 m_LaHistoryBufSize, 541 0, 542 "_History", 543 isInput, 544 currentPass, 545 hucRegionDumpLAUpdate)); 546 547 ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucRegion( 548 m_vdencLaStatsBuffer, 549 0, 550 m_brcLooaheadStatsBufferSize, 551 1, 552 "_Stats", 553 isInput, 554 currentPass, 555 hucRegionDumpLAUpdate)); 556 557 ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucRegion( 558 m_vdencLaDataBuffer, 559 0, 560 m_brcLooaheadDataBufferSize, 561 2, 562 "_Data", 563 isInput, 564 currentPass, 565 hucRegionDumpLAUpdate)); 566 567 return eStatus; 568 } 569 #endif 570 GetLaStatsStoreIdx(uint8_t & index)571 MOS_STATUS VdencLplaAnalysis::GetLaStatsStoreIdx(uint8_t &index) 572 { 573 ENCODE_FUNC_CALL(); 574 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 575 576 index = m_currLaDataIdx; 577 578 return eStatus; 579 } 580 StoreLookaheadStatistics(MOS_COMMAND_BUFFER & cmdBuffer,MHW_VDBOX_NODE_IND vdboxIndex)581 MOS_STATUS VdencLplaAnalysis::StoreLookaheadStatistics(MOS_COMMAND_BUFFER &cmdBuffer, MHW_VDBOX_NODE_IND vdboxIndex) 582 { 583 ENCODE_FUNC_CALL(); 584 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 585 586 if (!m_enabled) 587 { 588 return eStatus; 589 } 590 591 uint8_t index = 0; 592 ENCODE_CHK_STATUS_RETURN(GetLaStatsStoreIdx(index)); 593 uint32_t offset = sizeof(VdencHevcLaStats) * index; 594 if (m_useDSData) 595 { 596 auto &storeFrameByteCount = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)(); 597 storeFrameByteCount = {}; 598 storeFrameByteCount.pOsResource = m_vdencLaStatsBuffer; 599 storeFrameByteCount.dwResourceOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, frameByteCount); 600 storeFrameByteCount.dwValue = m_statsBuffer[index][0]; 601 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer)); 602 603 auto &storeHeaderBitCount = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)(); 604 storeHeaderBitCount = {}; 605 storeHeaderBitCount.pOsResource = m_vdencLaStatsBuffer; 606 storeHeaderBitCount.dwResourceOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, headerBitCount); 607 storeHeaderBitCount.dwValue = m_statsBuffer[index][1]; 608 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer)); 609 610 auto &storeIntraCuCount = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)(); 611 storeIntraCuCount = {}; 612 storeIntraCuCount.pOsResource = m_vdencLaStatsBuffer; 613 storeIntraCuCount.dwResourceOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, intraCuCount); 614 storeIntraCuCount.dwValue = m_statsBuffer[index][2]; 615 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer)); 616 617 auto &flushDwParams = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)(); 618 flushDwParams = {}; 619 // Make Flush DW call to make sure all previous work is done 620 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer)); 621 } 622 else 623 { 624 auto &miStoreRegMemParams = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)(); 625 auto &miLoadRegMemParams = m_miItf->MHW_GETPAR_F(MI_LOAD_REGISTER_MEM)(); 626 auto &flushDwParams = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)(); 627 628 miStoreRegMemParams = {}; 629 miLoadRegMemParams = {}; 630 flushDwParams = {}; 631 632 auto mmioRegistersHcp = m_hcpItf->GetMmioRegisters(vdboxIndex); 633 miStoreRegMemParams.dwRegister = mmioRegistersHcp->hcpEncBitstreamBytecountFrameRegOffset; 634 // Store BitstreamBytecount to m_vdencLaStatsBuffer 635 miStoreRegMemParams.presStoreBuffer = m_vdencLaStatsBuffer; 636 miStoreRegMemParams.dwOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, frameByteCount); 637 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(&cmdBuffer)); 638 639 // Calculate header size including LCU header 640 uint32_t headerBitSize = 0; 641 for (uint32_t i = 0; i < HEVC_MAX_NAL_UNIT_TYPE; i++) 642 { 643 headerBitSize += m_nalUnitParams[i]->uiSize * 8; 644 } 645 for (uint32_t i = 0; i < m_numSlices; i++) 646 { 647 headerBitSize += m_slcData[i].BitSize; 648 } 649 650 // Store headerBitCount to m_vdencLaStatsBuffer 651 auto &storeDataParams = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)(); 652 storeDataParams = {}; 653 storeDataParams.pOsResource = m_vdencLaStatsBuffer; 654 storeDataParams.dwResourceOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, headerBitCount); 655 storeDataParams.dwValue = headerBitSize; 656 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer)); 657 658 auto mmioRegs = m_miItf->GetMmioRegisters(); 659 ENCODE_CHK_NULL_RETURN(mmioRegs); 660 // VCS_GPR0_Lo = LCUHdrBits 661 miLoadRegMemParams.presStoreBuffer = m_basicFeature->m_recycleBuf->GetBuffer(FrameStatStreamOutBuffer, 0); // LCUHdrBits is in m_resFrameStatStreamOutBuffer DW4 662 miLoadRegMemParams.dwOffset = 4 * sizeof(uint32_t); 663 miLoadRegMemParams.dwRegister = mmioRegs->generalPurposeRegister0LoOffset; // VCS_GPR0_Lo 664 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_LOAD_REGISTER_MEM)(&cmdBuffer)); 665 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer)); 666 667 // load headerBitCount(in m_vdencLaStatsBuffer) to VCS_GPR4_Lo 668 miLoadRegMemParams.presStoreBuffer = m_vdencLaStatsBuffer; 669 miLoadRegMemParams.dwOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, headerBitCount); 670 miLoadRegMemParams.dwRegister = mmioRegs->generalPurposeRegister4LoOffset; 671 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_LOAD_REGISTER_MEM)(&cmdBuffer)); 672 673 mhw::mi::MHW_MI_ALU_PARAMS aluParams[4] = {}; 674 int32_t aluCount = 0; 675 676 //load1 srca, reg1 677 aluParams[aluCount].AluOpcode = MHW_MI_ALU_LOAD; 678 aluParams[aluCount].Operand1 = MHW_MI_ALU_SRCA; 679 aluParams[aluCount].Operand2 = MHW_MI_ALU_GPREG0; 680 ++aluCount; 681 682 //load2 srcb, reg2 683 aluParams[aluCount].AluOpcode = MHW_MI_ALU_LOAD; 684 aluParams[aluCount].Operand1 = MHW_MI_ALU_SRCB; 685 aluParams[aluCount].Operand2 = MHW_MI_ALU_GPREG4; 686 ++aluCount; 687 688 //add srca + srcb 689 aluParams[aluCount].AluOpcode = MHW_MI_ALU_ADD; 690 ++aluCount; 691 692 //store reg1, accu 693 aluParams[aluCount].AluOpcode = MHW_MI_ALU_STORE; 694 aluParams[aluCount].Operand1 = MHW_MI_ALU_GPREG0; 695 aluParams[aluCount].Operand2 = MHW_MI_ALU_ACCU; 696 ++aluCount; 697 698 auto &miMathParams = m_miItf->MHW_GETPAR_F(MI_MATH)(); 699 miMathParams = {}; 700 miMathParams.dwNumAluParams = aluCount; 701 miMathParams.pAluPayload = aluParams; 702 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_MATH)(&cmdBuffer)); 703 704 //store VCS_GPR0_Lo to m_vdencLaStatsBuffer 705 miStoreRegMemParams.presStoreBuffer = m_vdencLaStatsBuffer; 706 miStoreRegMemParams.dwOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, headerBitCount); 707 miStoreRegMemParams.dwRegister = mmioRegs->generalPurposeRegister0LoOffset; 708 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(&cmdBuffer)); 709 710 // Make Flush DW call to make sure all previous work is done 711 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer)); 712 713 ENCODE_CHK_STATUS_RETURN(StoreVdencStatistics(cmdBuffer, index)); 714 } 715 return eStatus; 716 } 717 StoreVdencStatistics(MOS_COMMAND_BUFFER & cmdBuffer,uint8_t index)718 MOS_STATUS VdencLplaAnalysis::StoreVdencStatistics(MOS_COMMAND_BUFFER &cmdBuffer, uint8_t index) 719 { 720 ENCODE_FUNC_CALL(); 721 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 722 723 uint32_t offset = sizeof(VdencHevcLaStats) * index; 724 auto &miCpyMemMemParams = m_miItf->MHW_GETPAR_F(MI_COPY_MEM_MEM)(); 725 miCpyMemMemParams = {}; 726 miCpyMemMemParams.presSrc = m_basicFeature->m_recycleBuf->GetBuffer(VdencStatsBuffer, 0); // 8X8 Normalized intra CU count is in m_resVdencStatsBuffer DW1 727 miCpyMemMemParams.dwSrcOffset = 4; 728 miCpyMemMemParams.presDst = m_vdencLaStatsBuffer; 729 miCpyMemMemParams.dwDstOffset = offset + CODECHAL_OFFSETOF(VdencHevcLaStats, intraCuCount); 730 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(&cmdBuffer)); 731 732 return eStatus; 733 } 734 ReadLPLAData(PMOS_COMMAND_BUFFER cmdBuffer,PMOS_RESOURCE resource,uint32_t baseOffset)735 MOS_STATUS VdencLplaAnalysis::ReadLPLAData(PMOS_COMMAND_BUFFER cmdBuffer, PMOS_RESOURCE resource, uint32_t baseOffset) 736 { 737 ENCODE_FUNC_CALL(); 738 739 // Write lookahead status to encode status buffer 740 auto &miCpyMemMemParams = m_miItf->MHW_GETPAR_F(MI_COPY_MEM_MEM)(); 741 auto &flushDwParams = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)(); 742 743 miCpyMemMemParams = {}; 744 miCpyMemMemParams.presSrc = m_vdencLaDataBuffer; 745 miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, encodeHints); 746 miCpyMemMemParams.presDst = resource; 747 miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, encodeHints); 748 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer)); 749 miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, targetFrameSize); 750 miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, targetFrameSize); 751 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer)); 752 miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, targetBufferFulness); 753 miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, targetBufferFulness); 754 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer)); 755 miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, pyramidDeltaQP); 756 miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, pyramidDeltaQP); 757 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer)); 758 //MI_COPY_MEM_MEM reads a DWord from memory and stores it to memory. This copy will include adaptive_rounding and minigop 759 miCpyMemMemParams.dwSrcOffset = m_offset * sizeof(CodechalVdencHevcLaData) + CODECHAL_OFFSETOF(CodechalVdencHevcLaData, adaptive_rounding); 760 miCpyMemMemParams.dwDstOffset = baseOffset + CODECHAL_OFFSETOF(LookaheadReport, adaptive_rounding); 761 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_COPY_MEM_MEM)(cmdBuffer)); 762 763 flushDwParams = {}; 764 ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(cmdBuffer)); 765 766 return MOS_STATUS_SUCCESS; 767 } 768 SetLaUpdateDmemParameters(HUC_DMEM_STATE_PAR_ALIAS & params,uint8_t currRecycledBufIdx,uint16_t curPass,uint16_t numPasses)769 MOS_STATUS VdencLplaAnalysis::SetLaUpdateDmemParameters(HUC_DMEM_STATE_PAR_ALIAS ¶ms, uint8_t currRecycledBufIdx, uint16_t curPass, uint16_t numPasses) 770 { 771 ENCODE_FUNC_CALL(); 772 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 773 774 if (!m_enabled) 775 { 776 return eStatus; 777 } 778 779 ENCODE_CHK_STATUS_RETURN(SetLaUpdateDmemBuffer(currRecycledBufIdx, m_currLaDataIdx, m_numValidLaRecords, curPass, numPasses)); 780 781 params.hucDataSource = m_vdencLaUpdateDmemBuffer[currRecycledBufIdx][curPass]; 782 params.dataLength = MOS_ALIGN_CEIL(m_vdencLaUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE); 783 params.dmemOffset = HUC_DMEM_OFFSET_RTOS_GEMS; 784 785 return eStatus; 786 } 787 UpdateLaDataIdx()788 MOS_STATUS VdencLplaAnalysis::UpdateLaDataIdx() 789 { 790 ENCODE_FUNC_CALL(); 791 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 792 793 if (!m_lastPicInStream) 794 { 795 m_currLaDataIdx = (m_currLaDataIdx + 1) % m_numLaDataEntry; 796 } 797 798 return eStatus; 799 } 800 SetLaInitDmemBuffer() const801 MOS_STATUS VdencLplaAnalysis::SetLaInitDmemBuffer() const 802 { 803 ENCODE_FUNC_CALL(); 804 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 805 806 // Setup LAInit DMEM 807 auto hucVdencLaInitDmem = (VdencHevcHucLaDmem *)m_allocator->LockResourceForWrite(m_vdencLaInitDmemBuffer); 808 ENCODE_CHK_NULL_RETURN(hucVdencLaInitDmem); 809 MOS_ZeroMemory(hucVdencLaInitDmem, sizeof(VdencHevcHucLaDmem)); 810 811 uint32_t initVbvFullness = MOS_MIN(m_hevcSeqParams->InitVBVBufferFullnessInBit, m_hevcSeqParams->VBVBufferSizeInBit); 812 uint8_t downscaleRatioIndicator = 2; // 4x downscaling 813 if (m_hevcPicParams->DownScaleRatio.fields.X16Minus1_X == 15 && m_hevcPicParams->DownScaleRatio.fields.X16Minus1_Y == 15) 814 { 815 downscaleRatioIndicator = 0; // no downscaling 816 } 817 818 hucVdencLaInitDmem->lookAheadFunc = 0; 819 hucVdencLaInitDmem->lengthAhead = m_hevcSeqParams->LookaheadDepth; 820 hucVdencLaInitDmem->vbvBufferSize = m_hevcSeqParams->VBVBufferSizeInBit / m_averageFrameSize; 821 hucVdencLaInitDmem->vbvInitialFullness = initVbvFullness / m_averageFrameSize; 822 hucVdencLaInitDmem->statsRecords = m_numLaDataEntry; 823 hucVdencLaInitDmem->averageFrameSize = m_averageFrameSize >> 3; 824 hucVdencLaInitDmem->downscaleRatio = downscaleRatioIndicator; 825 ENCODE_CHK_NULL_RETURN(m_basicFeature); 826 hucVdencLaInitDmem->enc_frame_width = m_basicFeature->m_frameWidth; 827 hucVdencLaInitDmem->enc_frame_height = m_basicFeature->m_frameHeight; 828 hucVdencLaInitDmem->codec_type = m_hevcSeqParams->FullPassCodecType; 829 hucVdencLaInitDmem->mbr_ratio = (m_hevcSeqParams->TargetBitRate > 0 && m_hevcSeqParams->MaxBitRate >= m_hevcSeqParams->TargetBitRate) ? 830 m_hevcSeqParams->MaxBitRate * 100 / m_hevcSeqParams->TargetBitRate : 100; 831 832 if (m_hevcSeqParams->GopRefDist == 1) 833 { 834 hucVdencLaInitDmem->PGop = 4; 835 } 836 else 837 { 838 hucVdencLaInitDmem->BGop = m_hevcSeqParams->GopRefDist; 839 hucVdencLaInitDmem->maxGop = m_hevcSeqParams->GopPicSize; 840 } 841 842 hucVdencLaInitDmem->GopOpt = m_hevcSeqParams->GopFlags.fields.StrictGop ? 2 : m_hevcSeqParams->GopFlags.fields.ClosedGop; 843 hucVdencLaInitDmem->AGop = m_hevcSeqParams->GopFlags.fields.AdaptiveGop; 844 if (m_hevcSeqParams->GopFlags.fields.AdaptiveGop) 845 { 846 hucVdencLaInitDmem->AGop_Threshold = 16; 847 } 848 hucVdencLaInitDmem->maxGop = m_hevcSeqParams->MaxAdaptiveGopPicSize; 849 hucVdencLaInitDmem->minGop = m_hevcSeqParams->MinAdaptiveGopPicSize; 850 hucVdencLaInitDmem->adaptiveIDR = (uint8_t)m_lookaheadAdaptiveI; 851 hucVdencLaInitDmem->la_dump_type = 4; 852 853 m_allocator->UnLock(m_vdencLaInitDmemBuffer); 854 855 return eStatus; 856 } 857 SetLaUpdateDmemBuffer(uint8_t currRecycledBufIdx,uint8_t currLaDataIdx,uint32_t numValidLaRecords,uint16_t curPass,uint16_t numPasses)858 MOS_STATUS VdencLplaAnalysis::SetLaUpdateDmemBuffer(uint8_t currRecycledBufIdx, uint8_t currLaDataIdx, uint32_t numValidLaRecords, uint16_t curPass, uint16_t numPasses) 859 { 860 ENCODE_FUNC_CALL(); 861 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 862 863 // Setup LAUpdate DMEM 864 auto hucVdencLaUpdateDmem = (VdencHevcHucLaDmem *)m_allocator->LockResourceForWrite(m_vdencLaUpdateDmemBuffer[currRecycledBufIdx][curPass]); 865 ENCODE_CHK_NULL_RETURN(hucVdencLaUpdateDmem); 866 MOS_ZeroMemory(hucVdencLaUpdateDmem, sizeof(VdencHevcHucLaDmem)); 867 868 hucVdencLaUpdateDmem->lookAheadFunc = 1; 869 hucVdencLaUpdateDmem->validStatsRecords = numValidLaRecords; 870 hucVdencLaUpdateDmem->offset = m_offset = (m_numLaDataEntry + currLaDataIdx + 1 - numValidLaRecords) % m_numLaDataEntry; 871 hucVdencLaUpdateDmem->cqmQpThreshold = m_cqmQpThreshold; 872 hucVdencLaUpdateDmem->currentPass = (uint8_t)curPass; 873 874 m_allocator->UnLock(m_vdencLaUpdateDmemBuffer[currRecycledBufIdx][curPass]); 875 876 return eStatus; 877 } 878 SetVdencPipeBufAddrParams(bool enableStreamIn,MHW_VDBOX_PIPE_BUF_ADDR_PARAMS & pipeBufAddrParams)879 MOS_STATUS VdencLplaAnalysis::SetVdencPipeBufAddrParams(bool enableStreamIn, MHW_VDBOX_PIPE_BUF_ADDR_PARAMS &pipeBufAddrParams) 880 { 881 ENCODE_FUNC_CALL(); 882 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 883 884 if (!m_enabled) 885 { 886 return eStatus; 887 } 888 889 if (enableStreamIn) 890 { 891 pipeBufAddrParams.presVdencStreamInBuffer = m_forceIntraStreamInBuf; 892 } 893 894 return eStatus; 895 } 896 IsLaAnalysisRequired()897 bool VdencLplaAnalysis::IsLaAnalysisRequired() 898 { 899 return m_enabled; 900 } 901 IsLaRecordsEmpty()902 bool VdencLplaAnalysis::IsLaRecordsEmpty() 903 { 904 if (!m_numValidLaRecords) 905 { 906 return true; 907 } 908 m_numValidLaRecords--; 909 return false; 910 } 911 CalculateLaRecords(bool blastPass)912 MOS_STATUS VdencLplaAnalysis::CalculateLaRecords(bool blastPass) 913 { 914 ENCODE_FUNC_CALL(); 915 916 if ((blastPass && m_numValidLaRecords >= m_lookaheadDepth) || 917 (m_lastPicInStream && m_numValidLaRecords)) 918 { 919 m_numValidLaRecords--; 920 m_lookaheadReport = true; 921 } 922 return MOS_STATUS_SUCCESS; 923 } 924 MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT,VdencLplaAnalysis)925 MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, VdencLplaAnalysis) 926 { 927 ENCODE_FUNC_CALL(); 928 929 params.frameStatisticsStreamOut = m_enabled ? true : params.frameStatisticsStreamOut; 930 931 return MOS_STATUS_SUCCESS; 932 } 933 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,VdencLplaAnalysis)934 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, VdencLplaAnalysis) 935 { 936 ENCODE_FUNC_CALL(); 937 938 if (m_streamInEnabled) 939 { 940 params.streamInBuffer = m_forceIntraStreamInBuf; 941 } 942 943 return MOS_STATUS_SUCCESS; 944 } 945 MHW_SETPAR_DECL_SRC(VDENC_CMD2,VdencLplaAnalysis)946 MHW_SETPAR_DECL_SRC(VDENC_CMD2, VdencLplaAnalysis) 947 { 948 ENCODE_FUNC_CALL(); 949 950 if (m_streamInEnabled) 951 { 952 params.vdencStreamIn = true; 953 } 954 955 return MOS_STATUS_SUCCESS; 956 } 957 MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,VdencLplaAnalysis)958 MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, VdencLplaAnalysis) 959 { 960 ENCODE_FUNC_CALL(); 961 962 if (params.function == LA_INIT) 963 { 964 ENCODE_CHK_STATUS_RETURN(SetLaInitDmemBuffer()); 965 966 params.hucDataSource = m_vdencLaInitDmemBuffer; 967 params.dataLength = MOS_ALIGN_CEIL(m_vdencLaInitDmemBufferSize, CODECHAL_CACHELINE_SIZE); 968 params.dmemOffset = HUC_DMEM_OFFSET_RTOS_GEMS; 969 } 970 971 return MOS_STATUS_SUCCESS; 972 } 973 MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,VdencLplaAnalysis)974 MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, VdencLplaAnalysis) 975 { 976 ENCODE_FUNC_CALL(); 977 978 switch (params.function) 979 { 980 case LA_INIT: 981 { 982 params.regionParams[0].presRegion = m_vdencLaHistoryBuffer; 983 params.regionParams[0].isWritable = true; 984 m_lookaheadInit = false; 985 986 break; 987 } 988 case LA_UPDATE: 989 { 990 params.regionParams[0].presRegion = m_vdencLaHistoryBuffer; 991 params.regionParams[0].isWritable = true; 992 params.regionParams[1].presRegion = m_vdencLaStatsBuffer; 993 params.regionParams[2].presRegion = m_vdencLaDataBuffer; 994 params.regionParams[2].isWritable = true; 995 996 break; 997 } 998 default: 999 break; 1000 } 1001 1002 return MOS_STATUS_SUCCESS; 1003 } 1004 1005 } //encode 1006