1 /*
2 * Copyright (c) 2019-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,Av1EncodeTile
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_av1_tile.cpp
24 //! \brief Defines the common interface for av1 tile
25 //!
26
27 #include "encode_av1_tile.h"
28 #include "encode_av1_vdenc_feature_manager.h"
29 #include "codec_def_common_av1.h"
30 #include "encode_av1_basic_feature.h"
31
32 namespace encode
33 {
VdencStatistics()34 VdencStatistics::VdencStatistics()
35 {
36 MOS_ZeroMemory(this, sizeof(*this));
37 }
38
Av1EncodeTile(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)39 Av1EncodeTile::Av1EncodeTile(
40 MediaFeatureManager *featureManager,
41 EncodeAllocator *allocator,
42 CodechalHwInterfaceNext *hwInterface,
43 void *constSettings) :
44 EncodeTile(featureManager, allocator, hwInterface, constSettings)
45 {
46 auto encFeatureManager = dynamic_cast<EncodeAv1VdencFeatureManager *>(featureManager);
47 ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
48
49 m_basicFeature = dynamic_cast<EncodeBasicFeature *>(encFeatureManager->GetFeature(Av1FeatureIDs::basicFeature));
50 ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
51 }
52
~Av1EncodeTile()53 Av1EncodeTile::~Av1EncodeTile()
54 {
55 for (auto i = 0; i < CODECHAL_GET_ARRAY_LENGTH(m_reportTileGroupParams); i++)
56 {
57 MOS_FreeMemory(m_reportTileGroupParams[i]);
58 }
59 }
60
Init(void * settings)61 MOS_STATUS Av1EncodeTile::Init(void *settings)
62 {
63 ENCODE_FUNC_CALL();
64 ENCODE_CHK_NULL_RETURN(settings);
65
66 // Make these BB recycled
67 ENCODE_CHK_STATUS_RETURN(AllocateResources());
68
69 return MOS_STATUS_SUCCESS;
70 }
71
Update(void * params)72 MOS_STATUS Av1EncodeTile::Update(void *params)
73 {
74 ENCODE_FUNC_CALL();
75 ENCODE_CHK_NULL_RETURN(params);
76 EncoderParams* encodeParams = (EncoderParams*)params;
77
78 m_enabled = true;
79
80 m_maxTileNumber = CODECHAL_GET_WIDTH_IN_BLOCKS(m_basicFeature->m_frameWidth, av1MinTileWidth) *
81 CODECHAL_GET_HEIGHT_IN_BLOCKS(m_basicFeature->m_frameHeight, av1MinTileHeight);
82
83 ENCODE_CHK_STATUS_RETURN(EncodeTile::Update(params));
84
85 m_av1TileGroupParams = static_cast<PCODEC_AV1_ENCODE_TILE_GROUP_PARAMS>(encodeParams->pSliceParams);
86 ENCODE_CHK_NULL_RETURN(m_av1TileGroupParams);
87 m_numTileGroups = encodeParams->dwNumSlices;
88
89 if (m_reportTileGroupParams[m_statisticsBufIndex] != nullptr)
90 {
91 MOS_FreeMemory(m_reportTileGroupParams[m_statisticsBufIndex]);
92 m_reportTileGroupParams[m_statisticsBufIndex] = nullptr;
93 }
94 m_reportTileGroupParams[m_statisticsBufIndex] = static_cast<Av1ReportTileGroupParams *>(MOS_AllocAndZeroMemory(
95 sizeof(Av1ReportTileGroupParams) * m_numTileGroups));
96
97 auto av1PicParam = static_cast<PCODEC_AV1_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
98
99 // Check each tile size
100 ENCODE_CHK_STATUS_RETURN(TileSizeCheck(av1PicParam));
101
102 // For FrameOBU + single tile, tile group header will be empty in spec, so directly skip below function.
103 if (!(av1PicParam->PicFlags.fields.EnableFrameOBU && m_numTiles == 1))
104 {
105 ENCODE_CHK_STATUS_RETURN(MakeTileGroupHeaderAv1(params));
106 }
107
108 // Setup tile group report data
109 // Make this structure recycled
110 ENCODE_CHK_STATUS_RETURN(SetTileGroupReportParams());
111
112 return MOS_STATUS_SUCCESS;
113 }
114
IsFirstTileInGroup(bool & firstTileInGroup,uint32_t & tileGroupIdx) const115 MOS_STATUS Av1EncodeTile::IsFirstTileInGroup(bool &firstTileInGroup, uint32_t &tileGroupIdx) const
116 {
117 ENCODE_FUNC_CALL();
118
119 auto tmpTileGroupParams = m_av1TileGroupParams;
120 for (uint16_t tileGrupCnt = 0; tileGrupCnt < m_numTileGroups; tileGrupCnt++)
121 {
122 if (tmpTileGroupParams->TileGroupStart <= m_tileIdx &&
123 tmpTileGroupParams->TileGroupEnd >= m_tileIdx)
124 {
125 firstTileInGroup = (tmpTileGroupParams->TileGroupStart == m_tileIdx);
126 tileGroupIdx = tileGrupCnt;
127 break;
128 }
129 tmpTileGroupParams++;
130 }
131
132 return MOS_STATUS_SUCCESS;
133 }
134
SetHucCtrlBuffer(VdencAv1HucCtrlBigData & hucCtrlBuffer)135 MOS_STATUS Av1EncodeTile::SetHucCtrlBuffer(VdencAv1HucCtrlBigData& hucCtrlBuffer)
136 {
137 ENCODE_FUNC_CALL();
138 ENCODE_CHK_NULL_RETURN(m_av1TileGroupParams);
139
140 for (uint32_t i = 0; i < m_numTileGroups; i++)
141 {
142 hucCtrlBuffer.tileNumberPerGroup[i] = m_av1TileGroupParams[i].TileGroupEnd - m_av1TileGroupParams[i].TileGroupStart + 1;
143 }
144
145 return MOS_STATUS_SUCCESS;
146 }
147
CalculateTilesBoundary(PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams,uint32_t * rowBd,uint32_t * colBd)148 MOS_STATUS Av1EncodeTile::CalculateTilesBoundary(
149 PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams,
150 uint32_t *rowBd,
151 uint32_t *colBd)
152 {
153 ENCODE_FUNC_CALL();
154
155 ENCODE_CHK_NULL_RETURN(av1PicParams);
156 ENCODE_CHK_NULL_RETURN(rowBd);
157 ENCODE_CHK_NULL_RETURN(colBd);
158
159 for (uint32_t i = 0; i < m_numTileColumns; i++)
160 {
161 colBd[i + 1] = colBd[i] + av1PicParams->width_in_sbs_minus_1[i] + 1;
162 }
163
164 for (uint32_t i = 0; i < m_numTileRows; i++)
165 {
166 rowBd[i + 1] = rowBd[i] + av1PicParams->height_in_sbs_minus_1[i] + 1;
167 }
168
169 return MOS_STATUS_SUCCESS;
170
171 }
172
CalculateNumLcuByTiles(PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams)173 MOS_STATUS Av1EncodeTile::CalculateNumLcuByTiles(PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams)
174 {
175 ENCODE_FUNC_CALL();
176
177 ENCODE_CHK_NULL_RETURN(av1PicParams);
178
179 m_numSbInPic = 0;
180 for (uint32_t i = 0; i < m_numTileRows; i++)
181 {
182 for (uint32_t j = 0; j < m_numTileColumns; j++)
183 {
184 m_numSbInPic += (av1PicParams->height_in_sbs_minus_1[i] + 1) * (av1PicParams->width_in_sbs_minus_1[j] + 1);
185 }
186 }
187
188 if (m_numSbInPic == 0)
189 {
190 ENCODE_ASSERTMESSAGE("LCU num cal by each tile is zero, sth must be wrong!");
191 return MOS_STATUS_INVALID_PARAMETER;
192 }
193
194 return MOS_STATUS_SUCCESS;
195 }
196
AllocateTileStatistics(void * params)197 MOS_STATUS Av1EncodeTile::AllocateTileStatistics(void *params)
198 {
199 ENCODE_FUNC_CALL();
200
201 ENCODE_CHK_NULL_RETURN(params);
202
203 MOS_ZeroMemory(&m_av1FrameStatsOffset, sizeof(Av1TileStatusInfo));
204 MOS_ZeroMemory(&m_av1TileStatsOffset, sizeof(Av1TileStatusInfo));
205 MOS_ZeroMemory(&m_av1StatsSize, sizeof(Av1TileStatusInfo));
206
207 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
208 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
209 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
210 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
211 allocParamsForBufferLinear.Format = Format_Buffer;
212
213 // Set the maximum size based on frame level statistics.
214 m_av1StatsSize.uiAv1PakStatistics = EncodeBasicFeature::m_sizeOfHcpPakFrameStats;
215 m_av1StatsSize.uiVdencStatistics = m_av1VdencStateSize;
216
217 // Maintain the offsets to use for patching addresses in to the HuC Pak Integration kernel Aggregated Frame Statistics Output Buffer
218 // Each offset needs to be page aligned as the combined region is fed into different page aligned HuC regions
219 m_av1FrameStatsOffset.uiAv1PakStatistics = 0;
220 m_av1FrameStatsOffset.uiVdencStatistics = MOS_ALIGN_CEIL(m_av1FrameStatsOffset.uiAv1PakStatistics + m_av1StatsSize.uiAv1PakStatistics, CODECHAL_PAGE_SIZE);
221
222 // Frame level statistics
223 m_hwInterface->m_pakIntAggregatedFrameStatsSize = MOS_ALIGN_CEIL(m_av1FrameStatsOffset.uiVdencStatistics + (m_av1StatsSize.uiVdencStatistics * m_numTiles), CODECHAL_PAGE_SIZE);
224
225 // AV1 Frame Statistics Buffer - Output from HuC PAK Integration kernel
226 if (Mos_ResourceIsNull(&m_resHuCPakAggregatedFrameStatsBuffer))
227 {
228 allocParamsForBufferLinear.dwBytes = m_hwInterface->m_pakIntAggregatedFrameStatsSize;
229 allocParamsForBufferLinear.pBufName = "AVP Aggregated Frame Statistics Streamout Buffer";
230 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
231
232 auto resource = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
233 ENCODE_CHK_NULL_RETURN(resource);
234 m_resHuCPakAggregatedFrameStatsBuffer = *resource;
235 }
236
237 // Maintain the offsets to use for patching addresses in to the Tile Based Statistics Buffer
238 // Each offset needs to be page aligned as the combined region is fed into different page aligned HuC regions
239
240 m_av1TileStatsOffset.uiAv1PakStatistics = 0; // PakStatistics is head of m_resTileBasedStatisticsBuffer;
241 m_av1TileStatsOffset.uiVdencStatistics = MOS_ALIGN_CEIL(m_av1TileStatsOffset.uiAv1PakStatistics + (m_av1StatsSize.uiAv1PakStatistics * m_numTiles), CODECHAL_PAGE_SIZE);
242 // Combined statistics size for all tiles
243 m_hwInterface->m_pakIntTileStatsSize = MOS_ALIGN_CEIL(m_av1TileStatsOffset.uiVdencStatistics + m_av1StatsSize.uiVdencStatistics * m_numTiles, CODECHAL_PAGE_SIZE);
244
245 // Tile size record size for all tiles
246 m_hwInterface->m_tileRecordSize = CODECHAL_CACHELINE_SIZE * m_numTiles;
247
248 MOS_SURFACE surface;
249 MOS_ZeroMemory(&surface, sizeof(surface));
250 uint32_t curPakIntTileStatsSize = 0;
251 surface.OsResource = m_resTileBasedStatisticsBuffer[m_statisticsBufIndex];
252 if (!Mos_ResourceIsNull(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]))
253 {
254 m_allocator->GetSurfaceInfo(&surface);
255 curPakIntTileStatsSize = surface.dwHeight * surface.dwWidth;
256 }
257
258 if (Mos_ResourceIsNull(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]) ||
259 curPakIntTileStatsSize < m_hwInterface->m_pakIntTileStatsSize)
260 {
261 if (!Mos_ResourceIsNull(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]))
262 {
263 m_allocator->DestroyResource(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]);
264 }
265 allocParamsForBufferLinear.dwBytes = m_hwInterface->m_pakIntTileStatsSize;
266 allocParamsForBufferLinear.pBufName = "AVP Tile Level Statistics Streamout Buffer";
267 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
268
269 auto resource = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
270 ENCODE_CHK_NULL_RETURN(resource);
271 m_resTileBasedStatisticsBuffer[m_statisticsBufIndex] = *resource;
272 }
273
274 // Allocate the updated tile size buffer for PAK integration kernel
275 if (Mos_ResourceIsNull(&m_tileRecordBuffer[m_statisticsBufIndex]))
276 {
277 allocParamsForBufferLinear.dwBytes = m_hwInterface->m_tileRecordSize;
278 allocParamsForBufferLinear.pBufName = "Tile Record Buffer";
279 allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
280
281 auto resource = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
282 ENCODE_CHK_NULL_RETURN(resource);
283 m_tileRecordBuffer[m_statisticsBufIndex] = *resource;
284 }
285
286 return MOS_STATUS_SUCCESS;
287 }
288
CalculateTileWidthAndHeight(PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams,uint32_t rowIndex,uint32_t colIndex,uint32_t * rowBd,uint32_t * colBd)289 MOS_STATUS Av1EncodeTile::CalculateTileWidthAndHeight(
290 PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams,
291 uint32_t rowIndex,
292 uint32_t colIndex,
293 uint32_t *rowBd,
294 uint32_t *colBd)
295 {
296 ENCODE_FUNC_CALL();
297
298 ENCODE_CHK_NULL_RETURN(av1PicParams);
299 ENCODE_CHK_NULL_RETURN(rowBd);
300 ENCODE_CHK_NULL_RETURN(colBd);
301
302 uint32_t idx = rowIndex * m_numTileColumns + colIndex;
303 uint32_t frameWidthInMinCb = MOS_ROUNDUP_DIVIDE((av1PicParams->frame_width_minus1 + 1), av1MinBlockWidth);
304 uint32_t frameHeightInMinCb = MOS_ROUNDUP_DIVIDE((av1PicParams->frame_height_minus1 + 1), av1MinBlockHeight);
305 uint32_t ratio = av1SuperBlockHeight / av1MinBlockHeight;
306
307 if (colIndex != m_numTileColumns - 1)
308 {
309 m_tileData[idx].tileWidthInMinCbMinus1 = (av1PicParams->width_in_sbs_minus_1[colIndex] + 1) * ratio - 1;
310 m_tileData[idx].isLastTileofRow = false;
311 }
312 else
313 {
314 m_tileData[idx].tileWidthInMinCbMinus1 = (frameWidthInMinCb - colBd[colIndex] * ratio) - 1;
315 m_tileData[idx].isLastTileofRow = true;
316 }
317
318 if (rowIndex != m_numTileRows - 1)
319 {
320 m_tileData[idx].isLastTileofColumn = false;
321 m_tileData[idx].tileHeightInMinCbMinus1 = (av1PicParams->height_in_sbs_minus_1[rowIndex] +1 ) * ratio - 1;
322 }
323 else
324 {
325 m_tileData[idx].tileHeightInMinCbMinus1 = (frameHeightInMinCb - rowBd[rowIndex] * ratio) - 1;
326 m_tileData[idx].isLastTileofColumn = true;
327 }
328
329 return MOS_STATUS_SUCCESS;
330 }
331
SetTileData(void * params)332 MOS_STATUS Av1EncodeTile::SetTileData(void *params)
333 {
334 ENCODE_FUNC_CALL();
335
336 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
337
338 if (!m_enabled)
339 {
340 return eStatus;
341 }
342
343 ENCODE_CHK_NULL_RETURN(params);
344
345 EncoderParams* encodeParams = (EncoderParams*)params;
346 ENCODE_CHK_NULL_RETURN(encodeParams);
347
348 PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams =
349 static_cast<PCODEC_AV1_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
350 ENCODE_CHK_NULL_RETURN(av1PicParams);
351
352 m_numTileRows = av1PicParams->tile_rows;
353 m_numTileColumns = av1PicParams->tile_cols;
354
355 uint32_t colBd[m_maxTileBdNum] = {0};
356 uint32_t rowBd[m_maxTileBdNum] = {0};
357 ENCODE_CHK_STATUS_RETURN(CalculateTilesBoundary(av1PicParams, &rowBd[0], &colBd[0]));
358
359 m_numTiles = m_numTileRows * m_numTileColumns;
360 if (m_numTiles > CODECHAL_GET_WIDTH_IN_BLOCKS(m_basicFeature->m_frameWidth, av1SuperBlockWidth) *
361 CODECHAL_GET_HEIGHT_IN_BLOCKS(m_basicFeature->m_frameHeight, av1SuperBlockHeight))
362 {
363 return MOS_STATUS_INVALID_PARAMETER;
364 }
365
366 uint32_t streamInWidthinSb = MOS_ROUNDUP_DIVIDE((av1PicParams->frame_width_minus1 +1), av1SuperBlockWidth);
367 uint32_t bitstreamByteOffset = 0;
368 uint32_t saoRowstoreOffset = 0;
369 uint32_t cuLevelStreamoutOffset = 0;
370 uint32_t sseRowstoreOffset = 0;
371 uint32_t tileStartSbAddr = 0;
372 uint32_t cumulativeCUTileOffsetInBytes = 0;
373 uint32_t tileLCUStreamOutOffsetInBytes = 0;
374
375 ENCODE_CHK_STATUS_RETURN(CalculateNumLcuByTiles(av1PicParams));
376
377 for ( uint32_t i = 0; i < m_numTileRows; i++)
378 {
379 for (uint32_t j = 0; j < m_numTileColumns; j++)
380 {
381 uint32_t idx = i * m_numTileColumns + j;
382 uint32_t numLcuInTile = (av1PicParams->height_in_sbs_minus_1[i] + 1) *
383 (av1PicParams->width_in_sbs_minus_1[j] + 1);
384
385 m_tileData[idx].tileStartXInSb = colBd[j];
386 m_tileData[idx].tileStartYInSb = rowBd[i];
387
388 //m_tileData[idx].tileColumnStoreSelect = j % 2;
389 //m_tileData[idx].tileRowStoreSelect = i % 2;
390
391 ENCODE_CHK_STATUS_RETURN(CalculateTileWidthAndHeight(av1PicParams, i, j, &rowBd[0], &colBd[0]));
392
393 m_tileData[idx].numOfTilesInFrame = m_numTiles;
394 m_tileData[idx].numOfTileColumnsInFrame = m_numTileColumns;
395
396 m_tileData[idx].pakTileStatisticsOffset = 8 * idx;
397 m_tileData[idx].tileSizeStreamoutOffset = idx;
398 m_tileData[idx].vp9ProbabilityCounterStreamoutOffset = 0;
399
400 m_tileData[idx].cumulativeCUTileOffset = cumulativeCUTileOffsetInBytes / CODECHAL_CACHELINE_SIZE;
401 m_tileData[idx].tileLCUStreamOutOffset = tileLCUStreamOutOffsetInBytes / CODECHAL_CACHELINE_SIZE;
402 m_tileData[idx].cuLevelStreamoutOffset = cuLevelStreamoutOffset;
403 m_tileData[idx].sseRowstoreOffset = sseRowstoreOffset;
404 m_tileData[idx].bitstreamByteOffset = bitstreamByteOffset;
405 m_tileData[idx].saoRowstoreOffset = saoRowstoreOffset;
406
407 uint32_t tileHeightInSb = MOS_ROUNDUP_DIVIDE(((m_tileData[idx].tileHeightInMinCbMinus1 + 1) * av1MinBlockHeight), av1SuperBlockHeight);
408 uint32_t tileWidthInSb = MOS_ROUNDUP_DIVIDE(((m_tileData[idx].tileWidthInMinCbMinus1 + 1) * av1MinBlockWidth), av1SuperBlockWidth);
409
410 m_tileData[idx].tileEndXInSb = m_tileData[idx].tileStartXInSb + tileWidthInSb;
411 m_tileData[idx].tileEndYInSb = m_tileData[idx].tileStartYInSb + tileHeightInSb;
412
413 // StreamIn data is 4 CLs per LCU
414 m_tileData[idx].tileStreaminOffset = 4 * (m_tileData[idx].tileStartYInSb * streamInWidthinSb + m_tileData[idx].tileStartXInSb * tileHeightInSb);
415 m_tileData[idx].sliceSizeStreamoutOffset = tileStartSbAddr; // correct sliceSizeStreamoutOffset calculation
416
417 uint32_t numOfSbsInTile = tileWidthInSb * tileHeightInSb;
418 tileStartSbAddr += numOfSbsInTile;
419
420 // For Cumulative CU Count : 2 bytes per LCU
421 cumulativeCUTileOffsetInBytes += numOfSbsInTile * 2;
422 cumulativeCUTileOffsetInBytes = MOS_ALIGN_CEIL(cumulativeCUTileOffsetInBytes, CODECHAL_CACHELINE_SIZE);
423
424 // Max LCU/SB size is 64, Min CU size is 8
425 const uint32_t maxNumOfCUInLCU = (av1SuperBlockWidth / av1MinBlockWidth) * (av1SuperBlockHeight / av1MinBlockHeight);
426
427 // For PAKObject Surface, 1 DW for PAK OBJ DATA + 1 DW for SIDE BAND INFORMATION
428 tileLCUStreamOutOffsetInBytes += 2 * BYTES_PER_DWORD * numOfSbsInTile * (NUM_PAK_DWS_PER_LCU + maxNumOfCUInLCU * NUM_DWS_PER_CU);
429 // CL alignment at end of every tile
430 tileLCUStreamOutOffsetInBytes = MOS_ALIGN_CEIL(tileLCUStreamOutOffsetInBytes, CODECHAL_CACHELINE_SIZE);
431
432 cuLevelStreamoutOffset += (m_tileData[idx].tileWidthInMinCbMinus1 + 1) * (m_tileData[idx].tileHeightInMinCbMinus1 + 1) * 16 / CODECHAL_CACHELINE_SIZE;
433
434 sseRowstoreOffset += (((av1PicParams->width_in_sbs_minus_1[j] + 1) + 3) * ((Av1BasicFeature*)m_basicFeature)->m_sizeOfSseSrcPixelRowStoreBufferPerLcu) / CODECHAL_CACHELINE_SIZE;
435
436 uint64_t totalSizeTemp = (uint64_t)m_basicFeature->m_bitstreamSize * (uint64_t)numLcuInTile;
437 uint32_t bitStreamSizePerTile = (uint32_t)(totalSizeTemp / (uint64_t)m_numSbInPic) + ((totalSizeTemp % (uint64_t)m_numSbInPic) ? 1 : 0);
438 bitstreamByteOffset += MOS_ALIGN_CEIL(bitStreamSizePerTile, CODECHAL_CACHELINE_SIZE) / CODECHAL_CACHELINE_SIZE;
439 }
440
441 // same row store buffer for different tile rows.
442 saoRowstoreOffset = 0;
443 sseRowstoreOffset = 0;
444 }
445
446 return eStatus;
447 }
448
SetTileGroupReportParams()449 MOS_STATUS Av1EncodeTile::SetTileGroupReportParams()
450 {
451 ENCODE_FUNC_CALL();
452
453 for (uint32_t i = 0; i < m_numTileGroups; i++)
454 {
455 m_reportTileGroupParams[m_statisticsBufIndex][i].TileGroupStart = m_av1TileGroupParams[i].TileGroupStart;
456 m_reportTileGroupParams[m_statisticsBufIndex][i].TileGroupEnd = m_av1TileGroupParams[i].TileGroupEnd;
457 m_reportTileGroupParams[m_statisticsBufIndex][i].TileGroupNum = m_numTileGroups;
458
459 auto av1BasicFeature = dynamic_cast<Av1BasicFeature *>(m_basicFeature);
460 ENCODE_CHK_NULL_RETURN(av1BasicFeature);
461
462 m_reportTileGroupParams[m_statisticsBufIndex][i].FirstTileGroupByteOffset = av1BasicFeature->GetAppHdrSizeInBytes();
463 }
464
465 return MOS_STATUS_SUCCESS;
466 }
467
GetTileGroupReportParams(uint32_t idx,const Av1ReportTileGroupParams * & reportTileGroupParams)468 MOS_STATUS Av1EncodeTile::GetTileGroupReportParams(uint32_t idx, const Av1ReportTileGroupParams *&reportTileGroupParams)
469 {
470 ENCODE_FUNC_CALL();
471
472 if (idx >= EncodeBasicFeature::m_uncompressedSurfaceNum)
473 {
474 ENCODE_ASSERTMESSAGE("Index exceeds the max number, when try to get tile report data");
475 return MOS_STATUS_INVALID_PARAMETER;
476 }
477
478 reportTileGroupParams = m_reportTileGroupParams[idx];
479
480 return MOS_STATUS_SUCCESS;
481 }
482
ReadObuSize(const uint8_t * ObuOffset,uint32_t & size)483 MOS_STATUS Av1EncodeTile::ReadObuSize(const uint8_t *ObuOffset, uint32_t &size)
484 {
485 ENCODE_CHK_NULL_RETURN(ObuOffset);
486
487 uint32_t value = 0;
488 for (uint32_t i = 0; i < OBU_LEB128_SIZE; ++i)
489 {
490 const uint8_t cur_byte = static_cast<uint8_t>(ObuOffset[i]);
491 const uint8_t decoded_byte = cur_byte & LEB128_BYTE_MASK;
492 value |= ((uint64_t)decoded_byte) << (i * 7);
493 if ((cur_byte & ~LEB128_BYTE_MASK) == 0)
494 {
495 size = value;
496 break;
497 }
498 }
499 return MOS_STATUS_SUCCESS;
500 }
501
CeilLog2(uint16_t x)502 uint16_t Av1EncodeTile::CeilLog2(uint16_t x)
503 {
504 uint16_t k = 0;
505 while (x > ((uint16_t)(1 << k))) k++;
506 return k;
507 }
508
TileLog2(uint16_t blksize,uint16_t target)509 uint16_t Av1EncodeTile::TileLog2(uint16_t blksize, uint16_t target)
510 {
511 uint16_t k = 0;
512 while ((uint16_t)(blksize << k) < target) k++;
513 return k;
514 }
515
TileSizeCheck(const PCODEC_AV1_ENCODE_PICTURE_PARAMS & av1PicParam)516 MOS_STATUS Av1EncodeTile::TileSizeCheck(const PCODEC_AV1_ENCODE_PICTURE_PARAMS &av1PicParam)
517 {
518 uint32_t maxTileAreaSb = MOS_ROUNDUP_DIVIDE(av1MaxTileArea, av1SuperBlockWidth * av1SuperBlockHeight);
519 uint32_t sbCols = MOS_ROUNDUP_DIVIDE(av1PicParam->frame_width_minus1 + 1, av1SuperBlockWidth);
520 uint32_t sbRows = MOS_ROUNDUP_DIVIDE(av1PicParam->frame_height_minus1 + 1, av1SuperBlockHeight);
521
522 //Tile Width sum equals image width, no pixel leak
523 if (av1PicParam->width_in_sbs_minus_1[0] + 1 == 0)
524 {
525 return MOS_STATUS_INVALID_PARAMETER;
526 }
527 uint32_t curTileWidthSb = av1PicParam->width_in_sbs_minus_1[0] + 1;
528 uint32_t widestTileSb = av1PicParam->width_in_sbs_minus_1[0] + 1;
529 uint32_t tileWidthSbSum = 0;
530
531 if (m_basicFeature->m_dualEncEnable && m_numTileRows != 1)
532 {
533 ENCODE_ASSERTMESSAGE("dual encode cannot support multi rows submission yet.");
534 return MOS_STATUS_INVALID_PARAMETER;
535 }
536
537 for (uint8_t i = 0; i < m_numTileColumns; i++)
538 {
539 curTileWidthSb = av1PicParam->width_in_sbs_minus_1[i] + 1;
540 widestTileSb = MOS_MAX(widestTileSb, curTileWidthSb);
541 tileWidthSbSum += curTileWidthSb;
542 if (m_basicFeature->m_dualEncEnable && curTileWidthSb == 2)
543 {
544 m_firstDummyIdx = i;
545 }
546 }
547 if (tileWidthSbSum != sbCols)
548 {
549 return MOS_STATUS_INVALID_PARAMETER;
550 }
551
552 //Tile Height sum equals image height, no pixel leak
553 if (av1PicParam->height_in_sbs_minus_1[0] + 1 == 0)
554 {
555 return MOS_STATUS_INVALID_PARAMETER;
556 }
557 uint32_t curTileHeightSb = av1PicParam->height_in_sbs_minus_1[0] + 1;
558 uint32_t highestWidthSb = av1PicParam->height_in_sbs_minus_1[0] + 1;
559 uint32_t tileHeightSbSum = 0;
560
561 for (uint8_t i = 0; i < m_numTileRows; i++)
562 {
563 curTileHeightSb = av1PicParam->height_in_sbs_minus_1[i] + 1;
564 highestWidthSb = MOS_MAX(1, curTileHeightSb);
565 tileHeightSbSum += curTileHeightSb;
566 }
567 if (tileHeightSbSum != sbRows)
568 {
569 return MOS_STATUS_INVALID_PARAMETER;
570 }
571
572 // Max tile check
573
574 for (uint8_t i = 0; i < m_numTileRows; i++)
575 {
576 curTileHeightSb = av1PicParam->height_in_sbs_minus_1[i] + 1;
577 if ((widestTileSb * curTileHeightSb) > maxTileAreaSb)
578 {
579 return MOS_STATUS_INVALID_PARAMETER;
580 }
581 }
582
583 return MOS_STATUS_SUCCESS;
584 }
585
WriteObuHeader(Av1TileGroupHeaderInfo & buf,const PCODEC_AV1_ENCODE_PICTURE_PARAMS & av1PicParam)586 void Av1EncodeTile::WriteObuHeader(Av1TileGroupHeaderInfo &buf, const PCODEC_AV1_ENCODE_PICTURE_PARAMS &av1PicParam)
587 {
588 if (av1PicParam == nullptr)
589 {
590 return;
591 }
592
593 auto ObuExtensionFlag = av1PicParam->TileGroupOBUHdrInfo.fields.obu_extension_flag;
594 auto ObuHasSizeField = av1PicParam->TileGroupOBUHdrInfo.fields.obu_has_size_field;
595 WriteBit(buf, 0); //forbidden bit
596 WriteLiteral(buf, 4, 4); //type
597 WriteBit(buf, ObuExtensionFlag); //obu_extension
598 WriteBit(buf, ObuHasSizeField); //obu_has_size_field
599 WriteBit(buf, 0); //reserved
600
601 //If obu_extension == 1, write OBU extension header
602 if (ObuExtensionFlag)
603 {
604 uint8_t temporalId = av1PicParam->TileGroupOBUHdrInfo.fields.temporal_id;
605 uint8_t spatialId = av1PicParam->TileGroupOBUHdrInfo.fields.spatial_id;
606 WriteLiteral(buf, temporalId, 3); //temporal_id
607 WriteLiteral(buf, spatialId, 2); //spatial_id
608 WriteLiteral(buf, 0, 3); //reserved
609 }
610 }
611
612 // in_value - [in] integer value to encoded as leb128
613 // out_encoded_value - [out] encoded data to be added to a bitstream
614 // fixed_output_len - [optional in] fixed len for the output, WA for driver part (value = len, 0 - not used)
615 // return - encoded len
write_leb128(uint64_t in_value,uint64_t & out_encoded_value,const uint8_t fixed_output_len)616 uint8_t Av1EncodeTile::write_leb128(uint64_t in_value, uint64_t &out_encoded_value, const uint8_t fixed_output_len)
617 {
618 uint8_t *out_buf = reinterpret_cast<uint8_t *>(&out_encoded_value);
619 uint8_t out_bytes_count = 0;
620
621 if (!fixed_output_len)
622 {
623 // general encoding
624 do
625 {
626 out_buf[out_bytes_count] = in_value & 0x7fU;
627 if (in_value >>= 7)
628 {
629 out_buf[out_bytes_count] |= 0x80U;
630 }
631 out_bytes_count++;
632 } while (in_value);
633 }
634 else
635 {
636 // WA to get fixed len of output
637 uint8_t value_byte_count = 0;
638 do
639 {
640 out_buf[value_byte_count++] = in_value & 0x7fU;
641 in_value >>= 7;
642 } while (in_value);
643 for (int i = 0; i < fixed_output_len - 1; i++)
644 {
645 out_buf[i] |= 0x80U;
646 out_bytes_count++;
647 }
648 out_bytes_count++;
649 }
650
651 return out_bytes_count;
652 }
653
WriteBit(Av1TileGroupHeaderInfo & buf,uint8_t bit)654 void Av1EncodeTile::WriteBit(Av1TileGroupHeaderInfo &buf, uint8_t bit)
655 {
656 const uint16_t byteOffset = buf.bitOffset / 8;
657 const uint8_t bitsLeftInByte = 8 - 1 - buf.bitOffset % 8;
658 if (bitsLeftInByte == 8 - 1)
659 {
660 buf.pBuffer[byteOffset] = uint8_t(bit << bitsLeftInByte);
661 }
662 else
663 {
664 buf.pBuffer[byteOffset] &= ~(1 << bitsLeftInByte);
665 buf.pBuffer[byteOffset] |= bit << bitsLeftInByte;
666 }
667 buf.bitOffset = buf.bitOffset + 1;
668 }
669
WriteLiteral(Av1TileGroupHeaderInfo & buf,uint64_t data,uint64_t bits)670 void Av1EncodeTile::WriteLiteral(Av1TileGroupHeaderInfo &buf, uint64_t data, uint64_t bits)
671 {
672 for (int64_t bit = bits - 1; bit >= 0; bit--)
673 {
674 WriteBit(buf, (data >> bit) & 1);
675 }
676 }
677
PrepareTileGroupHeaderAv1(uint8_t * buffer,uint32_t index,const PCODEC_AV1_ENCODE_PICTURE_PARAMS & av1PicParam)678 uint16_t Av1EncodeTile::PrepareTileGroupHeaderAv1(uint8_t *buffer, uint32_t index, const PCODEC_AV1_ENCODE_PICTURE_PARAMS &av1PicParam)
679 {
680 Av1TileGroupHeaderInfo localBuf;
681 localBuf.pBuffer = buffer;
682 localBuf.bitOffset = 0;
683
684 if (av1PicParam == nullptr)
685 {
686 ENCODE_ASSERTMESSAGE("Invalid (NULL) Pointer!");
687 return 0;
688 }
689 bool isFrameObu = av1PicParam->PicFlags.fields.EnableFrameOBU;
690 // if frame OBU enabled, should skip the generic OBU syntax, including OBU header and OBU size.
691 if (!isFrameObu)
692 {
693 WriteObuHeader(localBuf, av1PicParam);
694
695 uint64_t encoded_bytes = 0;
696 // SAS demands to set fixed-len size (0) for TG OBU for back annotation
697 uint32_t encoded_len = write_leb128(0, encoded_bytes, 4);
698 for (uint8_t i = 0; i < encoded_len; i++)
699 {
700 const uint8_t* ptr = reinterpret_cast<uint8_t*>(&encoded_bytes);
701 WriteLiteral(localBuf, ptr[i], 8);
702 }
703 }
704
705 const uint32_t NumTiles = m_numTileRows * m_numTileColumns;
706 auto tmpTileGroupParams = m_av1TileGroupParams + index;
707 uint8_t tile_start_and_end_present_flag = m_numTileGroups == 1 ? 0 : 1;
708 uint32_t tg_start, tg_end, tempOffset = 0;
709
710 tempOffset = localBuf.bitOffset;
711
712 if (NumTiles > 1)
713 {
714 WriteBit(localBuf, tile_start_and_end_present_flag);
715 }
716 if (NumTiles == 1 || !tile_start_and_end_present_flag)
717 {
718 tg_start = 0;
719 tg_end = NumTiles - 1;
720 }
721 else
722 {
723 uint32_t tileBits = static_cast<uint8_t>(CeilLog2(m_numTileRows)) + static_cast<uint8_t>(CeilLog2(m_numTileColumns));
724 WriteLiteral(localBuf, tmpTileGroupParams->TileGroupStart, tileBits);
725 WriteLiteral(localBuf, tmpTileGroupParams->TileGroupEnd, tileBits);
726 }
727
728 //byte_alignment
729 while (localBuf.bitOffset & 7)
730 WriteBit(localBuf, 0); //zero_bit
731
732 // HW keeps filling bitstream from this point
733
734 // tile group OBU size should exclude general OBU syntext related size.
735 m_reportTileGroupParams[m_statisticsBufIndex][index].TileGroupOBUSizeInBytes = (localBuf.bitOffset - tempOffset)/8;
736
737 auto av1BasicFeature = dynamic_cast<Av1BasicFeature*>(m_basicFeature);
738 ENCODE_CHK_NULL_RETURN(av1BasicFeature);
739 av1BasicFeature->m_tileGroupHeaderSize = (localBuf.bitOffset + 7) / 8;
740
741 return av1BasicFeature->m_tileGroupHeaderSize;
742 }
743
MakeTileGroupHeaderAv1(void * params)744 MOS_STATUS Av1EncodeTile::MakeTileGroupHeaderAv1(void *params)
745 {
746 ENCODE_CHK_NULL_RETURN(params);
747
748 EncoderParams *encodeParams = (EncoderParams *)params;
749 ENCODE_CHK_NULL_RETURN(encodeParams);
750
751 auto av1PicParam = static_cast<PCODEC_AV1_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
752 ENCODE_CHK_NULL_RETURN(av1PicParam);
753
754 uint32_t slcCount = 0;
755 BSBuffer *pBSBuffer;
756 uint32_t hdrDataOffset, hdrDataSize, hdrBufSize, hdrDataByteSize;
757
758 uint8_t *temp = new uint8_t[256];
759
760 for (uint32_t i = 0; i < m_numTileGroups; i++)
761 {
762 uint16_t bytesWrittenTgHeader = PrepareTileGroupHeaderAv1(temp, i, av1PicParam);
763 hdrDataSize = hdrBufSize = bytesWrittenTgHeader * 8; // In bits
764 hdrDataByteSize = (hdrDataSize + 7) >> 3; // In bytes
765 hdrDataOffset = 0;
766
767 if (hdrDataOffset >= hdrBufSize)
768 {
769 ENCODE_ASSERTMESSAGE("Encode: Data offset in packed slice header data is out of bounds.");
770 delete []temp;
771 return MOS_STATUS_INVALID_FILE_SIZE;
772 }
773
774 if (hdrDataByteSize > hdrBufSize)
775 {
776 ENCODE_ASSERTMESSAGE("Encode: Data length in packed slice header data is greater than buffer size.");
777 delete []temp;
778 return MOS_STATUS_INVALID_FILE_SIZE;
779 }
780
781 PCODEC_ENCODER_SLCDATA pSlcData = m_basicFeature->m_slcData;
782 pBSBuffer = &m_basicFeature->m_bsBuffer;
783 pSlcData[slcCount].SliceOffset = (uint32_t)(pBSBuffer->pCurrent - pBSBuffer->pBase);
784 pSlcData[slcCount].BitSize = hdrDataSize;
785 slcCount++;
786
787 if (slcCount > encodeParams->dwNumSlices)
788 {
789 ENCODE_ASSERTMESSAGE("Encode: Number of slice headers exceeds number of slices.");
790 delete []temp;
791 return MOS_STATUS_INVALID_FILE_SIZE;
792 }
793
794 MOS_SecureMemcpy(pBSBuffer->pCurrent,
795 hdrDataByteSize,
796 (temp + hdrDataOffset),
797 hdrDataByteSize);
798
799 pBSBuffer->pCurrent += hdrDataByteSize;
800 }
801 delete []temp;
802 return MOS_STATUS_SUCCESS;
803 }
804
GetTileStatsOffset(uint32_t & offset)805 MOS_STATUS Av1EncodeTile::GetTileStatsOffset(uint32_t &offset)
806 {
807 offset = m_av1TileStatsOffset.uiVdencStatistics;
808
809 return MOS_STATUS_SUCCESS;
810 }
811
GetTileInfo(Av1TileInfo * av1TileInfo) const812 MOS_STATUS Av1EncodeTile::GetTileInfo(Av1TileInfo *av1TileInfo) const
813 {
814 ENCODE_CHK_NULL_RETURN(av1TileInfo);
815
816 av1TileInfo->tileId = static_cast<uint16_t>(m_tileIdx); // Tile number in a frame
817
818 const auto currTileData = m_tileData[m_tileIdx];
819
820 av1TileInfo->tileColPositionInSb = static_cast<uint16_t>(currTileData.tileStartXInSb);
821 av1TileInfo->tileRowPositionInSb = static_cast<uint16_t>(currTileData.tileStartYInSb);
822
823 av1TileInfo->tileWidthInSbMinus1 = currTileData.tileEndXInSb - currTileData.tileStartXInSb - 1;
824 av1TileInfo->tileHeightInSbMinus1 = currTileData.tileEndYInSb - currTileData.tileStartYInSb - 1;
825
826 av1TileInfo->firstTileInAFrame = (0 == m_tileIdx);
827 av1TileInfo->lastTileOfColumn = currTileData.isLastTileofColumn;
828 av1TileInfo->lastTileOfRow = currTileData.isLastTileofRow;
829 av1TileInfo->lastTileOfFrame = (m_tileIdx == currTileData.numOfTilesInFrame - 1) ? true : false;
830
831 av1TileInfo->tileStartXInLCU = currTileData.tileStartXInLCU;
832 av1TileInfo->tileStartYInLCU = currTileData.tileStartYInLCU;
833 av1TileInfo->tileEndXInLCU = currTileData.tileEndXInLCU;
834 av1TileInfo->tileEndYInLCU = currTileData.tileEndYInLCU;
835
836 auto tmpTileGroupParams = m_av1TileGroupParams;
837 for (uint16_t tileGrupCnt = 0; tileGrupCnt < m_numTileGroups; tileGrupCnt++)
838 {
839 if (tmpTileGroupParams->TileGroupStart <= m_tileIdx &&
840 tmpTileGroupParams->TileGroupEnd >= m_tileIdx)
841 {
842 av1TileInfo->firstTileOfTileGroup = (tmpTileGroupParams->TileGroupStart == m_tileIdx);
843 av1TileInfo->lastTileOfTileGroup = (tmpTileGroupParams->TileGroupEnd == m_tileIdx);
844 av1TileInfo->tgTileNum = m_tileIdx - tmpTileGroupParams->TileGroupStart;
845 av1TileInfo->tileGroupId = tileGrupCnt;
846 break;
847 }
848 tmpTileGroupParams++;
849 }
850
851 return MOS_STATUS_SUCCESS;
852 }
853
MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,Av1EncodeTile)854 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, Av1EncodeTile)
855 {
856 if (!m_enabled)
857 {
858 return MOS_STATUS_SUCCESS;
859 }
860
861 MOS_RESOURCE* tileStatisticsBuffer = const_cast<MOS_RESOURCE*>(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]);
862 if (!Mos_ResourceIsNull(tileStatisticsBuffer))
863 {
864 params.streamOutBuffer = tileStatisticsBuffer;
865 params.streamOutOffset = m_av1TileStatsOffset.uiVdencStatistics;
866 }
867
868 return MOS_STATUS_SUCCESS;
869 }
870
MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE,Av1EncodeTile)871 MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE, Av1EncodeTile)
872 {
873 params.tileSliceStartLcuMbX = m_tileData[m_tileIdx].tileStartXInLCU;
874 params.tileSliceStartLcuMbY = m_tileData[m_tileIdx].tileStartYInLCU;
875 params.nextTileSliceStartLcuMbX = m_tileData[m_tileIdx].tileEndXInLCU;
876 params.nextTileSliceStartLcuMbY = m_tileData[m_tileIdx].tileEndYInLCU;
877
878 return MOS_STATUS_SUCCESS;
879 }
880
MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE,Av1EncodeTile)881 MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE, Av1EncodeTile)
882 {
883 params.tileEnable = true;
884 params.tileId = m_tileIdx;
885 params.ctbSize = av1SuperBlockWidth;
886 params.tileRowStoreSelect = m_curTileCodingParams.TileRowStoreSelect;
887 params.tileWidth = (m_curTileCodingParams.TileWidthInMinCbMinus1 + 1) * av1MinBlockWidth;
888 params.tileHeight = (m_curTileCodingParams.TileHeightInMinCbMinus1 + 1) * av1MinBlockWidth;
889 params.tileStartLCUX = m_curTileCodingParams.TileStartLCUX;
890 params.tileStartLCUY = m_curTileCodingParams.TileStartLCUY;
891 params.tileStreamInOffset = m_curTileCodingParams.TileStreaminOffset;
892 params.tileLCUStreamOutOffset = m_curTileCodingParams.TileLCUStreamOutOffset;
893 params.VdencHEVCVP9TileSlicePar18 = true;
894 params.VdencHEVCVP9TileSlicePar19 = m_curTileCodingParams.CumulativeCUTileOffset;
895 params.tileRowstoreOffset = 0;
896
897 return MOS_STATUS_SUCCESS;
898 }
899
MHW_SETPAR_DECL_SRC(AVP_PIC_STATE,Av1EncodeTile)900 MHW_SETPAR_DECL_SRC(AVP_PIC_STATE, Av1EncodeTile)
901 {
902 bool firstTileInGroup = false;
903 uint32_t tileGroupIdx = 0;
904
905 IsFirstTileInGroup(firstTileInGroup, tileGroupIdx);
906
907 params.headerPresent = firstTileInGroup;
908
909 return MOS_STATUS_SUCCESS;
910 }
911
MHW_SETPAR_DECL_SRC(AVP_PIPE_MODE_SELECT,Av1EncodeTile)912 MHW_SETPAR_DECL_SRC(AVP_PIPE_MODE_SELECT, Av1EncodeTile)
913 {
914 params.tileBasedReplayMode = false;
915
916 return MOS_STATUS_SUCCESS;
917 }
918
MHW_SETPAR_DECL_SRC(AVP_TILE_CODING,Av1EncodeTile)919 MHW_SETPAR_DECL_SRC(AVP_TILE_CODING, Av1EncodeTile)
920 {
921 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
922
923 Av1TileInfo av1TileInfo;
924 eStatus = GetTileInfo(&av1TileInfo);
925 params.tileId = av1TileInfo.tileId;
926 params.tileColPositionInSb = av1TileInfo.tileColPositionInSb;
927 params.tileRowPositionInSb = av1TileInfo.tileRowPositionInSb;
928 params.tileWidthInSbMinus1 = av1TileInfo.tileWidthInSbMinus1;
929 params.tileHeightInSbMinus1 = av1TileInfo.tileHeightInSbMinus1;
930 params.firstTileInAFrame = av1TileInfo.firstTileInAFrame;
931 params.lastTileOfColumn = av1TileInfo.lastTileOfColumn;
932 params.lastTileOfRow = av1TileInfo.lastTileOfRow;
933 params.lastTileOfFrame = av1TileInfo.lastTileOfFrame;
934 params.firstTileOfTileGroup = av1TileInfo.firstTileOfTileGroup;
935 params.lastTileOfTileGroup = av1TileInfo.lastTileOfTileGroup;
936 params.tgTileNum = av1TileInfo.tgTileNum;
937 params.tileGroupId = av1TileInfo.tileGroupId;
938
939 return eStatus;
940 }
941
MHW_SETPAR_DECL_SRC(AVP_IND_OBJ_BASE_ADDR_STATE,Av1EncodeTile)942 MHW_SETPAR_DECL_SRC(AVP_IND_OBJ_BASE_ADDR_STATE, Av1EncodeTile)
943 {
944 auto basicFeature = dynamic_cast<Av1BasicFeature *>(m_basicFeature);
945 ENCODE_CHK_NULL_RETURN(basicFeature);
946
947 if (basicFeature->m_enableSWStitching || basicFeature->m_dualEncEnable)
948 {
949 params.pakBaseObjectOffset = MOS_ALIGN_CEIL(m_tileData[m_tileIdx].bitstreamByteOffset * CODECHAL_CACHELINE_SIZE, MOS_PAGE_SIZE);
950 }
951
952 return MOS_STATUS_SUCCESS;
953 }
954
MHW_SETPAR_DECL_SRC(AVP_PAK_INSERT_OBJECT,Av1EncodeTile)955 MHW_SETPAR_DECL_SRC(AVP_PAK_INSERT_OBJECT, Av1EncodeTile)
956 {
957 bool firstTileInGroup = false;
958 uint32_t tileGroupIdx = 0;
959
960 IsFirstTileInGroup(firstTileInGroup, tileGroupIdx);
961
962 if (firstTileInGroup)
963 {
964 params.bsBuffer = &m_basicFeature->m_bsBuffer;
965 params.bitSize = m_basicFeature->m_slcData[tileGroupIdx].BitSize;
966 params.offset = m_basicFeature->m_slcData[tileGroupIdx].SliceOffset;
967 params.endOfHeaderInsertion = false;
968 params.lastHeader = true;
969 }
970
971 return MOS_STATUS_SUCCESS;
972 }
973
MHW_SETPAR_DECL_SRC(AVP_PIPE_BUF_ADDR_STATE,Av1EncodeTile)974 MHW_SETPAR_DECL_SRC(AVP_PIPE_BUF_ADDR_STATE, Av1EncodeTile)
975 {
976 params.tileSizeStreamoutBuffer = const_cast<PMOS_RESOURCE>(&m_tileRecordBuffer[m_statisticsBufIndex]);
977 params.tileSizeStreamoutBufferOffset = m_tileIdx * CODECHAL_CACHELINE_SIZE;
978
979 return MOS_STATUS_SUCCESS;
980 }
981
MHW_SETPAR_DECL_SRC(VDENC_CMD2,Av1EncodeTile)982 MHW_SETPAR_DECL_SRC(VDENC_CMD2, Av1EncodeTile)
983 {
984 ENCODE_FUNC_CALL();
985 auto av1BasicFeature = dynamic_cast<Av1BasicFeature *>(m_basicFeature);
986 ENCODE_CHK_NULL_RETURN(av1BasicFeature);
987 auto av1Picparams = av1BasicFeature->m_av1PicParams;
988 ENCODE_CHK_NULL_RETURN(av1Picparams);
989 auto av1Seqparams = av1BasicFeature->m_av1SeqParams;
990 ENCODE_CHK_NULL_RETURN(av1Seqparams);
991
992 // for BRC, adaptive rounding is done in HuC, so we can skip it here.
993 if (av1BasicFeature->m_roundingMethod == RoundingMethod::adaptiveRounding && !IsRateControlBrc(av1Seqparams->RateControlMethod))
994 {
995 uint32_t frameSizeIn8x8Units1 = ((av1BasicFeature->m_oriFrameWidth + 63) >> 6) * ((av1BasicFeature->m_oriFrameHeight + 63) >> 6);
996 uint32_t frameSizeIn8x8Units2 = ((av1BasicFeature->m_oriFrameWidth + 7) >> 3) * ((av1BasicFeature->m_oriFrameHeight + 7) >> 3);
997 av1BasicFeature->m_par65Inter = 2;
998
999 if (av1BasicFeature->m_encodedFrameNum > 0)
1000 {
1001 MOS_RESOURCE* buf = nullptr;
1002
1003 ENCODE_CHK_STATUS_RETURN(GetTileBasedStatisticsBuffer(m_prevStatisticsBufIndex, buf));
1004 ENCODE_CHK_NULL_RETURN(buf);
1005
1006 //will be optimized to avoid perf degradation when async > 1
1007 const auto* bufData = (VdencStatistics*)((uint8_t*)m_allocator->LockResourceForRead(buf) + m_av1TileStatsOffset.uiVdencStatistics);
1008 ENCODE_CHK_NULL_RETURN(bufData);
1009
1010 uint32_t newFCost1 = bufData->DW1.IntraCuCountNormalized / frameSizeIn8x8Units1;
1011
1012 m_allocator->UnLock(buf);
1013
1014 if (newFCost1 >= 2)
1015 {
1016 av1BasicFeature->m_par65Inter = 3;
1017 }
1018 else if (newFCost1 == 0)
1019 {
1020 av1BasicFeature->m_par65Inter = 1;
1021 }
1022 }
1023
1024 av1BasicFeature->m_par65Intra = 7;
1025
1026 if (av1Picparams->base_qindex <= 100 || frameSizeIn8x8Units2 < 5000)
1027 {
1028 av1BasicFeature->m_par65Intra = 6;
1029 }
1030
1031 if (av1Picparams->PicFlags.fields.frame_type != keyFrame)
1032 {
1033 av1BasicFeature->m_par65Intra = 5;
1034 }
1035 }
1036 else if (av1BasicFeature->m_roundingMethod == RoundingMethod::fixedRounding)
1037 {
1038 av1BasicFeature->m_par65Inter = 2;
1039 av1BasicFeature->m_par65Intra = 6;
1040 }
1041
1042 if (av1BasicFeature->m_roundingMethod == RoundingMethod::adaptiveRounding
1043 || av1BasicFeature->m_roundingMethod == RoundingMethod::fixedRounding)
1044 {
1045 #if _MEDIA_RESERVED
1046 for (auto i = 0; i < 3; i++)
1047 {
1048 params.vdencCmd2Par65[i][0][0] = av1BasicFeature->m_par65Intra;
1049 params.vdencCmd2Par65[i][0][1] = av1BasicFeature->m_par65Intra;
1050 params.vdencCmd2Par65[i][1][0] = av1BasicFeature->m_par65Inter;
1051 params.vdencCmd2Par65[i][1][1] = av1BasicFeature->m_par65Inter;
1052 params.vdencCmd2Par65[i][2][0] = av1BasicFeature->m_par65Inter;
1053 params.vdencCmd2Par65[i][2][1] = av1BasicFeature->m_par65Inter;
1054 }
1055 #else
1056 params.extSettings.emplace_back(
1057 [av1BasicFeature](uint32_t *data) {
1058 uint8_t tmp0 = av1BasicFeature->m_par65Intra & 0xf;
1059 uint8_t tmp1 = av1BasicFeature->m_par65Inter & 0xf;
1060
1061 data[32] |= (tmp1 << 16);
1062 data[32] |= (tmp1 << 20);
1063 data[32] |= (tmp0 << 24);
1064 data[32] |= (tmp0 << 28);
1065
1066 data[33] |= tmp1;
1067 data[33] |= (tmp1 << 4);
1068 data[33] |= (tmp1 << 8);
1069 data[33] |= (tmp1 << 12);
1070 data[33] |= (tmp0 << 16);
1071 data[33] |= (tmp0 << 20);
1072 data[33] |= (tmp1 << 24);
1073 data[33] |= (tmp1 << 28);
1074
1075 data[34] |= tmp1;
1076 data[34] |= (tmp1 << 4);
1077 data[34] |= (tmp0 << 8);
1078 data[34] |= (tmp0 << 12);
1079 data[34] |= (tmp1 << 16);
1080 data[34] |= (tmp1 << 20);
1081
1082 return MOS_STATUS_SUCCESS;
1083 });
1084 #endif // _MEDIA_RESERVED
1085 }
1086
1087
1088 return MOS_STATUS_SUCCESS;
1089 }
1090
GetTileStatusInfo(Av1TileStatusInfo & av1TileStatsOffset,Av1TileStatusInfo & av1StatsSize)1091 MOS_STATUS Av1EncodeTile::GetTileStatusInfo(
1092 Av1TileStatusInfo &av1TileStatsOffset,
1093 Av1TileStatusInfo &av1StatsSize)
1094 {
1095 av1TileStatsOffset = m_av1TileStatsOffset;
1096 av1StatsSize = m_av1StatsSize;
1097
1098 return MOS_STATUS_SUCCESS;
1099 }
1100
1101 } // namespace encode
1102