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 ¶ms, 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 ¶ms, 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