1 /*
2 * Copyright (c) 2020-2023, 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_vp9_pak.cpp
24 //! \brief    Defines the common interface for vp9 vdenc\pak features
25 //!
26 
27 #include "encode_vp9_pak.h"
28 #include "codec_def_common.h"
29 #include "encode_vp9_vdenc_feature_manager.h"
30 #include "encode_vp9_vdenc_const_settings.h"
31 #include "encode_vp9_brc.h"
32 #include "encode_vp9_hpu.h"
33 #include "encode_vp9_segmentation.h"
34 #include "media_cmd_packet.h"
35 
36 namespace encode
37 {
Vp9EncodePak(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)38 Vp9EncodePak::Vp9EncodePak(
39     MediaFeatureManager *featureManager,
40     EncodeAllocator *    allocator,
41     CodechalHwInterfaceNext *hwInterface,
42     void *               constSettings)
43     : MediaFeature(constSettings),
44       m_hwInterface(hwInterface),
45       m_allocator(allocator)
46 {
47     ENCODE_FUNC_CALL();
48     ENCODE_CHK_NULL_NO_STATUS_RETURN(featureManager);
49 
50     m_featureManager = featureManager;
51     auto encFeatureManager = dynamic_cast<EncodeVp9VdencFeatureManager *>(featureManager);
52     ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
53 
54     m_basicFeature = dynamic_cast<Vp9BasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
55     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
56 
57     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hwInterface);
58 
59     m_hcpInterfaceNew = std::static_pointer_cast<mhw::vdbox::hcp::Itf>(m_hwInterface->GetHcpInterfaceNext());
60     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hcpInterfaceNew);
61 
62     m_vdencInterfaceNew = std::static_pointer_cast<mhw::vdbox::vdenc::Itf>(m_hwInterface->GetVdencInterfaceNext());
63     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_vdencInterfaceNew);
64 
65     m_miItf = std::static_pointer_cast<mhw::mi::Itf>(m_hwInterface->GetMiInterfaceNext());
66     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_miItf);
67 }
68 
Init(void * settings)69 MOS_STATUS Vp9EncodePak::Init(void *settings)
70 {
71     ENCODE_FUNC_CALL();
72 
73     m_enabled = true;
74 
75     ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetVdencPictureSecondLevelCommandsSize(
76         CODECHAL_ENCODE_MODE_VP9, &m_vdencPicStateSecondLevelBatchBufferSize));
77 
78     ENCODE_CHK_STATUS_RETURN(AllocateResources());
79 
80     return MOS_STATUS_SUCCESS;
81 }
82 
Update(void * params)83 MOS_STATUS Vp9EncodePak::Update(void *params)
84 {
85     ENCODE_FUNC_CALL();
86     ENCODE_CHK_NULL_RETURN(params);
87 
88     EncoderParams *encodeParams = (EncoderParams *)params;
89 
90     auto vp9SeqParams = static_cast<PCODEC_VP9_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
91     ENCODE_CHK_NULL_RETURN(vp9SeqParams);
92     auto vp9PicParams = static_cast<PCODEC_VP9_ENCODE_PIC_PARAMS>(encodeParams->pPicParams);
93     ENCODE_CHK_NULL_RETURN(vp9PicParams);
94 
95     if (m_basicFeature->m_newSeq)
96     {
97         ENCODE_CHK_STATUS_RETURN(SetConstSettings());
98     }
99 
100     // Reset picture state 2nd level batch buffer stage
101     for (auto i = 0; i < 3; ++i)
102     {
103         m_picState2ndLevelBBConstructed[i] = false;
104     }
105 
106     if (m_basicFeature->m_ref.DysRefFrameFlags() != DYS_REF_NONE)
107     {
108         ENCODE_CHK_STATUS_RETURN(PreparePakObjAndCuRecord());
109     }
110 
111     return MOS_STATUS_SUCCESS;
112 }
113 
SetRegionsForBrcUpdate(mhw::vdbox::huc::HUC_VIRTUAL_ADDR_STATE_PAR & params,uint32_t currPass) const114 MOS_STATUS Vp9EncodePak::SetRegionsForBrcUpdate(mhw::vdbox::huc::HUC_VIRTUAL_ADDR_STATE_PAR &params, uint32_t currPass) const
115 {
116     ENCODE_FUNC_CALL();
117 
118     // Input SLBB (second level batch buffer) - IN
119     params.regionParams[3].presRegion = const_cast<PMOS_RESOURCE>(&m_resVdencPictureState2ndLevelBatchBufferRead[currPass][m_vdencPictureState2ndLevelBBIndex]);
120 
121     // Output SLBB - OUT
122     params.regionParams[6].presRegion = const_cast<PMOS_RESOURCE>(&m_resVdencPictureState2ndLevelBatchBufferWrite[0]);
123     params.regionParams[6].isWritable = true;
124 
125     return MOS_STATUS_SUCCESS;
126 }
127 
SetRegionsForHucProb(mhw::vdbox::huc::HUC_VIRTUAL_ADDR_STATE_PAR & params,uint32_t currPass) const128 MOS_STATUS Vp9EncodePak::SetRegionsForHucProb(mhw::vdbox::huc::HUC_VIRTUAL_ADDR_STATE_PAR &params, uint32_t currPass) const
129 {
130     ENCODE_FUNC_CALL();
131 
132     auto brcFeature = dynamic_cast<Vp9EncodeBrc *>(m_featureManager->GetFeature(Vp9FeatureIDs::vp9BrcFeature));
133     ENCODE_CHK_NULL_RETURN(brcFeature);
134 
135     // Input regions: 7, 8
136 
137     // If BRC enabled, BRC Pass 2 output SLBB -> input SLBB for HPU on pass 2 (HPU pass 1 and 3. BRC Update pass 1 and 2)
138     //                 BRC Pass 1 output SLBB -> input SLBB for HPU on pass 1
139     // If BRC not on, Driver prepared SLBB    -> input to HPU on both passes
140     if (brcFeature->IsVdencBrcEnabled())
141     {
142         params.regionParams[7].presRegion = const_cast<MOS_RESOURCE *>(&m_resVdencPictureState2ndLevelBatchBufferWrite[0]);
143     }
144     else
145     {
146         params.regionParams[7].presRegion = const_cast<MOS_RESOURCE *>(&m_resVdencPictureState2ndLevelBatchBufferRead[currPass][m_vdencPictureState2ndLevelBBIndex]);
147     }
148     params.regionParams[8].presRegion = const_cast<MOS_RESOURCE *>(&m_resHucPakInsertUncompressedHeaderReadBuffer[m_basicFeature->m_currRecycledBufIdx]);
149 
150     // Output regions: 4, 5, 6, 10, 11
151 
152     params.regionParams[4].presRegion  = const_cast<MOS_RESOURCE *>(&m_resHucPakInsertUncompressedHeaderWriteBuffer);
153     params.regionParams[4].isWritable  = true;
154     params.regionParams[5].presRegion  = const_cast<MOS_RESOURCE *>(&m_resCompressedHeaderBuffer);
155     params.regionParams[5].isWritable  = true;
156     params.regionParams[6].presRegion  = const_cast<MOS_RESOURCE *>(&m_resVdencPictureState2ndLevelBatchBufferWrite[0]);
157     params.regionParams[6].isWritable  = true;
158     params.regionParams[10].presRegion = const_cast<MOS_RESOURCE *>(&m_basicFeature->m_resBitstreamBuffer);
159     params.regionParams[10].isWritable = true;
160     params.regionParams[11].presRegion = const_cast<MOS_RESOURCE *>(&m_resVdencDataExtensionBuffer);
161     params.regionParams[11].isWritable = true;
162 
163     return MOS_STATUS_SUCCESS;
164 }
165 
ConstructPicStateBatchBuffer(EncodePipeline * pipeline)166 MOS_STATUS Vp9EncodePak::ConstructPicStateBatchBuffer(EncodePipeline* pipeline)
167 {
168     ENCODE_FUNC_CALL();
169     ENCODE_CHK_NULL_RETURN(pipeline);
170     ENCODE_CHK_NULL_RETURN(m_basicFeature);
171 
172     auto currPass    = pipeline->GetCurrentPass();
173     auto passNum     = pipeline->GetPassNum();
174     auto isFirstPipe = pipeline->IsFirstPipe();
175     auto isLastPass  = pipeline->IsLastPass();
176 
177     auto dysRefFrameFlags = m_basicFeature->m_ref.DysRefFrameFlags();
178     if ((dysRefFrameFlags == DYS_REF_NONE) && m_basicFeature->m_pakOnlyModeEnabledForLastPass)
179     {
180         // This flag sets PAK-only mode in SLBB for rePAK pass. In single-pass mode, this flag should be disabled.
181         m_basicFeature->m_vdencPakonlyMultipassEnabled = ((passNum > 1) && isLastPass) ? true : false;
182     }
183 
184     // This function will call by Vp9HucProbPkt or Vp9HucBrcUpdatePkt.
185     // Only construct once.
186     // Check if picture state 2nd level batch buffer already constrcuted, than skip.
187     if (currPass < 3 && m_picState2ndLevelBBConstructed[currPass])
188     {
189         return MOS_STATUS_SUCCESS;
190     }
191 
192     PMOS_RESOURCE picStateBuffer = nullptr;
193     if (dysRefFrameFlags != DYS_REF_NONE && m_basicFeature->m_dysVdencMultiPassEnabled)
194     {
195         picStateBuffer = &m_resVdencDysPictureState2ndLevelBatchBuffer;
196     }
197     else
198     {
199         if (!isFirstPipe)
200         {
201             return MOS_STATUS_SUCCESS;
202         }
203 
204         if (currPass >= 3)
205         {
206             ENCODE_ASSERTMESSAGE("Index exceeds the max number, when try to get m_resVdencPictureState2ndLevelBatchBufferRead;");
207             return MOS_STATUS_INVALID_PARAMETER;
208         }
209 
210         picStateBuffer = &m_resVdencPictureState2ndLevelBatchBufferRead[currPass][m_vdencPictureState2ndLevelBBIndex];
211     }
212     ENCODE_CHK_NULL_RETURN(picStateBuffer);
213 
214     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
215 
216     auto vp9SeqParams = static_cast<PCODEC_VP9_ENCODE_SEQUENCE_PARAMS>(m_basicFeature->m_vp9SeqParams);
217     ENCODE_CHK_NULL_RETURN(vp9SeqParams);
218     auto vp9PicParams = static_cast<PCODEC_VP9_ENCODE_PIC_PARAMS>(m_basicFeature->m_vp9PicParams);
219     ENCODE_CHK_NULL_RETURN(vp9PicParams);
220     auto vp9SegmentParams = static_cast<PCODEC_VP9_ENCODE_SEGMENT_PARAMS>(m_basicFeature->m_vp9SegmentParams);
221     ENCODE_CHK_NULL_RETURN(vp9SegmentParams);
222     auto osInterface = m_hwInterface->GetOsInterface();
223     ENCODE_CHK_NULL_RETURN(osInterface);
224 
225     uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(picStateBuffer);
226     ENCODE_CHK_NULL_RETURN(data);
227 
228     MOS_COMMAND_BUFFER constructedCmdBuf;
229     MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
230     constructedCmdBuf.pCmdBase   = (uint32_t *)data;
231     constructedCmdBuf.pCmdPtr    = (uint32_t *)data;
232     constructedCmdBuf.iOffset    = 0;
233     constructedCmdBuf.iRemaining = m_vdencPicStateSecondLevelBatchBufferSize;
234 
235     eStatus = AddVdencCmd1Command(constructedCmdBuf);
236     if (eStatus != MOS_STATUS_SUCCESS)
237     {
238         ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(picStateBuffer));
239         ENCODE_ASSERTMESSAGE("Failed to add CODECHAL_CMD1 command.");
240         return eStatus;
241     }
242 
243     m_basicFeature->m_hucPicStateOffset       = (uint16_t)constructedCmdBuf.iOffset;
244 
245     SETPAR_AND_ADDCMD(HCP_VP9_PIC_STATE, m_hcpInterfaceNew, &constructedCmdBuf);
246 
247     // HCP_VP9_SEGMENT_STATE
248     uint8_t segmentCount = (vp9PicParams->PicFlags.fields.segmentation_enabled) ? CODEC_VP9_MAX_SEGMENTS : 1;
249 
250     for (uint8_t i = 0; i < segmentCount; i++)
251     {
252         RUN_FEATURE_INTERFACE_RETURN(Vp9Segmentation, Vp9FeatureIDs::vp9Segmentation, SetSegmentId, i);
253         SETPAR_AND_ADDCMD(HCP_VP9_SEGMENT_STATE, m_hcpInterfaceNew, &constructedCmdBuf);
254     }
255 
256     // Adjust cmd buffer offset to have 8 segment state blocks
257     if (segmentCount < CODEC_VP9_MAX_SEGMENTS)
258     {
259         // Max 7 segments, 32 bytes each
260         uint8_t zeroBlock[Vp9Segmentation::m_segmentStateBlockSize * (CODEC_VP9_MAX_SEGMENTS - 1)];
261         MOS_ZeroMemory(zeroBlock, sizeof(zeroBlock));
262         Mhw_AddCommandCmdOrBB(osInterface, &constructedCmdBuf, nullptr, zeroBlock, (CODEC_VP9_MAX_SEGMENTS - segmentCount) * Vp9Segmentation::m_segmentStateBlockSize);
263     }
264 
265     m_basicFeature->m_slbbImgStateOffset = (uint16_t)constructedCmdBuf.iOffset;
266 
267     eStatus = AddVdencCmd2Command(constructedCmdBuf);
268     if (eStatus != MOS_STATUS_SUCCESS)
269     {
270         ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(picStateBuffer));
271         ENCODE_ASSERTMESSAGE("Failed to add CODECHAL_CMD2 command.");
272         return eStatus;
273     }
274 
275     // BB_END
276     eStatus = m_miItf->AddMiBatchBufferEnd(&constructedCmdBuf, nullptr);
277     if (eStatus != MOS_STATUS_SUCCESS)
278     {
279         ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(picStateBuffer));
280         ENCODE_ASSERTMESSAGE("Failed to add MI Batch Buffer End command.");
281         return eStatus;
282     }
283 
284     constructedCmdBuf.iOffset += 24; // padding for alignment on 64
285     constructedCmdBuf.iRemaining -= 24;
286     if ((constructedCmdBuf.iOffset != m_vdencPicStateSecondLevelBatchBufferSize) &&
287         (constructedCmdBuf.iRemaining < 0))
288     {
289         ENCODE_ASSERTMESSAGE("Failed to constructed Second Level Batch Buffer: No space for padding bytes.");
290         return MOS_STATUS_NO_SPACE;
291     }
292 
293     m_basicFeature->m_hucSlbbSize = (uint16_t)constructedCmdBuf.iOffset;
294 
295     ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(picStateBuffer));
296 
297     // Indicated picture state 2nd level batch buffer for this pass already constructed
298     m_picState2ndLevelBBConstructed[currPass] = true;
299 
300     return MOS_STATUS_SUCCESS;
301 }
302 
SetHucPakInsertObjBatchBuffer(MHW_BATCH_BUFFER & secondLevelBatchBuffer)303 MOS_STATUS Vp9EncodePak::SetHucPakInsertObjBatchBuffer(MHW_BATCH_BUFFER &secondLevelBatchBuffer)
304 {
305     ENCODE_FUNC_CALL();
306 
307     secondLevelBatchBuffer.dwOffset     = 0;
308     secondLevelBatchBuffer.bSecondLevel = true;
309 
310     if (!m_basicFeature->m_hucEnabled)
311     {
312         secondLevelBatchBuffer.OsResource = m_resHucPakInsertUncompressedHeaderReadBuffer[m_basicFeature->m_currRecycledBufIdx];
313     }
314     else
315     {
316         secondLevelBatchBuffer.OsResource = m_resHucPakInsertUncompressedHeaderWriteBuffer;
317     }
318 
319     return MOS_STATUS_SUCCESS;
320 }
321 
SetVdencSecondLevelBatchBuffer(uint32_t currPass,MHW_BATCH_BUFFER & secondLevelBatchBuffer)322 MOS_STATUS Vp9EncodePak::SetVdencSecondLevelBatchBuffer(uint32_t currPass, MHW_BATCH_BUFFER &secondLevelBatchBuffer)
323 {
324     ENCODE_FUNC_CALL();
325 
326     secondLevelBatchBuffer.dwOffset     = 0;
327     secondLevelBatchBuffer.bSecondLevel = true;
328 
329     if (m_basicFeature->m_hucEnabled)
330     {
331         secondLevelBatchBuffer.OsResource = m_resVdencPictureState2ndLevelBatchBufferWrite[0];
332     }
333     else
334     {
335         auto dysRefFrameFlags         = m_basicFeature->m_ref.DysRefFrameFlags();
336         auto dysVdencMultiPassEnabled = m_basicFeature->m_dysVdencMultiPassEnabled;
337         if ((dysRefFrameFlags != DYS_REF_NONE) && dysVdencMultiPassEnabled)
338         {
339             secondLevelBatchBuffer.OsResource = m_resVdencDysPictureState2ndLevelBatchBuffer;
340         }
341         else
342         {
343             if (currPass >= 3)
344             {
345                 ENCODE_ASSERTMESSAGE("Index exceeds the max number, when try to set vdenc second level batch buffer;");
346                 return MOS_STATUS_INVALID_PARAMETER;
347             }
348 
349             secondLevelBatchBuffer.OsResource = m_resVdencPictureState2ndLevelBatchBufferRead[currPass][m_vdencPictureState2ndLevelBBIndex];
350         }
351     }
352 
353     return MOS_STATUS_SUCCESS;
354 }
355 
GetVdencPictureState2ndLevelBatchBufferSize(uint32_t & size)356 MOS_STATUS Vp9EncodePak::GetVdencPictureState2ndLevelBatchBufferSize(uint32_t &size)
357 {
358     ENCODE_FUNC_CALL();
359 
360     size = m_vdencPicStateSecondLevelBatchBufferSize;
361 
362     return MOS_STATUS_SUCCESS;
363 }
364 
UpdateParameters()365 MOS_STATUS Vp9EncodePak::UpdateParameters()
366 {
367     ENCODE_FUNC_CALL();
368     ENCODE_CHK_NULL_RETURN(m_basicFeature);
369 
370     if (m_basicFeature->m_hucEnabled)
371     {
372         // We save the index of the 2nd level batch buffer in case is a pass that needs
373         m_lastVdencPictureState2ndLevelBBIndex = m_vdencPictureState2ndLevelBBIndex;
374     }
375     m_vdencPictureState2ndLevelBBIndex = (m_vdencPictureState2ndLevelBBIndex + 1) % CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM;
376 
377     return MOS_STATUS();
378 }
379 
PakConstructPicStateBatchBuffer(PMOS_RESOURCE picStateBuffer)380 MOS_STATUS Vp9EncodePak::PakConstructPicStateBatchBuffer(PMOS_RESOURCE picStateBuffer)
381 {
382     ENCODE_FUNC_CALL();
383     ENCODE_CHK_NULL_RETURN(picStateBuffer);
384 
385     uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(picStateBuffer);
386     ENCODE_CHK_NULL_RETURN(data);
387 
388     for (int i = 0; i < CODECHAL_ENCODE_VP9_BRC_MAX_NUM_OF_PASSES; ++i)
389     {
390         MOS_COMMAND_BUFFER constructedCmdBuf;
391 
392         constructedCmdBuf.pCmdBase   = (uint32_t *)data;
393         constructedCmdBuf.pCmdPtr    = (uint32_t *)(data + i * CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS);
394         constructedCmdBuf.iOffset    = 0;
395         constructedCmdBuf.iRemaining = CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS;
396 
397         SETPAR_AND_ADDCMD(HCP_VP9_PIC_STATE, m_hcpInterfaceNew, &constructedCmdBuf);
398 
399         // After adding pic state cmds in above function, pCmdPtr is not at the end of the picState buffer, so adjust it.
400         // -1 to go back one uint32_t where BB end will be added
401         constructedCmdBuf.pCmdPtr = (uint32_t *)(data + (i + 1) * CODECHAL_ENCODE_VP9_PIC_STATE_BUFFER_SIZE_PER_PASS) - 1;
402 
403         ENCODE_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(&constructedCmdBuf, nullptr));
404     }
405 
406     m_allocator->UnLock(picStateBuffer);
407 
408     return MOS_STATUS_SUCCESS;
409 }
410 
GetCompressedHeaderBuffer()411 PMOS_RESOURCE Vp9EncodePak::GetCompressedHeaderBuffer()
412 {
413     ENCODE_FUNC_CALL();
414 
415     return &m_resCompressedHeaderBuffer;
416 }
417 
AllocateResources()418 MOS_STATUS Vp9EncodePak::AllocateResources()
419 {
420     ENCODE_FUNC_CALL();
421     ENCODE_CHK_NULL_RETURN(m_basicFeature);
422 
423     MOS_RESOURCE *allocatedBuffer = nullptr;
424     // Initiate allocation parameters and lock flags
425     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
426     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
427     allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
428     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
429     allocParamsForBufferLinear.Format   = Format_Buffer;
430 
431     // VDENC picture second level batch buffer (Read/Write)
432     allocParamsForBufferLinear.dwBytes  = MOS_ALIGN_CEIL(m_vdencPicStateSecondLevelBatchBufferSize, CODECHAL_PAGE_SIZE);
433     allocParamsForBufferLinear.pBufName = "VDENC Picture Second Level Batch Buffer Read";
434     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
435     for (auto i = 0; i < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; ++i)
436     {
437         for (auto j = 0; j < 3; ++j)
438         {
439             allocatedBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
440             ENCODE_CHK_NULL_RETURN(allocatedBuffer);
441             m_resVdencPictureState2ndLevelBatchBufferRead[j][i] = *allocatedBuffer;
442         }
443     }
444 
445     allocParamsForBufferLinear.pBufName = "VDENC Picture Second Level Batch Buffer Write";
446     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
447     for (auto i = 0; i < CODECHAL_VP9_ENCODE_RECYCLED_BUFFER_NUM; ++i)
448     {
449         allocatedBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
450         ENCODE_CHK_NULL_RETURN(allocatedBuffer);
451         m_resVdencPictureState2ndLevelBatchBufferWrite[i] = *allocatedBuffer;
452     }
453 
454     // Huc VP9 pak insert uncompressed header
455     allocParamsForBufferLinear.dwBytes  = CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER;
456     allocParamsForBufferLinear.pBufName = "HucPakInsertUncompressedHeaderReadBuffer";
457     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
458     for (auto i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; ++i)
459     {
460         allocatedBuffer = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
461         ENCODE_CHK_NULL_RETURN(allocatedBuffer);
462         m_resHucPakInsertUncompressedHeaderReadBuffer[i] = *allocatedBuffer;
463     }
464 
465     allocParamsForBufferLinear.dwBytes  = CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER;
466     allocParamsForBufferLinear.pBufName = "HucPakInsertUncompressedHeaderWriteBuffer";
467     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
468     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
469     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
470     m_resHucPakInsertUncompressedHeaderWriteBuffer = *allocatedBuffer;
471 
472     // Compressed header buffer
473     allocParamsForBufferLinear.dwBytes  = 32 * CODECHAL_CACHELINE_SIZE;
474     allocParamsForBufferLinear.pBufName = "CompressedHeaderBuffer";
475     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
476     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
477     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
478     m_resCompressedHeaderBuffer = *allocatedBuffer;
479 
480     // Allocate data extension buffer
481     allocParamsForBufferLinear.dwBytes  = CODECHAL_ENCODE_VP9_VDENC_DATA_EXTENSION_SIZE;
482     allocParamsForBufferLinear.pBufName = "DataExtensionBuffer";
483     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
484     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
485     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
486     m_resVdencDataExtensionBuffer = *allocatedBuffer;
487 
488     // Metadata line buffer
489     uint32_t size                       = m_basicFeature->m_maxPicWidthInSb * 5 * CODECHAL_CACHELINE_SIZE;
490     allocParamsForBufferLinear.dwBytes  = size;
491     allocParamsForBufferLinear.pBufName = "MetadataLineBuffer";
492     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
493     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
494     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
495     m_resMetadataLineBuffer = allocatedBuffer;
496 
497     // Metadata tile line buffer
498     size                                = m_basicFeature->m_maxPicWidthInSb * 5 * CODECHAL_CACHELINE_SIZE;
499     allocParamsForBufferLinear.dwBytes  = size;
500     allocParamsForBufferLinear.pBufName = "MetadataTileLineBuffer";
501     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
502     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
503     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
504     m_resMetadataTileLineBuffer = allocatedBuffer;
505 
506     // Metadata tile column buffer
507     size                                = m_basicFeature->m_maxPicHeightInSb * 5 * CODECHAL_CACHELINE_SIZE;
508     allocParamsForBufferLinear.dwBytes  = size;
509     allocParamsForBufferLinear.pBufName = "MetadataTileColumnBuffer";
510     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
511     allocatedBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
512     ENCODE_CHK_NULL_RETURN(allocatedBuffer);
513     m_resMetadataTileColumnBuffer = allocatedBuffer;
514 
515     return MOS_STATUS_SUCCESS;
516 }
517 
ConstructPakInsertObjBatchBuffer()518 MOS_STATUS Vp9EncodePak::ConstructPakInsertObjBatchBuffer()
519 {
520     ENCODE_FUNC_CALL();
521 
522     ENCODE_CHK_NULL_RETURN(m_hwInterface);
523     uint32_t nalUnitSize   = m_basicFeature->m_nalUnitParams[0]->uiSize;
524     uint32_t nalUnitOffset = m_basicFeature->m_nalUnitParams[0]->uiOffset;
525     ENCODE_ASSERT(nalUnitSize > 0 && nalUnitSize < CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER);
526 
527     uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(&m_resHucPakInsertUncompressedHeaderReadBuffer[m_basicFeature->m_currRecycledBufIdx]);
528     ENCODE_CHK_NULL_RETURN(data);
529 
530     MOS_COMMAND_BUFFER constructedCmdBuf;
531     MOS_ZeroMemory(&constructedCmdBuf, sizeof(constructedCmdBuf));
532     constructedCmdBuf.pCmdBase   = (uint32_t *)data;
533     constructedCmdBuf.pCmdPtr    = (uint32_t *)data;
534     constructedCmdBuf.iOffset    = 0;
535     constructedCmdBuf.iRemaining = CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER;
536 
537     SETPAR_AND_ADDCMD(HCP_PAK_INSERT_OBJECT, m_hcpInterfaceNew, &constructedCmdBuf);
538 
539     uint32_t byteSize = (nalUnitSize * 8 + 7) >> 3;
540 
541     if (byteSize)
542     {
543         MHW_MI_CHK_NULL(&m_basicFeature->m_bsBuffer);
544         MHW_MI_CHK_NULL(m_basicFeature->m_bsBuffer.pBase);
545         uint8_t *data_bb = (uint8_t *)(m_basicFeature->m_bsBuffer.pBase + nalUnitOffset);
546         MHW_MI_CHK_STATUS(Mhw_AddCommandCmdOrBB(m_hwInterface->GetOsInterface(), &constructedCmdBuf, nullptr, data_bb, byteSize));
547     }
548 
549     ENCODE_CHK_STATUS_RETURN(m_miItf->AddMiBatchBufferEnd(&constructedCmdBuf, nullptr));
550 
551     ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(&m_resHucPakInsertUncompressedHeaderReadBuffer[m_basicFeature->m_currRecycledBufIdx]));
552 
553     return MOS_STATUS_SUCCESS;
554 }
555 
PreparePakObjAndCuRecord()556 MOS_STATUS Vp9EncodePak::PreparePakObjAndCuRecord()
557 {
558     ENCODE_FUNC_CALL();
559 
560     auto picWidthInSb  = m_basicFeature->m_picWidthInSb;
561     auto picHeightInSb = m_basicFeature->m_picHeightInSb;
562 
563     // We use PAK to perform dynamic scaling for reference frame, basically if every CU is inter and skipped, the reconstructed picture will be
564     // the down scaled copy of reference frame.
565     // Here driver needs to prepare pak obj and cu record, since PAK has a limitation that input picture needs to be CU boundary aligned,
566     // and to simplify handling the boundary condition, we set each CU with size 8x8, inter and zero MV.
567     // Segment skip needs to be turned on also.
568 
569     auto oriFrameWidth  = MOS_ALIGN_CEIL(m_basicFeature->m_oriFrameWidth, CODEC_VP9_MIN_BLOCK_WIDTH);
570     auto oriFrameHeight = MOS_ALIGN_CEIL(m_basicFeature->m_oriFrameHeight, CODEC_VP9_MIN_BLOCK_HEIGHT);
571 
572     uint32_t numCuLastSbCol = (oriFrameWidth / CODEC_VP9_MIN_BLOCK_WIDTH) -
573                               (picWidthInSb - 1) * (CODEC_VP9_SUPER_BLOCK_WIDTH / CODEC_VP9_MIN_BLOCK_WIDTH);
574     uint32_t numCuLastSbRow = (oriFrameHeight / CODEC_VP9_MIN_BLOCK_HEIGHT) -
575                               (picHeightInSb - 1) * (CODEC_VP9_SUPER_BLOCK_HEIGHT / CODEC_VP9_MIN_BLOCK_HEIGHT);
576 
577     auto data = (uint8_t *)m_allocator->LockResourceForWrite(m_basicFeature->m_resMbCodeBuffer);
578     ENCODE_CHK_NULL_RETURN(data);
579 
580     HcpPakObject *pakObjData = (HcpPakObject *)data;
581     CU_DATA *     cuDataPtr  = (CU_DATA *)(data + m_basicFeature->m_mvOffset);
582 
583     // Fill PAK object
584     HcpPakObject pakObj;
585     MOS_ZeroMemory(&pakObj, sizeof(pakObj));
586     pakObj.DW0.Type        = 0x03;
587     pakObj.DW0.Opcode      = 0x27;
588     pakObj.DW0.SubOp       = 0x35;
589     pakObj.DW0.DwordLength = 1;  // Total 4 DW. But only 3 DW are actual fields
590                                  // DW0/DW1/DW2 excluded from this field as per spec definition
591     pakObj.DW1.Split_flag_level0             = 1;
592     pakObj.DW1.Split_flag_level1             = 0xF;
593     pakObj.DW1.Split_flag_level2_level1part0 = 0xF;
594     pakObj.DW1.Split_flag_level2_level1part1 = 0xF;
595     pakObj.DW1.Split_flag_level2_level1part2 = 0xF;
596     pakObj.DW1.Split_flag_level2_level1part3 = 0xF;
597 
598     // Fill CU data
599     CU_DATA cuData;
600     MOS_ZeroMemory(&cuData, sizeof(cuData));
601     cuData.cu_size           = 0;                         // 8x8
602     cuData.cu_pred_mode0     = cuData.cu_pred_mode1 = 1;  // Inter
603     cuData.refframe_part0_l0 = cuData.refframe_part1_l0 = m_basicFeature->m_ref.GetDysRefIndex();
604 
605     for (uint32_t j = 0; j < picHeightInSb; ++j)
606     {
607         for (uint32_t i = 0; i < picWidthInSb; ++i)
608         {
609             if ((j == picHeightInSb - 1) && (i == picWidthInSb - 1))
610             {
611                 pakObj.DW1.CU_count_minus1   = numCuLastSbCol * numCuLastSbRow - 1;
612                 pakObj.DW1.IsLastSBFrameflag = 1;
613                 pakObj.DW1.IsLastSBTileflag  = 1;
614                 pakObj.Reserved_DW03         = 0x05000000;  // add batch buffer end flag
615             }
616             else if (i == picWidthInSb - 1)
617             {
618                 pakObj.DW1.CU_count_minus1 = numCuLastSbCol * 8 - 1;
619             }
620             else if (j == picHeightInSb - 1)
621             {
622                 pakObj.DW1.CU_count_minus1 = numCuLastSbRow * 8 - 1;
623             }
624             else
625             {
626                 pakObj.DW1.CU_count_minus1 = 63;
627             }
628 
629             pakObj.DW2.Current_SB_X_Addr = i;
630             pakObj.DW2.Current_SB_Y_Addr = j;
631 
632             *pakObjData++ = pakObj;
633 
634             for (unsigned int cuIdx = 0; cuIdx < 64; cuIdx++)
635             {
636                 *cuDataPtr++ = cuData;
637             }
638         }
639     }
640     ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(m_basicFeature->m_resMbCodeBuffer));
641 
642     return MOS_STATUS_SUCCESS;
643 }
644 
AddVdencCmd1Command(MOS_COMMAND_BUFFER & cmdBuffer)645 MOS_STATUS Vp9EncodePak::AddVdencCmd1Command(MOS_COMMAND_BUFFER &cmdBuffer)
646 {
647     ENCODE_FUNC_CALL();
648 
649     ENCODE_CHK_NULL_RETURN(m_vdencInterfaceNew);
650 
651     ENCODE_CHK_NULL_RETURN(m_basicFeature);
652     ENCODE_CHK_NULL_RETURN(m_basicFeature->m_vp9PicParams);
653 
654     SETPAR_AND_ADDCMD(VDENC_CMD1, m_vdencInterfaceNew, &cmdBuffer);
655 
656     return MOS_STATUS_SUCCESS;
657 }
658 
AddVdencCmd2Command(MOS_COMMAND_BUFFER & cmdBuffer)659 MOS_STATUS Vp9EncodePak::AddVdencCmd2Command(MOS_COMMAND_BUFFER &cmdBuffer)
660 {
661     ENCODE_FUNC_CALL();
662 
663     ENCODE_CHK_NULL_RETURN(m_vdencInterfaceNew);
664 
665     SETPAR_AND_ADDCMD(VDENC_CMD2, m_vdencInterfaceNew, &cmdBuffer);
666 
667     return MOS_STATUS_SUCCESS;
668 }
669 
CalculateQpLambdaValues(double & sadQpLambda,double & rdQpLambda)670 void Vp9EncodePak::CalculateQpLambdaValues(double &sadQpLambda, double &rdQpLambda)
671 {
672     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature->m_vp9PicParams);
673 
674     auto   qp           = m_basicFeature->m_vp9PicParams->LumaACQIndex;
675     auto   vp9FrameType = m_basicFeature->m_vp9PicParams->PicFlags.fields.frame_type;
676     double QPScale      = (vp9FrameType == CODEC_VP9_KEY_FRAME) ? 0.31 : 0.33;
677     double lambda       = QPScale * CODECHAL_VP9_QUANT_AC[qp] / 8;
678 
679     sadQpLambda = lambda * 4 + 0.5;
680     rdQpLambda  = lambda * lambda * 4 + 0.5;
681 }
682 
MHW_SETPAR_DECL_SRC(HCP_PAK_INSERT_OBJECT,Vp9EncodePak)683 MHW_SETPAR_DECL_SRC(HCP_PAK_INSERT_OBJECT, Vp9EncodePak)
684 {
685     ENCODE_FUNC_CALL();
686 
687     uint32_t nalUnitSize = m_basicFeature->m_nalUnitParams[0]->uiSize;
688     ENCODE_ASSERT(nalUnitSize > 0 && nalUnitSize < CODECHAL_ENCODE_VP9_PAK_INSERT_UNCOMPRESSED_HEADER);
689 
690     uint32_t byteSize         = (nalUnitSize * 8 + 7) >> 3;
691     uint32_t dataBitsInLastDw = nalUnitSize * 8 % 32;
692     if (dataBitsInLastDw == 0)
693     {
694         dataBitsInLastDw = 32;
695     }
696 
697     params.dwPadding = (MOS_ALIGN_CEIL(byteSize, sizeof(uint32_t))) / sizeof(uint32_t);
698 
699     params.bEmulationByteBitsInsert  = false;
700     params.uiSkipEmulationCheckCount = m_basicFeature->m_nalUnitParams[0]->uiSkipEmulationCheckCount;
701     params.dataBitsInLastDw          = dataBitsInLastDw;
702     params.bEndOfSlice               = false;
703     params.bLastHeader               = true;
704 
705     return MOS_STATUS_SUCCESS;
706 }
707 
MHW_SETPAR_DECL_SRC(HCP_IND_OBJ_BASE_ADDR_STATE,Vp9EncodePak)708 MHW_SETPAR_DECL_SRC(HCP_IND_OBJ_BASE_ADDR_STATE, Vp9EncodePak)
709 {
710     ENCODE_FUNC_CALL();
711 
712     params.presCompressedHeaderBuffer = const_cast<PMOS_RESOURCE>(&m_resCompressedHeaderBuffer);
713     params.dwCompressedHeaderSize     = 32 * CODECHAL_CACHELINE_SIZE;
714 
715     return MOS_STATUS_SUCCESS;
716 }
717 
MHW_SETPAR_DECL_SRC(HCP_PIPE_BUF_ADDR_STATE,Vp9EncodePak)718 MHW_SETPAR_DECL_SRC(HCP_PIPE_BUF_ADDR_STATE, Vp9EncodePak)
719 {
720     ENCODE_FUNC_CALL();
721 
722     params.presMetadataLineBuffer       = m_resMetadataLineBuffer;
723     params.presMetadataTileLineBuffer   = m_resMetadataTileLineBuffer;
724     params.presMetadataTileColumnBuffer = m_resMetadataTileColumnBuffer;
725 
726     return MOS_STATUS_SUCCESS;
727 }
728 
729 }  // namespace encode
730