1 /*
2 * Copyright (c) 2020, 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 //!
24 //! \file     encode_av1_brc_update_packet.cpp
25 //! \brief    Defines the implementation of av1 brc update packet
26 //!
27 
28 #include "encode_av1_brc_update_packet.h"
29 #include "codechal_debug.h"
30 #include "encode_av1_brc.h"
31 #include "encode_av1_vdenc_packet.h"
32 #include "encode_av1_vdenc_lpla_enc.h"
33 #if _MEDIA_RESERVED
34 #include "encode_av1_scc.h"
35 #endif
36 
37 namespace encode
38 {
Init()39     MOS_STATUS Av1BrcUpdatePkt::Init()
40     {
41         ENCODE_FUNC_CALL();
42         HUC_CHK_STATUS_RETURN(EncodeHucPkt::Init());
43 
44         ENCODE_CHK_NULL_RETURN(m_pipeline);
45         m_allocator = m_pipeline->GetEncodeAllocator();
46         ENCODE_CHK_NULL_RETURN(m_allocator);
47 
48         ENCODE_CHK_NULL_RETURN(m_featureManager);
49         m_basicFeature = dynamic_cast<Av1BasicFeature *>(m_featureManager->GetFeature(Av1FeatureIDs::basicFeature));
50         ENCODE_CHK_NULL_RETURN(m_basicFeature);
51 
52         return MOS_STATUS_SUCCESS;
53     }
54 
CalculateCommandSize(uint32_t & commandBufferSize,uint32_t & requestedPatchListSize)55     MOS_STATUS Av1BrcUpdatePkt::CalculateCommandSize(uint32_t &commandBufferSize, uint32_t &requestedPatchListSize)
56     {
57         ENCODE_FUNC_CALL();
58 
59         auto osInterface = m_hwInterface->GetOsInterface();
60         ENCODE_CHK_NULL_RETURN(osInterface);
61 
62         uint32_t hucCommandsSize = 0;
63         uint32_t hucPatchListSize = 0;
64         MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
65 
66         ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetHucStateCommandSize(
67             m_basicFeature->m_mode, (uint32_t*)&hucCommandsSize, (uint32_t*)&hucPatchListSize, &stateCmdSizeParams));
68 
69         commandBufferSize = hucCommandsSize;
70         requestedPatchListSize = osInterface->bUsesPatchList ? hucPatchListSize : 0;
71 
72         if (m_pipeline->IsSingleTaskPhaseSupported())
73         {
74             commandBufferSize *= m_pipeline->GetPassNum();
75         }
76 
77         // 4K align since allocation is in chunks of 4K bytes.
78         commandBufferSize = MOS_ALIGN_CEIL(commandBufferSize, CODECHAL_PAGE_SIZE);
79 
80         return MOS_STATUS_SUCCESS;
81     }
82 
AllocateResources()83     MOS_STATUS Av1BrcUpdatePkt::AllocateResources()
84     {
85         ENCODE_FUNC_CALL();
86         ENCODE_CHK_STATUS_RETURN(EncodeHucPkt::AllocateResources());
87 
88         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
89         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
90         allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
91         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
92         allocParamsForBufferLinear.Format = Format_Buffer;
93 
94         MOS_RESOURCE *allocatedbuffer       = nullptr;
95 
96         for (auto k = 0; k < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; k++)
97         {
98             // Const Data buffer
99             allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencBrcConstDataBufferSize, CODECHAL_PAGE_SIZE);
100             allocParamsForBufferLinear.pBufName = "VDENC BRC Const Data Buffer";
101             allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE;
102             allocatedbuffer       = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
103             ENCODE_CHK_NULL_RETURN(allocatedbuffer);
104             m_vdencBrcConstDataBuffer[k] = *allocatedbuffer;
105 
106             // Pak insert buffer (input for HuC FW)
107             allocParamsForBufferLinear.dwBytes  = CODECHAL_PAGE_SIZE;
108             allocParamsForBufferLinear.pBufName = "VDENC Read Batch Buffer";
109             allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE;
110             allocatedbuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
111             ENCODE_CHK_NULL_RETURN(allocatedbuffer);
112             m_vdencPakInsertBatchBuffer[k] = *allocatedbuffer;
113 
114             for (auto i = 0; i < VDENC_BRC_NUM_OF_PASSES; i++)
115             {
116                 // VDEnc read batch buffer (input for HuC FW)
117                 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
118                 allocParamsForBufferLinear.pBufName = "VDENC Read Batch Buffer";
119                 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE;
120                 allocatedbuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
121                 ENCODE_CHK_NULL_RETURN(allocatedbuffer);
122                 m_vdencReadBatchBuffer[k][i] = *allocatedbuffer;
123 
124                 // BRC update DMEM
125                 allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(m_vdencBrcUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE);
126                 allocParamsForBufferLinear.pBufName = "VDENC BrcUpdate DmemBuffer";
127                 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE;
128                 allocatedbuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
129                 ENCODE_CHK_NULL_RETURN(allocatedbuffer);
130                 m_vdencBrcUpdateDmemBuffer[k][i] = *allocatedbuffer;
131             }
132         }
133 
134         return MOS_STATUS_SUCCESS;
135     }
136 
SetConstDataHuCBrcUpdate()137     MOS_STATUS Av1BrcUpdatePkt::SetConstDataHuCBrcUpdate()
138     {
139         ENCODE_FUNC_CALL();
140 
141         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
142 
143         auto hucConstData = (VdencAv1HucBrcConstantData *)m_allocator->LockResourceForWrite(&m_vdencBrcConstDataBuffer[m_pipeline->m_currRecycledBufIdx]);
144         ENCODE_CHK_NULL_RETURN(hucConstData);
145 
146         RUN_FEATURE_INTERFACE_RETURN(Av1Brc, Av1FeatureIDs::av1BrcFeature, SetConstForUpdate, hucConstData);
147 
148         m_allocator->UnLock(&m_vdencBrcConstDataBuffer[m_pipeline->m_currRecycledBufIdx]);
149 
150         return eStatus;
151     }
152 
Submit(MOS_COMMAND_BUFFER * commandBuffer,uint8_t packetPhase)153     MOS_STATUS Av1BrcUpdatePkt::Submit(MOS_COMMAND_BUFFER *commandBuffer, uint8_t packetPhase)
154     {
155         ENCODE_FUNC_CALL();
156 
157         ENCODE_CHK_NULL_RETURN(m_basicFeature);
158         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
159 
160         ENCODE_CHK_STATUS_RETURN(ConstructBatchBufferHuCBRC(&m_vdencReadBatchBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]));
161         ENCODE_CHK_STATUS_RETURN(ConstructPakInsertHucBRC(&m_vdencPakInsertBatchBuffer[m_pipeline->m_currRecycledBufIdx]));
162 
163         bool firstTaskInPhase = packetPhase & firstPacket;
164         bool requestProlog = false;
165 
166         auto brcFeature = dynamic_cast<Av1Brc *>(m_featureManager->GetFeature(Av1FeatureIDs::av1BrcFeature));
167         ENCODE_CHK_NULL_RETURN(brcFeature);
168 
169         uint16_t perfTag = m_pipeline->IsFirstPass() ? CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE : CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE_SECOND_PASS;
170         uint16_t pictureType = (m_basicFeature->m_pictureCodingType == I_TYPE) ? 0 : (m_basicFeature->m_ref.IsLowDelay() ? (m_basicFeature->m_ref.IsPFrame() ? 1 : 3) : 2);
171         SetPerfTag(perfTag, (uint16_t)m_basicFeature->m_mode, pictureType);
172 
173         if (!m_pipeline->IsSingleTaskPhaseSupported() || firstTaskInPhase)
174         {
175             // Send command buffer header at the beginning (OS dependent)
176             requestProlog = true;
177         }
178 
179         ENCODE_CHK_STATUS_RETURN(Execute(commandBuffer, true, requestProlog, BRC_UPDATE));
180 
181         if (!IsHuCStsUpdNeeded())
182         {
183             // Write HUC_STATUS mask: DW1 (mask value)
184             auto &storeDataParams            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
185             storeDataParams                  = {};
186             storeDataParams.pOsResource      = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
187             storeDataParams.dwResourceOffset = sizeof(uint32_t);
188             storeDataParams.dwValue          = AV1_BRC_HUC_STATUS_REENCODE_MASK;
189             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(commandBuffer));
190 
191             // store HUC_STATUS register: DW0 (actual value)
192             ENCODE_CHK_COND_RETURN((m_vdboxIndex > MHW_VDBOX_NODE_1), "ERROR - vdbox index exceed the maximum");
193             auto mmioRegisters              = m_hucItf->GetMmioRegisters(m_vdboxIndex);
194             auto &storeRegParams            = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)();
195             storeDataParams                 = {};
196             storeRegParams.presStoreBuffer  = m_basicFeature->m_recycleBuf->GetBuffer(VdencBrcPakMmioBuffer, 0);
197             storeRegParams.dwOffset         = 0;
198             storeRegParams.dwRegister       = mmioRegisters->hucStatusRegOffset;
199             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(commandBuffer));
200         }
201 
202         return MOS_STATUS_SUCCESS;
203     }
204 
AddBBEnd(std::shared_ptr<mhw::mi::Itf> m_miItf,MOS_COMMAND_BUFFER & cmdBuffer)205     inline MOS_STATUS AddBBEnd(std::shared_ptr<mhw::mi::Itf> m_miItf, MOS_COMMAND_BUFFER& cmdBuffer)
206     {
207         ENCODE_FUNC_CALL();
208         ENCODE_CHK_NULL_RETURN(m_miItf);
209 
210         MHW_BATCH_BUFFER TempBatchBuffer = {};
211         TempBatchBuffer.iSize = CODECHAL_PAGE_SIZE;
212         TempBatchBuffer.pData = (uint8_t *)cmdBuffer.pCmdBase;
213         TempBatchBuffer.iCurrent = cmdBuffer.iOffset;
214         TempBatchBuffer.iRemaining = cmdBuffer.iRemaining;
215 
216         ENCODE_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(nullptr, &TempBatchBuffer));
217 
218         cmdBuffer.pCmdPtr += (TempBatchBuffer.iCurrent - cmdBuffer.iOffset) / 4;
219         cmdBuffer.iOffset = TempBatchBuffer.iCurrent;
220         cmdBuffer.iRemaining = TempBatchBuffer.iRemaining;
221 
222         return MOS_STATUS_SUCCESS;
223     }
224 
ConstructBatchBufferHuCBRC(PMOS_RESOURCE batchBuffer)225     MOS_STATUS Av1BrcUpdatePkt::ConstructBatchBufferHuCBRC(PMOS_RESOURCE batchBuffer)
226     {
227         ENCODE_FUNC_CALL();
228 
229         ENCODE_CHK_NULL_RETURN(batchBuffer);
230 
231         auto batchbufferAddr = (uint8_t *)m_allocator->LockResourceForWrite(batchBuffer);
232         ENCODE_CHK_NULL_RETURN(batchbufferAddr);
233         MOS_COMMAND_BUFFER constructedCmdBuf;
234         MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
235         constructedCmdBuf.pCmdBase = constructedCmdBuf.pCmdPtr = (uint32_t *)batchbufferAddr;
236         constructedCmdBuf.iRemaining = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
237 
238         /*--------------SLBB layout--------------------*/
239         /*----Group1----*/
240         //AVP_SEGMENT_STATE
241         //AVP_INLOOP_FILTER_STATE
242         //BB_END
243         //
244         /*----Group2----*/
245         //VDENC_CMD1
246         //BB_END
247         //
248         /*----Group3----*/
249         //VDENC_CMD2
250         //BB_END
251         //
252         /*----Group4----*/
253         //AVP_PIC_STATE
254         //BB_END
255         //AVP_PIC_STATE (if multi tile)
256         //BB_END (if multi tile)
257         //
258         /*--------------End of SLBB layout--------------------*/
259 
260         SlbData slbData;
261         /*----Group1----*/
262         slbData.avpSegmentStateOffset = (uint16_t)constructedCmdBuf.iOffset;
263         ENCODE_CHK_STATUS_RETURN(AddAllCmds_AVP_SEGMENT_STATE(&constructedCmdBuf));
264         slbData.avpInloopFilterStateOffset = (uint16_t)constructedCmdBuf.iOffset;
265         SETPAR_AND_ADDCMD(AVP_INLOOP_FILTER_STATE, m_avpItf, &constructedCmdBuf);
266         ENCODE_CHK_STATUS_RETURN(AddBBEnd(m_miItf, constructedCmdBuf));
267         /*----Group2----*/
268         slbData.vdencCmd1Offset = (uint16_t)constructedCmdBuf.iOffset;
269         SETPAR_AND_ADDCMD(VDENC_CMD1, m_vdencItf, &constructedCmdBuf);
270         ENCODE_CHK_STATUS_RETURN(AddBBEnd(m_miItf, constructedCmdBuf));
271         /*----Group3----*/
272         slbData.vdencCmd2Offset = (uint16_t)constructedCmdBuf.iOffset;
273         SETPAR_AND_ADDCMD(VDENC_CMD2, m_vdencItf, &constructedCmdBuf);
274         ENCODE_CHK_STATUS_RETURN(AddBBEnd(m_miItf, constructedCmdBuf));
275         /*----Group4----*/
276         slbData.avpPicStateOffset = (uint16_t)constructedCmdBuf.iOffset;
277         ENCODE_CHK_STATUS_RETURN(AddAvpPicStateBaseOnTile(constructedCmdBuf, slbData));
278 
279         /*----Group5----*/
280         if (m_basicFeature->m_av1PicParams->PicFlags.fields.PaletteModeEnable)
281         {
282             slbData.vdencTileSliceStateOffset = (uint16_t)constructedCmdBuf.iOffset;
283             ENCODE_CHK_STATUS_RETURN(AddVdencTileSliceBaseOnTile(constructedCmdBuf, slbData));
284         }
285 
286         slbData.slbSize = (uint16_t)constructedCmdBuf.iOffset - slbData.avpSegmentStateOffset;
287 
288         RUN_FEATURE_INTERFACE_NO_RETURN(Av1Brc, Av1FeatureIDs::av1BrcFeature, SetSLBData, slbData);
289 
290         m_allocator->UnLock(batchBuffer);
291 
292         return MOS_STATUS_SUCCESS;
293     }
294 
ConstructPakInsertHucBRC(PMOS_RESOURCE batchBuffer)295     MOS_STATUS Av1BrcUpdatePkt::ConstructPakInsertHucBRC(PMOS_RESOURCE batchBuffer)
296     {
297         ENCODE_FUNC_CALL();
298 
299         ENCODE_CHK_NULL_RETURN(batchBuffer);
300 
301         RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, SetCurrentTile, 0, 0, m_pipeline);
302 
303         auto batchbufferAddr = (uint8_t *)m_allocator->LockResourceForWrite(batchBuffer);
304         ENCODE_CHK_NULL_RETURN(batchbufferAddr);
305 
306         MOS_COMMAND_BUFFER            constructedCmdBuf;
307         MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
308         constructedCmdBuf.pCmdBase = constructedCmdBuf.pCmdPtr = (uint32_t *)batchbufferAddr;
309         constructedCmdBuf.iRemaining                           = MOS_ALIGN_CEIL(m_hwInterface->m_vdencReadBatchBufferSize, CODECHAL_PAGE_SIZE);
310 
311         auto brcFeature = dynamic_cast<Av1Brc *>(m_featureManager->GetFeature(Av1FeatureIDs::av1BrcFeature));
312         ENCODE_CHK_NULL_RETURN(brcFeature);
313         auto slbData = brcFeature->GetSLBData();
314 
315         ENCODE_CHK_STATUS_RETURN(AddAllCmds_AVP_PAK_INSERT_OBJECT(&constructedCmdBuf));
316         ENCODE_CHK_STATUS_RETURN(AddBBEnd(m_miItf, constructedCmdBuf));
317 
318         slbData.pakInsertSlbSize = (uint16_t)constructedCmdBuf.iOffset;
319         RUN_FEATURE_INTERFACE_NO_RETURN(Av1Brc, Av1FeatureIDs::av1BrcFeature, SetSLBData, slbData);
320 
321         return MOS_STATUS_SUCCESS;
322     }
323 
AddAvpPicStateBaseOnTile(MOS_COMMAND_BUFFER & cmdBuffer,SlbData & slbData)324     MOS_STATUS Av1BrcUpdatePkt::AddAvpPicStateBaseOnTile(MOS_COMMAND_BUFFER& cmdBuffer, SlbData &slbData)
325     {
326         ENCODE_FUNC_CALL();
327 
328         uint16_t numTileColumns = 1;
329         uint16_t numTileRows = 1;
330         bool firstTileInGroup = false;
331         uint32_t tileGroupIdx = 0;
332         RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetTileRowColumns, numTileRows, numTileColumns);
333         slbData.tileNum = numTileRows * numTileColumns;
334 
335         for (uint32_t tileRow = 0; tileRow < numTileRows; tileRow++)
336         {
337             for (uint32_t tileCol = 0; tileCol < numTileColumns; tileCol++)
338             {
339                 RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, SetCurrentTile, tileRow, tileCol, m_pipeline);
340                 RUN_FEATURE_INTERFACE_NO_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, IsFirstTileInGroup, firstTileInGroup, tileGroupIdx);
341 #if _MEDIA_RESERVED
342                 RUN_FEATURE_INTERFACE_RETURN(Av1Scc, Av1FeatureIDs::av1Scc, UpdateIBCStatusForCurrentTile);
343 #endif
344                 if (firstTileInGroup)
345                 {
346                     SETPAR_AND_ADDCMD(AVP_PIC_STATE, m_avpItf, &cmdBuffer);
347                     ENCODE_CHK_STATUS_RETURN(AddBBEnd(m_miItf, cmdBuffer));
348                 }
349                 else
350                 {
351                     slbData.avpPicStateCmdNum = 2;
352                     slbData.secondAvpPicStateOffset = (uint16_t)cmdBuffer.iOffset;
353                     SETPAR_AND_ADDCMD(AVP_PIC_STATE, m_avpItf, &cmdBuffer);
354                     ENCODE_CHK_STATUS_RETURN(AddBBEnd(m_miItf, cmdBuffer));
355                     break;
356                 }
357             }
358 
359             if (slbData.avpPicStateCmdNum == 2)
360             {
361                 break;
362             }
363         }
364 
365         // Add MI_NOOPs to align with CODECHAL_CACHELINE_SIZE
366         uint32_t size = (MOS_ALIGN_CEIL(cmdBuffer.iOffset, CODECHAL_CACHELINE_SIZE) - cmdBuffer.iOffset) / sizeof(uint32_t);
367         for (uint32_t i = 0; i < size; i++)
368             ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_NOOP)(&cmdBuffer));
369 
370         return MOS_STATUS_SUCCESS;
371     }
372 
AddVdencTileSliceBaseOnTile(MOS_COMMAND_BUFFER & cmdBuffer,SlbData & slbData)373     MOS_STATUS Av1BrcUpdatePkt::AddVdencTileSliceBaseOnTile(MOS_COMMAND_BUFFER& cmdBuffer, SlbData& slbData)
374     {
375         ENCODE_FUNC_CALL();
376 
377         uint16_t numTileColumns = 1;
378         uint16_t numTileRows = 1;
379         RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetTileRowColumns, numTileRows, numTileColumns);
380 
381         auto& par = m_vdencItf->MHW_GETPAR_F(VDENC_HEVC_VP9_TILE_SLICE_STATE)();
382         par = {};
383 
384         for (uint32_t tileRow = 0; tileRow < numTileRows; tileRow++)
385         {
386             for (uint32_t tileCol = 0; tileCol < numTileColumns; tileCol++)
387             {
388                 RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, SetCurrentTile, tileRow, tileCol, m_pipeline);
389                 auto tileIdx = tileRow * numTileColumns + tileCol;
390 
391                 m_basicFeature->m_vdencTileSliceStart[tileIdx] = cmdBuffer.iOffset;
392                 SETPAR_AND_ADDCMD(VDENC_HEVC_VP9_TILE_SLICE_STATE, m_vdencItf, &cmdBuffer);
393                 ENCODE_CHK_STATUS_RETURN(AddBBEnd(m_miItf, cmdBuffer));
394 
395                 // Add MI_NOOPs to align with CODECHAL_CACHELINE_SIZE
396                 uint32_t size = (MOS_ALIGN_CEIL(cmdBuffer.iOffset, CODECHAL_CACHELINE_SIZE) - cmdBuffer.iOffset) / sizeof(uint32_t);
397                 for (uint32_t i = 0; i < size; i++)
398                     ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_NOOP)(&cmdBuffer));
399             }
400         }
401 
402         return MOS_STATUS_SUCCESS;
403     }
404 
AddAllCmds_AVP_SEGMENT_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const405     MOS_STATUS Av1BrcUpdatePkt::AddAllCmds_AVP_SEGMENT_STATE(PMOS_COMMAND_BUFFER cmdBuffer) const
406     {
407         ENCODE_FUNC_CALL();
408 
409         ENCODE_CHK_NULL_RETURN(m_featureManager);
410 
411         auto& par = m_avpItf->MHW_GETPAR_F(AVP_SEGMENT_STATE)();
412         par      = {};
413 
414         auto segmentFeature = dynamic_cast<Av1Segmentation *>(m_featureManager->GetFeature(Av1FeatureIDs::av1Segmentation));
415         ENCODE_CHK_NULL_RETURN(segmentFeature);
416 
417         MHW_CHK_STATUS_RETURN(segmentFeature->MHW_SETPAR_F(AVP_SEGMENT_STATE)(par));
418 
419         const bool segmentEnabled = par.av1SegmentParams.m_enabled;
420 
421         for (uint8_t i = 0; i < av1MaxSegments; i++)
422         {
423             par.currentSegmentId = i;
424             m_avpItf->MHW_ADDCMD_F(AVP_SEGMENT_STATE)(cmdBuffer);
425 
426             // If segmentation is not enabled, then AV1_SEGMENT_STATE must still be sent once for SegmentID = 0
427             // If i == numSegments -1, means all segments are issued, break the loop
428             if (!segmentEnabled || (i == par.numSegments - 1))
429             {
430                 break;
431             }
432         }
433 
434         return MOS_STATUS_SUCCESS;
435     }
436 
AddAllCmds_AVP_PAK_INSERT_OBJECT(PMOS_COMMAND_BUFFER cmdBuffer) const437     MOS_STATUS Av1BrcUpdatePkt::AddAllCmds_AVP_PAK_INSERT_OBJECT(PMOS_COMMAND_BUFFER cmdBuffer) const
438     {
439         ENCODE_FUNC_CALL();
440 
441         ENCODE_CHK_NULL_RETURN(m_osInterface);
442         auto& params = m_avpItf->MHW_GETPAR_F(AVP_PAK_INSERT_OBJECT)();
443         params      = {};
444 
445         auto GetExtraData = [&]() { return params.bsBuffer->pBase + params.offset; };
446         auto GetExtraSize = [&]() { return (params.bitSize + 7) >> 3; };
447 
448         // First, Send all other OBU bit streams other than tile group OBU when it's first tile in frame
449         uint32_t tileIdx    = 0;
450         bool     tgOBUValid = m_basicFeature->m_slcData[0].BitSize > 0 ? true : false;
451 
452         RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetTileIdx, tileIdx);
453 
454         if (tileIdx == 0)
455         {
456             uint32_t nalNum = 0;
457             for (uint32_t i = 0; i < MAX_NUM_OBU_TYPES && m_basicFeature->m_nalUnitParams[i]->uiSize > 0; i++)
458             {
459                 nalNum++;
460             }
461 
462             params.bsBuffer             = &m_basicFeature->m_bsBuffer;
463             params.endOfHeaderInsertion = false;
464 
465             // Support multiple packed header buffer
466             for (uint32_t i = 0; i < nalNum; i++)
467             {
468                 uint32_t nalUnitSize   = m_basicFeature->m_nalUnitParams[i]->uiSize;
469                 uint32_t nalUnitOffset = m_basicFeature->m_nalUnitParams[i]->uiOffset;
470 
471                 ENCODE_ASSERT(nalUnitSize < CODECHAL_ENCODE_AV1_PAK_INSERT_UNCOMPRESSED_HEADER);
472 
473                 if (IsFrameHeader(*(m_basicFeature->m_bsBuffer.pBase + nalUnitOffset)))
474                 {
475                     params.bitSize    = nalUnitSize * 8;
476                     params.offset     = nalUnitOffset;
477                     params.lastHeader = !tgOBUValid && (i+1 == nalNum);
478 
479                     m_avpItf->MHW_ADDCMD_F(AVP_PAK_INSERT_OBJECT)(cmdBuffer);
480                     m_osInterface->pfnAddCommand(cmdBuffer, GetExtraData(), GetExtraSize());
481                 }
482             }
483         }
484 
485         return MOS_STATUS_SUCCESS;
486     }
487 
488 #if USE_CODECHAL_DEBUG_TOOL
DumpInput()489     MOS_STATUS Av1BrcUpdatePkt::DumpInput()
490     {
491         ENCODE_FUNC_CALL();
492         int32_t currentPass = m_pipeline->GetCurrentPass();
493 
494         CodechalDebugInterface *debugInterface = m_pipeline->GetDebugInterface();
495         ENCODE_CHK_NULL_RETURN(debugInterface);
496 
497         ENCODE_CHK_STATUS_RETURN(debugInterface->DumpHucDmem(
498             &m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()],
499             m_vdencBrcUpdateDmemBufferSize,
500             currentPass,
501             hucRegionDumpUpdate));
502 
503         ENCODE_CHK_STATUS_RETURN(DumpRegion(0, "_BrcHistory", true, hucRegionDumpUpdate, 6080));
504         ENCODE_CHK_STATUS_RETURN(DumpRegion(1, "_VdencStats", true, hucRegionDumpUpdate, 48*4));
505         ENCODE_CHK_STATUS_RETURN(DumpRegion(3, "_InputSLBB", true, hucRegionDumpUpdate, 600*4));
506         ENCODE_CHK_STATUS_RETURN(DumpRegion(5, "_ConstData", true, hucRegionDumpUpdate, MOS_ALIGN_CEIL(m_vdencBrcConstDataBufferSize, CODECHAL_PAGE_SIZE)));
507         ENCODE_CHK_STATUS_RETURN(DumpRegion(7, "_PakMmio", true, hucRegionDumpUpdate, 16*4));
508         ENCODE_CHK_STATUS_RETURN(DumpRegion(8, "_InputPakInsert", true, hucRegionDumpUpdate, 100));
509         ENCODE_CHK_STATUS_RETURN(DumpRegion(10, "_InputCdfTable", true, hucRegionDumpUpdate, 4 * MOS_ALIGN_CEIL(m_basicFeature->m_cdfMaxNumBytes, CODECHAL_CACHELINE_SIZE)));
510 
511         return MOS_STATUS_SUCCESS;
512     }
513 
DumpOutput()514     MOS_STATUS Av1BrcUpdatePkt::DumpOutput()
515     {
516         ENCODE_FUNC_CALL();
517 
518         ENCODE_CHK_STATUS_RETURN(DumpRegion(0, "_BrcHistory", false, hucRegionDumpUpdate, 6080));
519         ENCODE_CHK_STATUS_RETURN(DumpRegion(4, "_BrcData", false, hucRegionDumpUpdate, 32));
520         ENCODE_CHK_STATUS_RETURN(DumpRegion(6, "_OutputSLBB", false, hucRegionDumpUpdate, 600 * 4));
521         ENCODE_CHK_STATUS_RETURN(DumpRegion(9, "_OutputPakInsert", false, hucRegionDumpUpdate, 100));
522         ENCODE_CHK_STATUS_RETURN(DumpRegion(11, "_OutputCdfTable", false, hucRegionDumpUpdate, MOS_ALIGN_CEIL(m_basicFeature->m_cdfMaxNumBytes, CODECHAL_CACHELINE_SIZE)));
523 
524         return MOS_STATUS_SUCCESS;
525     }
526 #endif
527 
MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE,Av1BrcUpdatePkt)528     MHW_SETPAR_DECL_SRC(HUC_IMEM_STATE, Av1BrcUpdatePkt)
529     {
530         params.kernelDescriptor = m_vdboxHucAv1BrcUpdateKernelDescriptor;
531 
532         return MOS_STATUS_SUCCESS;
533     }
534 
MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE,Av1BrcUpdatePkt)535     MHW_SETPAR_DECL_SRC(HUC_DMEM_STATE, Av1BrcUpdatePkt)
536     {
537         params.function      = BRC_UPDATE;
538         params.passNum       = static_cast<uint8_t>(m_pipeline->GetPassNum());
539         params.currentPass   = static_cast<uint8_t> (m_pipeline->GetCurrentPass());
540         params.hucDataSource = const_cast<PMOS_RESOURCE> (& m_vdencBrcUpdateDmemBuffer[m_pipeline->m_currRecycledBufIdx][m_pipeline->GetCurrentPass()]);
541         params.dataLength    = MOS_ALIGN_CEIL(m_vdencBrcUpdateDmemBufferSize, CODECHAL_CACHELINE_SIZE);
542         params.dmemOffset    = HUC_DMEM_OFFSET_RTOS_GEMS;
543 
544         return MOS_STATUS_SUCCESS;
545     }
546 
MHW_SETPAR_DECL_SRC(VD_PIPELINE_FLUSH,Av1BrcUpdatePkt)547     MHW_SETPAR_DECL_SRC(VD_PIPELINE_FLUSH, Av1BrcUpdatePkt)
548     {
549         params.waitDoneVDCmdMsgParser = true;
550         params.waitDoneAV1 = true;
551         params.flushAV1 = true;
552 
553         return MOS_STATUS_SUCCESS;
554     }
555 
MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE,Av1BrcUpdatePkt)556     MHW_SETPAR_DECL_SRC(HUC_VIRTUAL_ADDR_STATE, Av1BrcUpdatePkt)
557     {
558         ENCODE_FUNC_CALL();
559 
560         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
561 
562         int32_t currentPass = m_pipeline->GetCurrentPass();
563         if (currentPass < 0)
564         {
565             eStatus = MOS_STATUS_INVALID_PARAMETER;
566             return eStatus;
567         }
568 
569         ENCODE_CHK_NULL_RETURN(m_basicFeature);
570         ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf);
571 
572         params.function = BRC_UPDATE;
573 
574         uint32_t prevBufIdx = 0;
575         RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetPrevStatisticsBufferIndex, prevBufIdx);
576         uint32_t statBufIdx = 0;
577         RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetStatisticsBufferIndex, statBufIdx);
578         MOS_RESOURCE *resTileBasedStatisticsBuffer = nullptr;
579         RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetTileBasedStatisticsBuffer, currentPass == 0? prevBufIdx : statBufIdx, resTileBasedStatisticsBuffer);
580         uint32_t offset = 0;
581         RUN_FEATURE_INTERFACE_RETURN(Av1EncodeTile, Av1FeatureIDs::encodeTile, GetTileStatsOffset, offset);
582 
583         MOS_RESOURCE *resBrcDataBuffer = nullptr;
584         RUN_FEATURE_INTERFACE_RETURN(Av1Brc, Av1FeatureIDs::av1BrcFeature, GetBrcDataBuffer, resBrcDataBuffer);
585 
586         const uint32_t bufIdx = m_pipeline->m_currRecycledBufIdx;
587         auto brcFeature = dynamic_cast<Av1Brc *>(m_featureManager->GetFeature(Av1FeatureIDs::av1BrcFeature));
588         ENCODE_CHK_NULL_RETURN(brcFeature);
589         auto vdenc2ndLevelBatchBuffer = brcFeature->GetVdenc2ndLevelBatchBuffer(bufIdx);
590         ENCODE_CHK_NULL_RETURN(vdenc2ndLevelBatchBuffer);
591 
592         auto pakInsertOutputBatchBuffer = brcFeature->GetPakInsertOutputBatchBuffer(bufIdx);
593         ENCODE_CHK_NULL_RETURN(pakInsertOutputBatchBuffer);
594 
595         // Region 0 - History Buffer (Input/Output)
596         params.regionParams[0].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(VdencBRCHistoryBuffer, 0);
597         params.regionParams[0].isWritable = true;
598         // Region 1 - VDenc Stats Buffer (Input)
599         params.regionParams[1].presRegion = resTileBasedStatisticsBuffer;
600         params.regionParams[1].dwOffset   = offset;
601         // Region 3 - Input SLB Buffer (Input)
602         params.regionParams[3].presRegion = const_cast<PMOS_RESOURCE>(&m_vdencReadBatchBuffer[bufIdx][currentPass]);
603         // Region 4 - BRC Data for next frame's width/height - (Output)
604         params.regionParams[4].presRegion = resBrcDataBuffer;
605         params.regionParams[4].isWritable = true;
606         // Region 5 - Const Data (Input)
607         params.regionParams[5].presRegion = const_cast<PMOS_RESOURCE>(&m_vdencBrcConstDataBuffer[bufIdx]);
608         // Region 6 - Output SLBB - (Output)
609         params.regionParams[6].presRegion = &vdenc2ndLevelBatchBuffer->OsResource;
610         params.regionParams[6].isWritable = true;
611         // Region 7 - PAK MMIO for frame size (Input)
612         params.regionParams[7].presRegion = m_basicFeature->m_recycleBuf->GetBuffer(PakInfo, 0);
613         // Region 8 - PAK INSERT cmd with FrameHeader before back annotation (Input)
614         params.regionParams[8].presRegion = const_cast<PMOS_RESOURCE>(&m_vdencPakInsertBatchBuffer[bufIdx]);
615         // Region 9 - PAK INSERT cmd with FrameHeader after back annotation (Output)
616         params.regionParams[9].presRegion = &pakInsertOutputBatchBuffer->OsResource;
617         params.regionParams[9].isWritable = true;
618         // Region 10 - CDF table (Input)
619         params.regionParams[10].presRegion = m_basicFeature->m_defaultCdfBuffers;
620         // Region 11 - CDF (output)
621         params.regionParams[11].presRegion = m_basicFeature->m_defaultCdfBufferInUse;
622         params.regionParams[11].isWritable = true;
623 
624         return MOS_STATUS_SUCCESS;
625     }
626 
MHW_SETPAR_DECL_SRC(AVP_PIC_STATE,Av1BrcUpdatePkt)627     MHW_SETPAR_DECL_SRC(AVP_PIC_STATE, Av1BrcUpdatePkt)
628     {
629         params.notFirstPass = !m_pipeline->IsFirstPass();
630 
631         return MOS_STATUS_SUCCESS;
632     }
633 
634 }
635