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