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