1 /* 2 * Copyright (c) 2018-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_status_reporte.cpp 24 //! \brief Defines the common interface for encode status reporter 25 //! \details 26 //! 27 #include <cmath> 28 #include "encode_status_report.h" 29 30 namespace encode { 31 32 const uint32_t EncoderStatusReport::m_codecFuncToFuncIdPairs[m_maxCodecFuncNum] = 33 { 34 0, 35 CODECHAL_ENCODE_ENC_ID, 36 CODECHAL_ENCODE_PAK_ID, 37 CODECHAL_ENCODE_ENC_PAK_ID, 38 CODECHAL_ENCODE_ENC_ID, 39 CODECHAL_ENCODE_ENC_PAK_ID, 40 0, 41 0, 42 CODECHAL_ENCODE_FEI_PRE_ENC_ID, 43 CODECHAL_ENCODE_FEI_ENC_ID, 44 CODECHAL_ENCODE_FEI_PAK_ID, 45 CODECHAL_ENCODE_FEI_ENC_PAK_ID 46 }; 47 EncoderStatusReport(EncodeAllocator * allocator,PMOS_INTERFACE pOsInterface,bool enableMfx,bool enableRcs,bool enablecp)48 EncoderStatusReport::EncoderStatusReport( 49 EncodeAllocator *allocator, PMOS_INTERFACE pOsInterface, bool enableMfx, bool enableRcs, bool enablecp): 50 m_osInterface(pOsInterface), 51 m_enableMfx(enableMfx), 52 m_enableRcs(enableRcs), 53 m_enableCp(enablecp), 54 m_allocator(allocator) 55 { 56 m_sizeOfReport = sizeof(EncodeStatusReportData); 57 } 58 ~EncoderStatusReport()59 EncoderStatusReport::~EncoderStatusReport() 60 { 61 Destroy(); 62 } 63 Create()64 MOS_STATUS EncoderStatusReport::Create() 65 { 66 ENCODE_FUNC_CALL(); 67 68 MOS_ALLOC_GFXRES_PARAMS param; 69 MOS_ZeroMemory(¶m, sizeof(MOS_ALLOC_GFXRES_PARAMS)); 70 param.Type = MOS_GFXRES_BUFFER; 71 param.TileType = MOS_TILE_LINEAR; 72 param.Format = Format_Buffer; 73 param.dwBytes = sizeof(uint32_t) * 2; 74 param.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE; 75 param.pBufName = "StatusQueryBufferGlobalCount"; 76 // keeping status buffer persistent since its used in all command buffers 77 param.bIsPersistent = true; 78 79 m_completedCountBuf = m_allocator->AllocateResource(param, true); 80 ENCODE_CHK_STATUS_RETURN(m_allocator->SkipResourceSync(m_completedCountBuf)); 81 82 m_completedCount = (uint32_t *)m_allocator->LockResourceForRead(m_completedCountBuf); 83 ENCODE_CHK_NULL_RETURN(m_completedCount); 84 85 if (m_enableMfx) 86 { 87 param.dwBytes = m_statusBufSizeMfx * CODECHAL_ENCODE_STATUS_NUM; 88 param.pBufName = "StatusQueryBufferMfx"; 89 // keeping status buffer persistent since its used in all command buffers 90 param.bIsPersistent = true; 91 m_statusBufMfx = m_allocator->AllocateResource(param, true); 92 ENCODE_CHK_STATUS_RETURN(m_allocator->SkipResourceSync(m_statusBufMfx)); 93 94 m_dataStatusMfx = (uint8_t *)m_allocator->LockResourceForRead(m_statusBufMfx); 95 ENCODE_CHK_NULL_RETURN(m_dataStatusMfx); 96 } 97 98 if (m_enableRcs) 99 { 100 param.dwBytes = m_statusBufSizeRcs * CODECHAL_ENCODE_STATUS_NUM; 101 param.pBufName = "StatusQueryBufferRcs"; 102 // keeping status buffer persistent since its used in all command buffers 103 param.bIsPersistent = true; 104 m_statusBufRcs = m_allocator->AllocateResource(param, true); 105 ENCODE_CHK_STATUS_RETURN(m_allocator->SkipResourceSync(m_statusBufRcs)); 106 107 m_dataStatusRcs = (uint8_t *)m_allocator->LockResourceForRead(m_statusBufRcs); 108 ENCODE_CHK_NULL_RETURN(m_dataStatusRcs); 109 } 110 111 if (m_enableCp) // && m_skipFrameBasedHWCounterRead == false) 112 { 113 param.dwBytes = sizeof(HwCounter) * CODECHAL_ENCODE_STATUS_NUM + sizeof(HwCounter); 114 param.pBufName = "HWCounterQueryBuffer"; 115 param.bIsPersistent = true; // keeping status buffer persistent since its used in all command buffers 116 m_hwcounterBuf = m_allocator->AllocateResource(param, false); 117 ENCODE_CHK_STATUS_RETURN(m_allocator->SkipResourceSync(m_hwcounterBuf)); 118 119 m_hwcounterBase = (uint32_t *)m_allocator->LockResourceWithNoOverwrite(m_hwcounterBuf); 120 ENCODE_CHK_NULL_RETURN(m_hwcounterBase); 121 } 122 123 m_submittedCount = 0; 124 m_reportedCount = 0; 125 126 m_statusBufAddr = MOS_NewArray(StatusBufAddr, statusReportMaxNum); 127 ENCODE_CHK_NULL_RETURN(m_statusBufAddr); 128 129 m_statusBufAddr[statusReportGlobalCount].osResource = m_completedCountBuf; 130 m_statusBufAddr[statusReportGlobalCount].offset = 0; 131 m_statusBufAddr[statusReportGlobalCount].bufSize = sizeof(uint32_t) * 2; 132 133 for (int i = statusReportRCSStart; i < statusReportRcsMaxNum; i++) 134 { 135 m_statusBufAddr[i].osResource = m_statusBufRcs; 136 m_statusBufAddr[i].bufSize = m_statusBufSizeRcs; 137 m_statusBufAddr[i].offset = i * sizeof(uint32_t) * 2; 138 } 139 140 for (int i = statusReportMfx; i < statusReportMfxMaxNum; i++) 141 { 142 m_statusBufAddr[i].osResource = m_statusBufMfx; 143 m_statusBufAddr[i].bufSize = m_statusBufSizeMfx; 144 } 145 146 SetOffsetsForStatusBufMfx(); 147 148 return MOS_STATUS_SUCCESS; 149 } 150 SetOffsetsForStatusBufMfx()151 void EncoderStatusReport::SetOffsetsForStatusBufMfx() 152 { 153 m_statusBufAddr[statusReportMfx].offset = 0; 154 m_statusBufAddr[statusReportMfxBitstreamByteCountPerFrame].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, mfcBitstreamByteCountPerFrame); 155 m_statusBufAddr[statusReportMfxBitstreamSyntaxElementOnlyBitCount].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, mfcBitstreamSyntaxElementOnlyBitCount); 156 m_statusBufAddr[statusReportImageStatusMask].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, imageStatusMask); 157 m_statusBufAddr[statusReportImageStatusCtrl].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, imageStatusCtrl); 158 m_statusBufAddr[statusReportHucStatusRegMask].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, hucStatusRegMask); 159 m_statusBufAddr[statusReportHucStatusReg].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, hucStatusReg); 160 m_statusBufAddr[statusReportHucStatus2Reg].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, hucStatus2Reg); 161 m_statusBufAddr[statusReportNumSlices].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, numSlices); 162 m_statusBufAddr[statusReportErrorFlags].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, errorFlags); 163 m_statusBufAddr[statusReportBRCQPReport].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, brcQPReport); 164 m_statusBufAddr[statusReportNumberPasses].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, numberPasses); 165 m_statusBufAddr[statusReportHeaderBytesInserted].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, headerBytesInserted); 166 m_statusBufAddr[statusReportQPStatusCount].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, qpStatusCount); 167 m_statusBufAddr[statusReportPictureCodingType].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, pictureCodingType); 168 m_statusBufAddr[statusReportLoopFilterLevel].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, loopFilterLevel); 169 m_statusBufAddr[statusReportImageStatusCtrlOfLastBRCPass].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, imageStatusCtrlOfLastBRCPass); 170 m_statusBufAddr[statusReportSceneChangedFlag].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, sceneChangedFlag); 171 m_statusBufAddr[statusReportSumSquareError].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, sumSquareError[0]); 172 m_statusBufAddr[statusReportSadLuma].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, sadLuma); 173 m_statusBufAddr[statusReportNumIntra4x4Block].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, numIntra4x4Block); 174 m_statusBufAddr[statusReportNumInterSkip4x4Block].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, numInterSkip4x4Block); 175 m_statusBufAddr[statusReportNumSkip8x8Block].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, numSkip8x8Block); 176 m_statusBufAddr[statusReportSliceReport].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, sliceReport); 177 m_statusBufAddr[statusReportLpla].offset = CODECHAL_OFFSETOF(EncodeStatusMfx, lookaheadStatus); 178 } 179 Init(void * inputPar)180 MOS_STATUS EncoderStatusReport::Init(void *inputPar) 181 { 182 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 183 184 EncoderStatusParameters *inputParameters = (EncoderStatusParameters *)inputPar; 185 uint32_t submitIndex = CounterToIndex(m_submittedCount); 186 187 if (inputParameters) 188 { 189 m_statusReportData[submitIndex].usedVdBoxNumber = inputParameters->numUsedVdbox; 190 m_statusReportData[submitIndex].statusReportNumber = inputParameters->statusReportFeedbackNumber; 191 m_statusReportData[submitIndex].currOriginalPic = inputParameters->currOriginalPic; 192 m_statusReportData[submitIndex].currRefList = inputParameters->currRefList; 193 m_statusReportData[submitIndex].numberTilesInFrame = inputParameters->numberTilesInFrame; 194 195 m_statusReportData[submitIndex].av1EnableFrameOBU = inputParameters->av1EnableFrameObu; 196 m_statusReportData[submitIndex].av1FrameHdrOBUSizeByteOffset = inputParameters->av1FrameHdrOBUSizeByteOffset; 197 m_statusReportData[submitIndex].frameWidth = inputParameters->frameWidth; 198 m_statusReportData[submitIndex].frameHeight = inputParameters->frameHeight; 199 200 uint64_t pairIndex = GetIdForCodecFuncToFuncIdPairs(inputParameters->codecFunction); 201 if (pairIndex >= m_maxCodecFuncNum) 202 { 203 return MOS_STATUS_INVALID_PARAMETER; 204 } 205 206 m_statusReportData[submitIndex].func = (CODECHAL_ENCODE_FUNCTION_ID)m_codecFuncToFuncIdPairs[pairIndex]; 207 208 m_hwWalker = inputParameters->hwWalker; 209 m_picWidthInMb = inputParameters->picWidthInMb; 210 m_frameFieldHeightInMb = inputParameters->frameFieldHeightInMb; 211 m_maxNumSlicesAllowed = inputParameters->maxNumSlicesAllowed; 212 } 213 214 if (m_enableMfx) 215 { 216 EncodeStatusMfx* encodeStatusMfx = (EncodeStatusMfx*)(m_dataStatusMfx + submitIndex * m_statusBufSizeMfx); 217 encodeStatusMfx->status = querySkipped; 218 if (inputParameters) 219 { 220 encodeStatusMfx->pictureCodingType = inputParameters->pictureCodingType; 221 } 222 } 223 224 if (m_enableRcs) 225 { 226 EncodeStatusRcs* encodeStatusRcs = (EncodeStatusRcs*)(m_dataStatusRcs + submitIndex * m_statusBufSizeRcs); 227 for( auto i = 0; i < statusReportRcsMaxNum; i++) 228 { 229 encodeStatusRcs->executingStatus[i].status = querySkipped; 230 } 231 } 232 return eStatus; 233 } 234 Reset()235 MOS_STATUS EncoderStatusReport::Reset() 236 { 237 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 238 239 m_submittedCount++; 240 241 uint32_t submitIndex = CounterToIndex(m_submittedCount); 242 243 if (m_enableMfx) 244 { 245 EncodeStatusMfx *encodeStatusMfx = (EncodeStatusMfx *)(m_dataStatusMfx + submitIndex * m_statusBufSizeMfx); 246 MOS_ZeroMemory((uint8_t*)encodeStatusMfx, m_statusBufSizeMfx); 247 } 248 249 if (m_enableRcs) 250 { 251 EncodeStatusRcs *encodeStatusRcs = (EncodeStatusRcs *)(m_dataStatusRcs + submitIndex * m_statusBufSizeRcs); 252 MOS_ZeroMemory((uint8_t*)encodeStatusRcs, m_statusBufSizeRcs); 253 } 254 255 return eStatus; 256 } 257 GetHwCtrBuf()258 PMOS_RESOURCE EncoderStatusReport::GetHwCtrBuf() 259 { 260 return m_hwcounterBuf; 261 } 262 GetCommonMfxReportData(EncodeStatusReportData * statusReportData,uint32_t index)263 MOS_STATUS EncoderStatusReport::GetCommonMfxReportData(EncodeStatusReportData *statusReportData, uint32_t index) 264 { 265 EncodeStatusMfx *encodeStatusMfx = nullptr; 266 bool completed = false; 267 268 if (!m_enableMfx) 269 { 270 return MOS_STATUS_SUCCESS; 271 } 272 273 encodeStatusMfx = (EncodeStatusMfx*)(m_dataStatusMfx + index * m_statusBufSizeMfx); 274 completed = (encodeStatusMfx->status == queryEnd); 275 276 statusReportData->bitstreamSize = 277 encodeStatusMfx->mfcBitstreamByteCountPerFrame + encodeStatusMfx->headerBytesInserted; 278 279 statusReportData->qpY = encodeStatusMfx->brcQPReport.DW0.qpPrimeY; 280 statusReportData->suggestedQPYDelta = encodeStatusMfx->imageStatusCtrl.cumulativeSliceDeltaQP; 281 statusReportData->numberPasses = (uint8_t)(encodeStatusMfx->imageStatusCtrl.totalNumPass + 1); 282 statusReportData->sceneChangeDetected = 283 (encodeStatusMfx->sceneChangedFlag & CODECHAL_ENCODE_SCENE_CHANGE_DETECTED_MASK) ? 1 : 0; 284 285 if (m_picWidthInMb != 0 && m_frameFieldHeightInMb != 0) 286 { 287 statusReportData->averageQP= (unsigned char)(((uint32_t)encodeStatusMfx->qpStatusCount.cumulativeQP) 288 / (m_picWidthInMb * m_frameFieldHeightInMb)); 289 } 290 statusReportData->panicMode = encodeStatusMfx->imageStatusCtrl.panic; 291 292 PakNumberOfSlices *numSlices = &encodeStatusMfx->numSlices; 293 294 // If Num slices is greater than spec limit set NumSlicesNonCompliant to 1 and report error 295 if (numSlices->numberOfSlices > m_maxNumSlicesAllowed) 296 { 297 statusReportData->numSlicesNonCompliant = 1; 298 } 299 statusReportData->numberSlices = numSlices->numberOfSlices; 300 301 return MOS_STATUS_SUCCESS; 302 } 303 UpdateCodecStatus(EncodeStatusReportData * statusReportData,EncodeStatusRcs * encodeStatusRcs,bool completed)304 MOS_STATUS EncoderStatusReport::UpdateCodecStatus( 305 EncodeStatusReportData *statusReportData, 306 EncodeStatusRcs *encodeStatusRcs, 307 bool completed) 308 { 309 ENCODE_CHK_NULL_RETURN(statusReportData); 310 ENCODE_CHK_NULL_RETURN(encodeStatusRcs); 311 312 if (statusReportData->func != CODECHAL_ENCODE_ENC_ID && 313 statusReportData->func != CODECHAL_ENCODE_FEI_ENC_ID && 314 !completed) 315 { 316 if(statusReportData->func == CODECHAL_ENCODE_FEI_PRE_ENC_ID) 317 { 318 statusReportData->codecStatus = CODECHAL_STATUS_SUCCESSFUL; 319 } 320 else 321 { 322 // Add debug info here -> Media reset may have occured. 323 statusReportData->codecStatus = CODECHAL_STATUS_ERROR; 324 } 325 } 326 else if (m_hwWalker && statusReportData->func == CODECHAL_ENCODE_ENC_ID) 327 { 328 // iterate over all media states and check that all of them completed 329 for (auto j = 0; j < statusReportRcsMaxNum; j += 1) 330 { 331 if (encodeStatusRcs->executingStatus[j].status != queryEnd) 332 { 333 // some media state failed to complete 334 // Add debug info here -> Error: Unable to finish encoding. 335 statusReportData->codecStatus = CODECHAL_STATUS_ERROR; 336 break; 337 } 338 } 339 340 statusReportData->codecStatus = CODECHAL_STATUS_SUCCESSFUL; 341 } 342 343 return MOS_STATUS_SUCCESS; 344 } 345 ParseStatus(void * report,uint32_t index)346 MOS_STATUS EncoderStatusReport::ParseStatus(void *report, uint32_t index) 347 { 348 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 349 EncodeStatusMfx *encodeStatusMfx = nullptr; 350 EncodeStatusRcs *encodeStatusRcs = nullptr; 351 bool completed = false; 352 353 EncodeStatusReportData *statusReportData = &m_statusReportData[index]; 354 355 statusReportData->pFrmStatsInfo = ((EncodeStatusReportData *)report)->pFrmStatsInfo; 356 statusReportData->pBlkStatsInfo = ((EncodeStatusReportData *)report)->pBlkStatsInfo; 357 statusReportData->pBlkQualityInfo = ((EncodeStatusReportData*)report)->pBlkQualityInfo; 358 359 if (m_enableRcs) 360 { 361 encodeStatusRcs = (EncodeStatusRcs*)(m_dataStatusRcs + index * m_statusBufSizeRcs); 362 completed = (encodeStatusRcs->executingStatus[statusReportFrameStatus].status == queryEnd); 363 } 364 365 if (m_enableMfx) 366 { 367 encodeStatusMfx = (EncodeStatusMfx*)(m_dataStatusMfx + index * m_statusBufSizeMfx); 368 completed = (encodeStatusMfx->status == queryEnd); 369 } 370 371 if (m_enableCp) 372 { 373 m_hwcounter = (uint64_t *)(((char *)m_hwcounterBase) + (index * sizeof(HwCounter))); 374 statusReportData->hwCtr = m_hwcounter; 375 } 376 GetCommonMfxReportData(statusReportData, index); 377 378 statusReportData->codecStatus = CODECHAL_STATUS_SUCCESSFUL; 379 380 // Need add GPU Hang check here 381 UpdateCodecStatus(statusReportData, encodeStatusRcs, completed); 382 383 if ((statusReportData->codecStatus == CODECHAL_STATUS_ERROR) && encodeStatusMfx && (encodeStatusMfx->lookaheadStatus.targetFrameSize != 0)) 384 { 385 statusReportData->codecStatus = CODECHAL_STATUS_SUCCESSFUL; 386 } 387 388 // The frame is completed, notify the observers 389 if (statusReportData->codecStatus == CODECHAL_STATUS_SUCCESSFUL) 390 { 391 eStatus = NotifyObservers(encodeStatusMfx, encodeStatusRcs, statusReportData); 392 } 393 394 NullHW::StatusReport(m_osInterface, 395 (uint32_t &)statusReportData->codecStatus, 396 statusReportData->bitstreamSize); 397 398 *((EncodeStatusReportData *)report) = *statusReportData; 399 return eStatus; 400 401 } 402 SetStatus(void * report,uint32_t index,bool outOfRange)403 MOS_STATUS EncoderStatusReport::SetStatus(void *report, uint32_t index, bool outOfRange) 404 { 405 EncodeStatusReportData *statusReportData = &m_statusReportData[index]; 406 407 statusReportData->codecStatus = outOfRange ? CODECHAL_STATUS_UNAVAILABLE : CODECHAL_STATUS_INCOMPLETE; 408 409 *((EncodeStatusReportData *)report) = *statusReportData; 410 return MOS_STATUS_SUCCESS; 411 } 412 Destroy()413 MOS_STATUS EncoderStatusReport::Destroy() 414 { 415 ENCODE_FUNC_CALL(); 416 417 if (m_completedCountBuf != nullptr) 418 { 419 m_allocator->UnLock(m_completedCountBuf); 420 m_allocator->DestroyResource(m_completedCountBuf); 421 m_completedCountBuf = nullptr; 422 } 423 424 for(auto &statusReportData: m_statusReportData) 425 { 426 if(statusReportData.hevcTileinfo != nullptr) 427 { 428 MOS_FreeMemory(statusReportData.hevcTileinfo); 429 statusReportData.hevcTileinfo = nullptr; 430 } 431 } 432 433 if (m_statusBufMfx != nullptr) 434 { 435 m_allocator->UnLock(m_statusBufMfx); 436 m_allocator->DestroyResource(m_statusBufMfx); 437 m_statusBufMfx = nullptr; 438 } 439 440 if (m_statusBufRcs != nullptr) 441 { 442 m_allocator->UnLock(m_statusBufRcs); 443 m_allocator->DestroyResource(m_statusBufRcs); 444 m_statusBufRcs = nullptr; 445 } 446 447 if (m_statusBufAddr != nullptr) 448 { 449 MOS_DeleteArray(m_statusBufAddr); 450 m_statusBufAddr = nullptr; 451 } 452 453 454 return MOS_STATUS_SUCCESS; 455 } 456 } 457