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_huc_brc_init_packet.cpp 24 //! \brief Defines the interface for huc brc init/reset packet 25 //! 26 #include "encode_huc_brc_init_packet.h" 27 #include "mhw_vdbox.h" 28 #include "encode_hevc_brc.h" 29 #include "encode_hevc_vdenc_lpla_enc.h" 30 31 namespace encode { Init()32 MOS_STATUS HucBrcInitPkt::Init() 33 { 34 ENCODE_FUNC_CALL(); 35 ENCODE_CHK_STATUS_RETURN(EncodeHucPkt::Init()); 36 ENCODE_CHK_NULL_RETURN(m_featureManager); 37 38 m_basicFeature = dynamic_cast<HevcBasicFeature *>(m_featureManager->GetFeature(HevcFeatureIDs::basicFeature)); 39 ENCODE_CHK_NULL_RETURN(m_basicFeature); 40 41 return MOS_STATUS_SUCCESS; 42 } 43 AllocateResources()44 MOS_STATUS HucBrcInitPkt::AllocateResources() 45 { 46 ENCODE_CHK_STATUS_RETURN(EncodeHucPkt::AllocateResources()); 47 48 // initiate allocation paramters and lock flags 49 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; 50 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); 51 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; 52 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; 53 allocParamsForBufferLinear.Format = Format_Buffer; 54 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE; 55 MOS_RESOURCE *allocatedbuffer; 56 for (auto k = 0; k < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; k++) 57 { 58 // BRC init/reset DMEM 59 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencBrcInitDmemBufferSize, CODECHAL_CACHELINE_SIZE); 60 allocParamsForBufferLinear.pBufName = "VDENC BrcInit DmemBuffer"; 61 allocatedbuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true); 62 ENCODE_CHK_NULL_RETURN(allocatedbuffer); 63 m_vdencBrcInitDmemBuffer[k] = *allocatedbuffer; 64 } 65 66 return MOS_STATUS_SUCCESS; 67 } 68 Submit(MOS_COMMAND_BUFFER * commandBuffer,uint8_t packetPhase)69 MOS_STATUS HucBrcInitPkt::Submit(MOS_COMMAND_BUFFER *commandBuffer, uint8_t packetPhase) 70 { 71 ENCODE_FUNC_CALL(); 72 73 ENCODE_CHK_STATUS_RETURN(m_miItf->SetWatchdogTimerThreshold(m_basicFeature->m_frameWidth, m_basicFeature->m_frameHeight, true)); 74 bool firstTaskInPhase = packetPhase & firstPacket; 75 bool requestProlog = false; 76 77 SetPerfTag(CODECHAL_ENCODE_PERFTAG_CALL_BRC_INIT_RESET, (uint16_t)m_basicFeature->m_mode, m_basicFeature->m_pictureCodingType); 78 79 if (!m_pipeline->IsSingleTaskPhaseSupported() || firstTaskInPhase) 80 { 81 // Send command buffer header at the beginning (OS dependent) 82 requestProlog = true; 83 } 84 auto brcFeature = dynamic_cast<HEVCEncodeBRC*>(m_featureManager->GetFeature(HevcFeatureIDs::hevcBrcFeature)); 85 ENCODE_CHK_NULL_RETURN(brcFeature); 86 ENCODE_CHK_STATUS_RETURN(Execute(commandBuffer, true, requestProlog, BRC_INIT)); 87 88 // Disable Brc Init/reset here after init cmd executed, APP will re-trigger the reset by DDI params m_hevcSeqParams->bResetBRC 89 RUN_FEATURE_INTERFACE_NO_RETURN(HEVCEncodeBRC, HevcFeatureIDs::hevcBrcFeature, 90 DisableBrcInitReset); 91 92 CODECHAL_DEBUG_TOOL 93 ( 94 ENCODE_CHK_STATUS_RETURN(DumpHucBrcInit()); 95 ) 96 97 return MOS_STATUS_SUCCESS; 98 } 99 MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE,HucBrcInitPkt)100 MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE, HucBrcInitPkt) 101 { 102 params.kernelDescriptor = m_vdboxHucHevcBrcInitKernelDescriptor; 103 104 return MOS_STATUS_SUCCESS; 105 } 106 MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,HucBrcInitPkt)107 MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, HucBrcInitPkt) 108 { 109 ENCODE_CHK_STATUS_RETURN(SetDmemBuffer()); 110 111 params.function = BRC_INIT; 112 params.hucDataSource = const_cast<PMOS_RESOURCE>(&m_vdencBrcInitDmemBuffer[m_pipeline->m_currRecycledBufIdx]); 113 params.dataLength = MOS_ALIGN_CEIL(m_vdencBrcInitDmemBufferSize, CODECHAL_CACHELINE_SIZE); 114 params.dmemOffset = HUC_DMEM_OFFSET_RTOS_GEMS; 115 return MOS_STATUS_SUCCESS; 116 } 117 MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,HucBrcInitPkt)118 MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, HucBrcInitPkt) 119 { 120 ENCODE_CHK_NULL_RETURN(m_basicFeature); 121 ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf); 122 123 params.function = BRC_INIT; 124 params.regionParams[0].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(VdencBRCHistoryBuffer, m_basicFeature->m_frameNum); 125 params.regionParams[0].isWritable = true; 126 127 return MOS_STATUS_SUCCESS; 128 } 129 CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)130 MOS_STATUS HucBrcInitPkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize) 131 { 132 ENCODE_FUNC_CALL(); 133 134 auto osInterface = m_hwInterface->GetOsInterface(); 135 ENCODE_CHK_NULL_RETURN(osInterface); 136 137 uint32_t hucCommandsSize = 0; 138 uint32_t hucPatchListSize = 0; 139 MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams; 140 stateCmdSizeParams.uNumMfxWait = 3; 141 ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetHucStateCommandSize( 142 m_basicFeature->m_mode, (uint32_t*)&hucCommandsSize, (uint32_t*)&hucPatchListSize, &stateCmdSizeParams)); 143 144 commandBufferSize = hucCommandsSize; 145 requestedPatchListSize = osInterface->bUsesPatchList ? hucPatchListSize : 0; 146 147 // 4K align since allocation is in chunks of 4K bytes. 148 commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, CODECHAL_PAGE_SIZE); 149 150 return MOS_STATUS_SUCCESS; 151 } 152 SetDmemBuffer() const153 MOS_STATUS HucBrcInitPkt::SetDmemBuffer() const 154 { 155 ENCODE_FUNC_CALL(); 156 157 MOS_STATUS eStatus = MOS_STATUS_SUCCESS; 158 159 // Setup BrcInit DMEM 160 auto hucVdencBrcInitDmem = (VdencHevcHucBrcInitDmem *) 161 m_allocator->LockResourceForWrite(const_cast<MOS_RESOURCE*>(&m_vdencBrcInitDmemBuffer[m_pipeline->m_currRecycledBufIdx])); 162 ENCODE_CHK_NULL_RETURN(hucVdencBrcInitDmem); 163 MOS_ZeroMemory(hucVdencBrcInitDmem, sizeof(VdencHevcHucBrcInitDmem)); 164 165 bool enableTileReplay = false; 166 RUN_FEATURE_INTERFACE_RETURN(HevcEncodeTile, HevcFeatureIDs::encodeTile, IsTileReplayEnabled, enableTileReplay); 167 168 hucVdencBrcInitDmem->BRCFunc_U32 = enableTileReplay ? 1 : 0 << 7; //bit0 0: Init; 1: Reset, bit7 0: frame-based; 1: tile-based 169 hucVdencBrcInitDmem->InitBufFull_U32 = MOS_MIN(m_basicFeature->m_hevcSeqParams->InitVBVBufferFullnessInBit, m_basicFeature->m_hevcSeqParams->VBVBufferSizeInBit); 170 hucVdencBrcInitDmem->BufSize_U32 = m_basicFeature->m_hevcSeqParams->VBVBufferSizeInBit; 171 hucVdencBrcInitDmem->MinRate_U32 = 0; 172 hucVdencBrcInitDmem->FrameRateM_U32 = m_basicFeature->m_hevcSeqParams->FrameRate.Numerator; 173 hucVdencBrcInitDmem->FrameRateD_U32 = m_basicFeature->m_hevcSeqParams->FrameRate.Denominator; 174 hucVdencBrcInitDmem->ACQP_U32 = 0; 175 176 auto CalculatedMaxFrame = m_basicFeature->GetProfileLevelMaxFrameSize(); 177 hucVdencBrcInitDmem->UserMaxFrame = m_basicFeature->m_hevcSeqParams->UserMaxIFrameSize > 0 ? MOS_MIN(m_basicFeature->m_hevcSeqParams->UserMaxIFrameSize, CalculatedMaxFrame) : CalculatedMaxFrame; 178 hucVdencBrcInitDmem->ProfileLevelMaxFramePB_U32 = m_basicFeature->m_hevcSeqParams->UserMaxPBFrameSize > 0 ? MOS_MIN(m_basicFeature->m_hevcSeqParams->UserMaxPBFrameSize, CalculatedMaxFrame) : CalculatedMaxFrame; 179 180 hucVdencBrcInitDmem->SSCFlag = m_basicFeature->m_hevcSeqParams->SliceSizeControl; 181 182 // LDB case, NumP=0 & NumB=100, but GopP=100 & GopB=0 183 184 hucVdencBrcInitDmem->FrameWidth_U16 = (uint16_t)m_basicFeature->m_oriFrameWidth; 185 hucVdencBrcInitDmem->FrameHeight_U16 = (uint16_t)m_basicFeature->m_oriFrameHeight; 186 187 hucVdencBrcInitDmem->MinQP_U8 = m_basicFeature->m_hevcPicParams->BRCMinQp < 10 ? 10 : m_basicFeature->m_hevcPicParams->BRCMinQp; // Setting values from arch spec 188 hucVdencBrcInitDmem->MaxQP_U8 = m_basicFeature->m_hevcPicParams->BRCMaxQp < 10 ? 51 : (m_basicFeature->m_hevcPicParams->BRCMaxQp > 51 ? 51 : m_basicFeature->m_hevcPicParams->BRCMaxQp); // Setting values from arch spec 189 190 hucVdencBrcInitDmem->BRCPyramidEnable_U8 = 0; 191 192 //QP modulation settings 193 m_basicFeature->m_hevcSeqParams->GopRefDist = 194 m_basicFeature->m_hevcSeqParams->GopRefDist == 0 ? 1 : 195 m_basicFeature->m_hevcSeqParams->GopRefDist; 196 bool bAllowedPyramid = m_basicFeature->m_hevcSeqParams->GopRefDist != 3; 197 uint16_t intraPeriod = m_basicFeature->m_hevcSeqParams->GopPicSize > 4001 ? 4000 : m_basicFeature->m_hevcSeqParams->GopPicSize - 1; 198 intraPeriod = ((intraPeriod + m_basicFeature->m_hevcSeqParams->GopRefDist - 1) / m_basicFeature->m_hevcSeqParams->GopRefDist) * m_basicFeature->m_hevcSeqParams->GopRefDist; 199 if (m_basicFeature->m_hevcSeqParams->HierarchicalFlag && bAllowedPyramid) 200 { 201 hucVdencBrcInitDmem->GopP_U16 = intraPeriod/m_basicFeature->m_hevcSeqParams->GopRefDist; 202 hucVdencBrcInitDmem->GopB_U16 = (hucVdencBrcInitDmem->GopP_U16)*(m_basicFeature->m_hevcSeqParams->GopRefDist>1); 203 hucVdencBrcInitDmem->GopB1_U16 = hucVdencBrcInitDmem->GopP_U16 * ((m_basicFeature->m_hevcSeqParams->GopRefDist > 2) + (m_basicFeature->m_hevcSeqParams->GopRefDist == 4 || m_basicFeature->m_hevcSeqParams->GopRefDist > 5)); 204 hucVdencBrcInitDmem->GopB2_U16 = (intraPeriod - hucVdencBrcInitDmem->GopP_U16 - hucVdencBrcInitDmem->GopB_U16 - hucVdencBrcInitDmem->GopB1_U16) * (m_basicFeature->m_hevcSeqParams->GopRefDist > 3); 205 hucVdencBrcInitDmem->MaxBRCLevel_U8 = hucVdencBrcInitDmem->GopB1_U16 == 0 ? HEVC_BRC_FRAME_TYPE_B : (hucVdencBrcInitDmem->GopB2_U16 == 0 ? HEVC_BRC_FRAME_TYPE_B1 : HEVC_BRC_FRAME_TYPE_B2); 206 hucVdencBrcInitDmem->BRCPyramidEnable_U8 = 1; 207 } 208 else //FlatB or LDB 209 { 210 hucVdencBrcInitDmem->GopP_U16 = intraPeriod/m_basicFeature->m_hevcSeqParams->GopRefDist; 211 hucVdencBrcInitDmem->GopB_U16 = intraPeriod - hucVdencBrcInitDmem->GopP_U16; 212 hucVdencBrcInitDmem->MaxBRCLevel_U8 = hucVdencBrcInitDmem->GopB_U16 == 0 ? HEVC_BRC_FRAME_TYPE_P_OR_LB : HEVC_BRC_FRAME_TYPE_B; 213 } 214 215 hucVdencBrcInitDmem->LumaBitDepth_U8 = m_basicFeature->m_hevcSeqParams->bit_depth_luma_minus8 + 8; 216 hucVdencBrcInitDmem->ChromaBitDepth_U8 = m_basicFeature->m_hevcSeqParams->bit_depth_chroma_minus8 + 8; 217 218 if (m_basicFeature->m_hevcSeqParams->SourceBitDepth == ENCODE_HEVC_BIT_DEPTH_10) 219 { 220 hucVdencBrcInitDmem->LumaBitDepth_U8 = 10; 221 hucVdencBrcInitDmem->ChromaBitDepth_U8 = 10; 222 } 223 224 RUN_FEATURE_INTERFACE_RETURN(HevcVdencRoi, HevcFeatureIDs::hevcVdencRoiFeature, SetDmemHuCBrcInitReset, hucVdencBrcInitDmem); 225 226 if ((m_basicFeature->m_hevcSeqParams->SlidingWindowSize != 0) && (m_basicFeature->m_hevcSeqParams->MaxBitRatePerSlidingWindow != 0)) 227 { 228 if (m_basicFeature->m_hevcSeqParams->TargetBitRate == 0) 229 { 230 ENCODE_ASSERTMESSAGE("TargetBitRate is zero!"); 231 return MOS_STATUS_INVALID_PARAMETER; 232 } 233 hucVdencBrcInitDmem->SlidingWindow_Size_U32 = MOS_MIN((uint32_t)m_basicFeature->m_hevcSeqParams->SlidingWindowSize, 60); 234 hucVdencBrcInitDmem->SLIDINGWINDOW_MaxRateRatio = (uint8_t)((uint64_t)m_basicFeature->m_hevcSeqParams->MaxBitRatePerSlidingWindow * 100 / m_basicFeature->m_hevcSeqParams->TargetBitRate); 235 } 236 else 237 { 238 if (m_basicFeature->m_hevcSeqParams->FrameRate.Denominator == 0) 239 { 240 ENCODE_ASSERTMESSAGE("FrameRate.Deminator is zero!"); 241 return MOS_STATUS_INVALID_PARAMETER; 242 } 243 uint32_t framerate = m_basicFeature->m_hevcSeqParams->FrameRate.Numerator / m_basicFeature->m_hevcSeqParams->FrameRate.Denominator; 244 hucVdencBrcInitDmem->SlidingWindow_Size_U32 = MOS_MIN(framerate, 60); 245 hucVdencBrcInitDmem->SLIDINGWINDOW_MaxRateRatio = 120; 246 } 247 248 // Tile Row based BRC 249 if (enableTileReplay) 250 { 251 hucVdencBrcInitDmem->SlideWindowRC = 0; //Reserved for now 252 hucVdencBrcInitDmem->MaxLogCUSize = m_basicFeature->m_hevcSeqParams->log2_max_coding_block_size_minus3 + 3; 253 hucVdencBrcInitDmem->FrameWidthInLCU = (m_basicFeature->m_hevcSeqParams->wFrameWidthInMinCbMinus1 + 1) >> (m_basicFeature->m_hevcSeqParams->log2_max_coding_block_size_minus3 - m_basicFeature->m_hevcSeqParams->log2_min_coding_block_size_minus3); 254 hucVdencBrcInitDmem->FrameHeightInLCU = (m_basicFeature->m_hevcSeqParams->wFrameHeightInMinCbMinus1 + 1) >> (m_basicFeature->m_hevcSeqParams->log2_max_coding_block_size_minus3 - m_basicFeature->m_hevcSeqParams->log2_min_coding_block_size_minus3); 255 } 256 257 // Long term reference 258 hucVdencBrcInitDmem->LongTermRefEnable_U8 = true; 259 hucVdencBrcInitDmem->LongTermRefMsdk_U8 = true; 260 hucVdencBrcInitDmem->IsLowDelay_U8 = m_basicFeature->m_ref.IsLowDelay(); 261 262 hucVdencBrcInitDmem->LookaheadDepth_U8 = m_basicFeature->m_hevcSeqParams->LookaheadDepth; 263 RUN_FEATURE_INTERFACE_RETURN(HEVCVdencLplaEnc, HevcFeatureIDs::hevcVdencLplaEncFeature, 264 SetDmemForInit, hucVdencBrcInitDmem); 265 266 RUN_FEATURE_INTERFACE_RETURN(HEVCEncodeBRC, HevcFeatureIDs::hevcBrcFeature, 267 SetDmemForInit, hucVdencBrcInitDmem); 268 269 ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(const_cast<MOS_RESOURCE*>(&m_vdencBrcInitDmemBuffer[m_pipeline->m_currRecycledBufIdx]))); 270 271 return eStatus; 272 } 273 274 #if USE_CODECHAL_DEBUG_TOOL DumpHucBrcInit()275 MOS_STATUS HucBrcInitPkt::DumpHucBrcInit() 276 { 277 ENCODE_FUNC_CALL(); 278 int32_t currentPass = m_pipeline->GetCurrentPass(); 279 280 HevcBasicFeature *hevcBasicFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature); 281 ENCODE_CHK_NULL_RETURN(hevcBasicFeature); 282 283 CodechalDebugInterface *debugInterface = m_pipeline->GetDebugInterface(); 284 ENCODE_CHK_NULL_RETURN(debugInterface); 285 286 ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucDmem( 287 &m_vdencBrcInitDmemBuffer[m_pipeline->m_currRecycledBufIdx], 288 m_vdencBrcInitDmemBufferSize, 289 currentPass, 290 hucRegionDumpInit)); 291 292 ENCODE_CHK_STATUS_RETURN(DumpRegion(0, "_History", true, hucRegionDumpInit)); 293 294 return MOS_STATUS_SUCCESS; 295 } 296 #endif 297 } 298