1 /*
2 * Copyright (c) 2019-2020, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     encode_hevc_tile.cpp
24 //! \brief    Defines the common interface for hevc tile
25 //!
26 
27 #include "encode_hevc_tile.h"
28 #include "encode_hevc_basic_feature.h"
29 #include "codec_def_common.h"
30 #include "encode_hevc_vdenc_feature_manager.h"
31 #include "encode_pipeline.h"
32 
33 namespace encode
34 {
HevcEncodeTile(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)35     HevcEncodeTile::HevcEncodeTile(
36         MediaFeatureManager *featureManager,
37         EncodeAllocator *allocator,
38         CodechalHwInterfaceNext *hwInterface,
39         void *constSettings) :
40         EncodeTile(featureManager, allocator, hwInterface, constSettings)
41     {
42         ENCODE_CHK_NULL_NO_STATUS_RETURN(hwInterface);
43         m_mosCtx = hwInterface->GetOsInterface()->pOsContext;
44 
45         auto encFeatureManager = dynamic_cast<EncodeHevcVdencFeatureManager *>(featureManager);
46         ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
47 
48         m_basicFeature = dynamic_cast<EncodeBasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
49         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
50 
51         m_hcpItf = std::static_pointer_cast<mhw::vdbox::hcp::Itf>(hwInterface->GetHcpInterfaceNext());
52         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hcpItf);
53     }
54 
Init(void * settings)55     MOS_STATUS HevcEncodeTile::Init(void* settings)
56     {
57         ENCODE_FUNC_CALL();
58         ENCODE_CHK_NULL_RETURN(settings);
59 
60         ENCODE_CHK_STATUS_RETURN(EncodeTile::Init(settings));
61 
62 #if (_DEBUG || _RELEASE_INTERNAL)
63         // Tile Replay Enable should be passed from DDI, will change later when DDI is ready
64         MediaUserSetting::Value outValue;
65         ReadUserSetting(
66             m_userSettingPtr,
67             outValue,
68             "HEVC VDEnc TileReplay Enable",
69             MediaUserSetting::Group::Sequence);
70         m_enableTileReplay = outValue.Get<bool>();
71 #else
72         m_enableTileReplay = false;
73 #endif
74 
75         return MOS_STATUS_SUCCESS;
76     }
77 
Update(void * params)78     MOS_STATUS HevcEncodeTile::Update(void *params)
79     {
80         ENCODE_FUNC_CALL();
81         ENCODE_CHK_NULL_RETURN(params);
82 
83         EncoderParams* encodeParams = (EncoderParams*)params;;
84         ENCODE_CHK_NULL_RETURN(encodeParams);
85 
86         PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams =
87         static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
88         ENCODE_CHK_NULL_RETURN(hevcPicParams);
89 
90         m_enabled = hevcPicParams->tiles_enabled_flag ? true : false;
91 
92 
93         m_maxTileNumber = CODECHAL_GET_WIDTH_IN_BLOCKS(m_basicFeature->m_frameWidth, CODECHAL_HEVC_MIN_TILE_SIZE) *
94                              CODECHAL_GET_HEIGHT_IN_BLOCKS(m_basicFeature->m_frameHeight, CODECHAL_HEVC_MIN_TILE_SIZE);
95 
96         ENCODE_CHK_STATUS_RETURN(EncodeTile::Update(params));
97 
98         return MOS_STATUS_SUCCESS;
99     }
100 
IsLcuInTile(uint32_t lcuX,uint32_t lcuY,EncodeTileData * currentTile)101     bool HevcEncodeTile::IsLcuInTile(
102         uint32_t        lcuX,
103         uint32_t        lcuY,
104         EncodeTileData *currentTile)
105     {
106         ENCODE_FUNC_CALL();
107 
108         if (m_basicFeature == nullptr)
109         {
110             ENCODE_ASSERTMESSAGE("Null basic feature, unexpected!");
111             return false;
112         }
113         auto hevcBasicFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
114         if (hevcBasicFeature == nullptr)
115         {
116             ENCODE_ASSERTMESSAGE("Null hevc basic feature, unexpected!");
117             return false;
118         }
119         auto hevcSeqParams = hevcBasicFeature->m_hevcSeqParams;
120         if (hevcSeqParams == nullptr)
121         {
122             ENCODE_ASSERTMESSAGE("Null seq parameters, unexpected!");
123             return false;
124         }
125 
126         uint32_t shift           = hevcSeqParams->log2_max_coding_block_size_minus3 - hevcSeqParams->log2_min_coding_block_size_minus3;
127         uint32_t residual        = (1 << shift) - 1;
128         uint32_t tileColumnWidth = (currentTile->tileWidthInMinCbMinus1 + 1 + residual) >> shift;
129         uint32_t tileRowHeight   = (currentTile->tileHeightInMinCbMinus1 + 1 + residual) >> shift;
130 
131         return (lcuX < currentTile->tileStartXInLCU ||
132                 lcuY < currentTile->tileStartYInLCU ||
133                 lcuX >= currentTile->tileStartXInLCU + tileColumnWidth ||
134                 lcuY >= currentTile->tileStartYInLCU + tileRowHeight);
135     }
136 
IsSliceInTile(uint32_t sliceNumber,EncodeTileData * currentTile,bool * sliceInTile,bool * lastSliceInTile)137     MOS_STATUS HevcEncodeTile::IsSliceInTile(
138         uint32_t       sliceNumber,
139         EncodeTileData *currentTile,
140         bool *         sliceInTile,
141         bool *         lastSliceInTile)
142     {
143         ENCODE_FUNC_CALL();
144         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
145 
146         ENCODE_CHK_NULL_RETURN(currentTile);
147         ENCODE_CHK_NULL_RETURN(sliceInTile);
148         ENCODE_CHK_NULL_RETURN(lastSliceInTile);
149         ENCODE_CHK_NULL_RETURN(m_basicFeature);
150         auto tmpHevcBasicFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
151         ENCODE_CHK_NULL_RETURN(tmpHevcBasicFeature);
152 
153         auto hevcPicParams   = tmpHevcBasicFeature->m_hevcPicParams;
154         auto hevcSeqParams   = tmpHevcBasicFeature->m_hevcSeqParams;
155         auto hevcSliceParams = tmpHevcBasicFeature->m_hevcSliceParams;
156         ENCODE_CHK_NULL_RETURN(hevcPicParams);
157         ENCODE_CHK_NULL_RETURN(hevcSeqParams);
158         ENCODE_CHK_NULL_RETURN(hevcSliceParams);
159 
160         if (!m_enabled)
161         {
162             *lastSliceInTile = *sliceInTile = true;
163             return eStatus;
164         }
165 
166         uint32_t shift            = hevcSeqParams->log2_max_coding_block_size_minus3 - hevcSeqParams->log2_min_coding_block_size_minus3;
167         uint32_t residual         = (1 << shift) - 1;
168         uint32_t frameWidthInLCU  = (hevcSeqParams->wFrameWidthInMinCbMinus1 + 1 + residual) >> shift;
169         uint32_t frameHeightInLCU = (hevcSeqParams->wFrameHeightInMinCbMinus1 + 1 + residual) >> shift;
170 
171         uint32_t tileColumnWidth = (currentTile->tileWidthInMinCbMinus1 + 1 + residual) >> shift;
172         uint32_t tileRowHeight   = (currentTile->tileHeightInMinCbMinus1 + 1 + residual) >> shift;
173 
174         const CODEC_HEVC_ENCODE_SLICE_PARAMS *hevcSlcParams = &hevcSliceParams[sliceNumber];
175         uint32_t                              sliceStartLCU = hevcSlcParams->slice_segment_address;
176         uint32_t                              sliceLCUx     = sliceStartLCU % frameWidthInLCU;
177         uint32_t                              sliceLCUy     = sliceStartLCU / frameWidthInLCU;
178 
179         if (IsLcuInTile(sliceLCUx, sliceLCUy, currentTile))
180         {
181             // slice start is not in the tile boundary
182             *lastSliceInTile = *sliceInTile = false;
183             return eStatus;
184         }
185 
186         sliceLCUx += (hevcSlcParams->NumLCUsInSlice - 1) % tileColumnWidth;
187         sliceLCUy += (hevcSlcParams->NumLCUsInSlice - 1) / tileColumnWidth;
188 
189         if (sliceLCUx >= currentTile->tileStartXInLCU + tileColumnWidth)
190         {
191             sliceLCUx -= tileColumnWidth;
192             sliceLCUy++;
193         }
194 
195         if (IsLcuInTile(sliceLCUx, sliceLCUy, currentTile))
196         {
197             // last LCU of the slice is out of the tile boundary
198             *lastSliceInTile = *sliceInTile = false;
199             return eStatus;
200         }
201 
202         *sliceInTile = true;
203 
204         sliceLCUx++;
205         sliceLCUy++;
206 
207         // the end of slice is at the boundary of tile
208         *lastSliceInTile = (sliceLCUx == currentTile->tileStartXInLCU + tileColumnWidth &&
209                             sliceLCUy == currentTile->tileStartYInLCU + tileRowHeight);
210 
211         return eStatus;
212     }
213 
SetPipeNumber(uint32_t numPipes)214     MOS_STATUS HevcEncodeTile::SetPipeNumber(uint32_t numPipes)
215     {
216         ENCODE_FUNC_CALL();
217 
218         m_curTileCodingParams.NumberOfActiveBePipes = numPipes;
219 
220         return MOS_STATUS_SUCCESS;
221     }
222 
SetCurrentTileFromSliceIndex(uint32_t slcCount,EncodePipeline * pipeline)223     MOS_STATUS HevcEncodeTile::SetCurrentTileFromSliceIndex(
224         uint32_t        slcCount,
225         EncodePipeline *pipeline)
226     {
227         ENCODE_FUNC_CALL();
228 
229         bool lastSliceInTile = false, sliceInTile = false;
230 
231         EncodeTileData curTileData = {};
232 
233         // Find the tileData corresponding to this slice
234         for (uint32_t tileRow = 0; tileRow < m_numTileRows; tileRow++)
235         {
236             for (uint32_t tileCol = 0; tileCol < m_numTileColumns; tileCol++)
237             {
238                 ENCODE_CHK_STATUS_RETURN(SetCurrentTile(tileRow, tileCol, pipeline));
239                 ENCODE_CHK_STATUS_RETURN(GetCurrentTile(curTileData));
240                 ENCODE_CHK_STATUS_RETURN(IsSliceInTile(slcCount, &curTileData, &sliceInTile, &lastSliceInTile));
241 
242                 if (sliceInTile)
243                 {
244                     break;
245                 }
246             }
247             if (sliceInTile)
248             {
249                 break;
250             }
251         }
252 
253         return MOS_STATUS_SUCCESS;
254     }
255 
CalculateNumLcuByTiles(PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)256     MOS_STATUS HevcEncodeTile::CalculateNumLcuByTiles(PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams)
257     {
258         ENCODE_FUNC_CALL();
259 
260         ENCODE_CHK_NULL_RETURN(hevcPicParams);
261 
262         m_numLcuInPic = 0;
263         for (uint32_t numLcusInTiles = 0, i = 0; i < m_numTileRows; i++)
264         {
265             for (uint32_t j = 0; j < m_numTileColumns; j++)
266             {
267                 m_numLcuInPic += hevcPicParams->tile_row_height[i] * hevcPicParams->tile_column_width[j];
268             }
269         }
270         if (m_numLcuInPic == 0)
271         {
272             ENCODE_ASSERTMESSAGE("LCU num cal by each tile is zero, sth must be wrong!");
273             return MOS_STATUS_INVALID_PARAMETER;
274         }
275         return MOS_STATUS_SUCCESS;
276     }
277 
CalculateTilesBoundary(PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,uint32_t * rowBd,uint32_t * colBd)278     MOS_STATUS HevcEncodeTile::CalculateTilesBoundary(
279         PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,
280         uint32_t *rowBd,
281         uint32_t *colBd)
282     {
283         ENCODE_FUNC_CALL();
284 
285         ENCODE_CHK_NULL_RETURN(hevcPicParams);
286         ENCODE_CHK_NULL_RETURN(rowBd);
287         ENCODE_CHK_NULL_RETURN(colBd);
288 
289         for (uint32_t i = 0; i < m_numTileColumns; i++)
290         {
291             colBd[i + 1] = colBd[i] + hevcPicParams->tile_column_width[i];
292         }
293 
294         for (uint32_t i = 0; i < m_numTileRows; i++)
295         {
296             rowBd[i + 1] = rowBd[i] + hevcPicParams->tile_row_height[i];
297         }
298 
299         return MOS_STATUS_SUCCESS;
300 
301     }
302 
CalculateTileWidthAndHeight(PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,uint32_t rowIndex,uint32_t colIndex,uint32_t * rowBd,uint32_t * colBd)303     MOS_STATUS HevcEncodeTile::CalculateTileWidthAndHeight(
304         PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams,
305         PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams,
306         uint32_t  rowIndex,
307         uint32_t  colIndex,
308         uint32_t *rowBd,
309         uint32_t *colBd)
310     {
311         ENCODE_FUNC_CALL();
312 
313         ENCODE_CHK_NULL_RETURN(hevcPicParams);
314         ENCODE_CHK_NULL_RETURN(hevcSeqParams);
315         ENCODE_CHK_NULL_RETURN(rowBd);
316         ENCODE_CHK_NULL_RETURN(colBd);
317 
318         uint32_t idx                = rowIndex * m_numTileColumns + colIndex;
319         int32_t  frameWidthInMinCb  = hevcSeqParams->wFrameWidthInMinCbMinus1 + 1;
320         int32_t  frameHeightInMinCb = hevcSeqParams->wFrameHeightInMinCbMinus1 + 1;
321         int32_t  shift              = hevcSeqParams->log2_max_coding_block_size_minus3 - hevcSeqParams->log2_min_coding_block_size_minus3;
322 
323         if (colIndex != m_numTileColumns - 1)
324         {
325             m_tileData[idx].tileWidthInMinCbMinus1 = (hevcPicParams->tile_column_width[colIndex] << shift) - 1;
326             m_tileData[idx].isLastTileofRow        = false;
327         }
328         else
329         {
330             m_tileData[idx].tileWidthInMinCbMinus1 = (frameWidthInMinCb - (colBd[colIndex] << shift)) - 1;
331             m_tileData[idx].isLastTileofRow        = true;
332         }
333 
334         if (rowIndex != m_numTileRows - 1)
335         {
336             m_tileData[idx].isLastTileofColumn      = false;
337             m_tileData[idx].tileHeightInMinCbMinus1 = (hevcPicParams->tile_row_height[rowIndex] << shift) - 1;
338         }
339         else
340         {
341             m_tileData[idx].tileHeightInMinCbMinus1 = (frameHeightInMinCb - (rowBd[rowIndex] << shift)) - 1;
342             m_tileData[idx].isLastTileofColumn      = true;
343         }
344 
345         return MOS_STATUS_SUCCESS;
346     }
347 
GetTileInfo(uint32_t xPosition,uint32_t yPosition,uint32_t & tileStartLcuX,uint32_t & tileEndLcuX,uint32_t & tileStartLcuY,uint32_t & tileEndLcuY,uint32_t & tileStreaminOffset)348     MOS_STATUS HevcEncodeTile::GetTileInfo(
349         uint32_t xPosition,
350         uint32_t yPosition,
351         uint32_t &tileStartLcuX,
352         uint32_t &tileEndLcuX,
353         uint32_t &tileStartLcuY,
354         uint32_t &tileEndLcuY,
355         uint32_t &tileStreaminOffset)
356     {
357         MOS_STATUS eStatus = MOS_STATUS_INVALID_PARAMETER;
358 
359         for (uint32_t i = 0; i < m_numTiles; i++)
360         {
361             tileStartLcuX = m_tileData[i].tileStartXInLCU;
362             tileStartLcuY = m_tileData[i].tileStartYInLCU;
363             tileEndLcuX   = m_tileData[i].tileEndXInLCU;
364             tileEndLcuY   = m_tileData[i].tileEndYInLCU;
365 
366             tileStreaminOffset = m_tileData[i].tileStreaminOffset;
367 
368             if ((xPosition >= (tileStartLcuX * 2)) &&
369                 (yPosition >= (tileStartLcuY * 2)) &&
370                 (xPosition < (tileEndLcuX * 2)) &&
371                 (yPosition < (tileEndLcuY * 2)))
372             {
373                 eStatus = MOS_STATUS_SUCCESS;
374                 break;
375             }
376         }
377 
378         return eStatus;
379     }
380 
SetTileData(void * params)381     MOS_STATUS HevcEncodeTile::SetTileData(void *params)
382     {
383         ENCODE_FUNC_CALL();
384 
385         MOS_STATUS eStatus       = MOS_STATUS_SUCCESS;
386 
387         if (!m_enabled)
388         {
389             return eStatus;
390         }
391 
392         ENCODE_CHK_NULL_RETURN(params);
393 
394         EncoderParams* encodeParams = (EncoderParams*)params;;
395         ENCODE_CHK_NULL_RETURN(encodeParams);
396 
397         PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams =
398         static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
399         ENCODE_CHK_NULL_RETURN(hevcPicParams);
400 
401         PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams =
402         static_cast<PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
403         ENCODE_CHK_NULL_RETURN(hevcSeqParams);
404 
405         PCODEC_HEVC_ENCODE_SLICE_PARAMS hevcSliceParams =
406         static_cast<PCODEC_HEVC_ENCODE_SLICE_PARAMS>(encodeParams->pSliceParams);
407         ENCODE_CHK_NULL_RETURN(hevcSliceParams);
408 
409         m_numTileRows    = hevcPicParams->num_tile_rows_minus1 + 1;
410         m_numTileColumns = hevcPicParams->num_tile_columns_minus1 + 1;
411 
412         uint32_t colBd[m_maxTileBdNum] = {0};
413         uint32_t rowBd[m_maxTileBdNum] = {0};
414         ENCODE_CHK_STATUS_RETURN(CalculateTilesBoundary(hevcPicParams, &rowBd[0], &colBd[0]));
415 
416         m_numTiles = m_numTileRows * m_numTileColumns;
417         if (m_numTiles > CODECHAL_GET_WIDTH_IN_BLOCKS(m_basicFeature->m_frameWidth, CODECHAL_HEVC_VDENC_MIN_TILE_WIDTH_SIZE) *
418                 CODECHAL_GET_HEIGHT_IN_BLOCKS(m_basicFeature->m_frameHeight, CODECHAL_HEVC_VDENC_MIN_TILE_HEIGHT_SIZE))
419         {
420             return MOS_STATUS_INVALID_PARAMETER;
421         }
422 
423         bool is10Bit = m_basicFeature->m_is10Bit;
424 
425         uint32_t const numCuRecordTab[] = {1, 4, 16, 64};  //LCU: 8x8->1, 16x16->4, 32x32->16, 64x64->64
426         uint32_t       numCuRecord      = numCuRecordTab[MOS_MIN(3, hevcSeqParams->log2_max_coding_block_size_minus3)];
427         uint32_t       maxBytePerLCU    = 1 << (hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
428         maxBytePerLCU = maxBytePerLCU * maxBytePerLCU;  // number of pixels per LCU
429         maxBytePerLCU = maxBytePerLCU * 3 / (is10Bit ? 1 : 2);  //assume 4:2:0 format
430         uint32_t bitstreamByteOffset = 0, saoRowstoreOffset = 0, cuLevelStreamoutOffset = 0, sseRowstoreOffset = 0;
431         int32_t  frameWidthInMinCb  = hevcSeqParams->wFrameWidthInMinCbMinus1 + 1;
432         int32_t  frameHeightInMinCb = hevcSeqParams->wFrameHeightInMinCbMinus1 + 1;
433         int32_t  shift              = hevcSeqParams->log2_max_coding_block_size_minus3 - hevcSeqParams->log2_min_coding_block_size_minus3;
434         uint32_t ctbSize            = 1 << (hevcSeqParams->log2_max_coding_block_size_minus3 + 3);
435         uint32_t streamInWidthinLCU = MOS_ROUNDUP_DIVIDE((frameWidthInMinCb << (hevcSeqParams->log2_min_coding_block_size_minus3 + 3)), ctbSize);
436         uint32_t tileStartLCUAddr   = 0;
437 
438         ENCODE_CHK_STATUS_RETURN(CalculateNumLcuByTiles(hevcPicParams));
439 
440         uint64_t    activeBitstreamSize = (uint64_t)m_basicFeature->m_bitstreamSize;
441         // There would be padding at the end of last tile in CBR, reserve dedicated part in the BS buf
442         if (hevcSeqParams->RateControlMethod == RATECONTROL_CBR)
443         {
444             // Assume max padding num < target frame size derived from target bit rate and frame rate
445             if (hevcSeqParams->FrameRate.Denominator == 0)
446             {
447                 return MOS_STATUS_INVALID_PARAMETER;
448             }
449             uint32_t actualFrameRate = hevcSeqParams->FrameRate.Numerator / hevcSeqParams->FrameRate.Denominator;
450             uint64_t reservedPart    = (uint64_t)hevcSeqParams->TargetBitRate / 8 / (uint64_t)actualFrameRate * 1024;
451 
452             if (reservedPart > activeBitstreamSize)
453             {
454                 ENCODE_ASSERTMESSAGE("Frame size cal from target Bit rate is larger than BS buf! Issues in CBR paras!");
455                 return MOS_STATUS_INVALID_PARAMETER;
456             }
457 
458             // Capping the reserved part to 1/10 of bs buf size
459             if (reservedPart > activeBitstreamSize / 10)
460             {
461                 reservedPart = activeBitstreamSize / 10;
462             }
463 
464             activeBitstreamSize -= reservedPart;
465         }
466 
467         for (uint32_t numLcusInTiles = 0, i = 0; i < m_numTileRows; i++)
468         {
469             for (uint32_t j = 0; j < m_numTileColumns; j++)
470             {
471                 uint32_t idx          = i * m_numTileColumns + j;
472                 uint32_t numLcuInTile = hevcPicParams->tile_row_height[i] * hevcPicParams->tile_column_width[j];
473 
474                 m_tileData[idx].tileStartXInLCU = colBd[j];
475                 m_tileData[idx].tileStartYInLCU = rowBd[i];
476 
477                 m_tileData[idx].tileColumnStoreSelect = j % 2;
478                 m_tileData[idx].tileRowStoreSelect    = i % 2;
479 
480                 ENCODE_CHK_STATUS_RETURN(CalculateTileWidthAndHeight(hevcPicParams, hevcSeqParams, i, j, &rowBd[0], &colBd[0]));
481 
482                 m_tileData[idx].numOfTilesInFrame       = m_numTiles;
483                 m_tileData[idx].numOfTileColumnsInFrame = m_numTileColumns;
484                 m_tileData[idx].cuRecordOffset = MOS_ALIGN_CEIL(((numCuRecord * numLcusInTiles) * m_hcpItf->GetEncCuRecordSize()),
485                                                      CODECHAL_CACHELINE_SIZE) / CODECHAL_CACHELINE_SIZE;
486 
487                 m_tileData[idx].pakTileStatisticsOffset              = 9 * idx;
488                 m_tileData[idx].tileSizeStreamoutOffset              = idx;
489                 m_tileData[idx].vp9ProbabilityCounterStreamoutOffset = 0;
490 
491                 m_tileData[idx].cuLevelStreamoutOffset   = cuLevelStreamoutOffset;
492                 m_tileData[idx].sseRowstoreOffset        = sseRowstoreOffset;
493                 m_tileData[idx].bitstreamByteOffset      = bitstreamByteOffset;
494                 m_tileData[idx].saoRowstoreOffset        = saoRowstoreOffset;
495 
496                 uint32_t tileHeightInLCU                 = MOS_ROUNDUP_DIVIDE(((m_tileData[idx].tileHeightInMinCbMinus1 + 1) << (hevcSeqParams->log2_min_coding_block_size_minus3 + 3)), ctbSize);
497                 uint32_t tileWidthInLCU                  = MOS_ROUNDUP_DIVIDE(((m_tileData[idx].tileWidthInMinCbMinus1 + 1) << (hevcSeqParams->log2_min_coding_block_size_minus3 + 3)), ctbSize);
498 
499                 m_tileData[idx].tileEndXInLCU              = m_tileData[idx].tileStartXInLCU + tileWidthInLCU;
500                 m_tileData[idx].tileEndYInLCU              = m_tileData[idx].tileStartYInLCU + tileHeightInLCU;
501 
502                 //StreamIn data is 4 CLs per LCU
503                 m_tileData[idx].tileStreaminOffset       = 4 * (m_tileData[idx].tileStartYInLCU * streamInWidthinLCU + m_tileData[idx].tileStartXInLCU * tileHeightInLCU);
504                 m_tileData[idx].sliceSizeStreamoutOffset = tileStartLCUAddr;
505 
506                 tileStartLCUAddr += (tileWidthInLCU * tileHeightInLCU);
507 
508                 cuLevelStreamoutOffset += (m_tileData[idx].tileWidthInMinCbMinus1 + 1) * (m_tileData[idx].tileHeightInMinCbMinus1 + 1) * 16 / CODECHAL_CACHELINE_SIZE;
509                 sseRowstoreOffset += ((hevcPicParams->tile_column_width[j] + 3) * ((HevcBasicFeature*)m_basicFeature)->m_sizeOfSseSrcPixelRowStoreBufferPerLcu) / CODECHAL_CACHELINE_SIZE;
510                 saoRowstoreOffset += (MOS_ALIGN_CEIL(hevcPicParams->tile_column_width[j], 4) * CODECHAL_HEVC_SAO_STRMOUT_SIZE_PERLCU) / CODECHAL_CACHELINE_SIZE;
511 
512                 uint64_t totalSizeTemp = (uint64_t)activeBitstreamSize * (uint64_t)numLcuInTile;
513                 uint32_t bitStreamSizePerTile = (uint32_t)(totalSizeTemp / (uint64_t)m_numLcuInPic) + ((totalSizeTemp % (uint64_t)m_numLcuInPic) ? 1 : 0);
514                 bitstreamByteOffset += MOS_ALIGN_CEIL(bitStreamSizePerTile, CODECHAL_CACHELINE_SIZE) / CODECHAL_CACHELINE_SIZE;
515 
516                 numLcusInTiles += numLcuInTile;
517             }
518 
519             // same row store buffer for different tile rows.
520             saoRowstoreOffset = 0;
521             sseRowstoreOffset = 0;
522         }
523 
524         return eStatus;
525     }
526 
AllocateTileStatistics(void * params)527     MOS_STATUS HevcEncodeTile::AllocateTileStatistics(void *params)
528     {
529         ENCODE_FUNC_CALL();
530 
531         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
532 
533         ENCODE_CHK_NULL_RETURN(params);
534 
535         if (!m_enabled)
536         {
537             return eStatus;
538         }
539 
540         EncoderParams *encodeParams = (EncoderParams *)params;
541         ENCODE_CHK_NULL_RETURN(encodeParams);
542 
543         PCODEC_HEVC_ENCODE_PICTURE_PARAMS hevcPicParams =
544             static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
545         ENCODE_CHK_NULL_RETURN(hevcPicParams);
546 
547         auto num_tile_rows    = hevcPicParams->num_tile_rows_minus1 + 1;
548         auto num_tile_columns = hevcPicParams->num_tile_columns_minus1 + 1;
549         auto num_tiles        = num_tile_rows * num_tile_columns;
550 
551         uint32_t maxLcuSize = 64;
552         if (m_numLcuInPic == 0)
553         {
554             ENCODE_ASSERTMESSAGE("LCU num cal by each tile is zero, sth must be wrong!");
555             return MOS_STATUS_INVALID_PARAMETER;
556         }
557 
558         MOS_ZeroMemory(&m_hevcFrameStatsOffset, sizeof(HevcTileStatusInfo));
559         MOS_ZeroMemory(&m_hevcTileStatsOffset, sizeof(HevcTileStatusInfo));
560         MOS_ZeroMemory(&m_hevcStatsSize, sizeof(HevcTileStatusInfo));
561 
562         // Set the maximum size based on frame level statistics.
563         m_hevcStatsSize.tileSizeRecord     = CODECHAL_CACHELINE_SIZE;
564         m_hevcStatsSize.hevcPakStatistics  = EncodeBasicFeature::m_sizeOfHcpPakFrameStats;
565         m_hevcStatsSize.vdencStatistics    = CODECHAL_HEVC_VDENC_STATS_SIZE;
566         m_hevcStatsSize.hevcSliceStreamout = CODECHAL_CACHELINE_SIZE;
567 
568         // Maintain the offsets to use for patching addresses in to the HuC Pak Integration kernel Aggregated Frame Statistics Output Buffer
569         // Each offset needs to be page aligned as the combined region is fed into different page aligned HuC regions
570         m_hevcFrameStatsOffset.tileSizeRecord     = 0;  // Tile Size Record is not present in resHuCPakAggregatedFrameStatsBuffer
571         m_hevcFrameStatsOffset.hevcPakStatistics  = 0;
572         m_hevcFrameStatsOffset.vdencStatistics    = MOS_ALIGN_CEIL(m_hevcFrameStatsOffset.hevcPakStatistics + m_hevcStatsSize.hevcPakStatistics, CODECHAL_PAGE_SIZE);
573         m_hevcFrameStatsOffset.hevcSliceStreamout = MOS_ALIGN_CEIL(m_hevcFrameStatsOffset.vdencStatistics + m_hevcStatsSize.vdencStatistics, CODECHAL_PAGE_SIZE);
574 
575         // Frame level statistics
576         m_hwInterface->m_pakIntAggregatedFrameStatsSize = MOS_ALIGN_CEIL(m_hevcFrameStatsOffset.hevcSliceStreamout + (m_hevcStatsSize.hevcSliceStreamout * m_numLcuInPic), CODECHAL_PAGE_SIZE);
577 
578         // HEVC Frame Statistics Buffer - Output from HuC PAK Integration kernel
579         if (Mos_ResourceIsNull(&m_resHuCPakAggregatedFrameStatsBuffer))
580         {
581             MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
582             MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
583             allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
584             allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
585             allocParamsForBufferLinear.Format   = Format_Buffer;
586             allocParamsForBufferLinear.dwBytes  = m_hwInterface->m_pakIntAggregatedFrameStatsSize;
587             allocParamsForBufferLinear.pBufName = "HCP Aggregated Frame Statistics Streamout Buffer";
588             allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
589             auto resource = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
590             ENCODE_CHK_NULL_RETURN(resource);
591             m_resHuCPakAggregatedFrameStatsBuffer = *resource;
592         }
593 
594         // Maintain the offsets to use for patching addresses in to the Tile Based Statistics Buffer
595         // Each offset needs to be page aligned as the combined region is fed into different page aligned HuC regions
596         m_hevcTileStatsOffset.tileSizeRecord     = 0; // TileRecord is a separated resource
597         m_hevcTileStatsOffset.hevcPakStatistics  = 0; // PakStatistics is head of m_resTileBasedStatisticsBuffer;
598         m_hevcTileStatsOffset.vdencStatistics    = MOS_ALIGN_CEIL(m_hevcTileStatsOffset.hevcPakStatistics + (m_hevcStatsSize.hevcPakStatistics * num_tiles), CODECHAL_PAGE_SIZE);
599         m_hevcTileStatsOffset.hevcSliceStreamout = MOS_ALIGN_CEIL(m_hevcTileStatsOffset.vdencStatistics + (m_hevcStatsSize.vdencStatistics * num_tiles), CODECHAL_PAGE_SIZE);
600         // Combined statistics size for all tiles
601         m_hwInterface->m_pakIntTileStatsSize = MOS_ALIGN_CEIL(m_hevcTileStatsOffset.hevcSliceStreamout + m_hevcStatsSize.hevcSliceStreamout * m_numLcuInPic, CODECHAL_PAGE_SIZE);
602 
603         // Tile size record size for all tiles
604         m_hwInterface->m_tileRecordSize = m_hevcStatsSize.tileSizeRecord * num_tiles;
605 
606         MOS_SURFACE surface;
607         MOS_ZeroMemory(&surface, sizeof(surface));
608         surface.OsResource = m_resTileBasedStatisticsBuffer[m_statisticsBufIndex];
609         if (!Mos_ResourceIsNull(&surface.OsResource))
610         {
611             m_allocator->GetSurfaceInfo(&surface);
612         }
613         uint32_t curPakIntTileStatsSize = surface.dwHeight * surface.dwWidth;
614 
615         if (Mos_ResourceIsNull(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]) ||
616             curPakIntTileStatsSize < m_hwInterface->m_pakIntTileStatsSize)
617         {
618             if (!Mos_ResourceIsNull(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]))
619             {
620                 m_allocator->DestroyResource(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]);
621             }
622             MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
623             MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
624             allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
625             allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
626             allocParamsForBufferLinear.Format   = Format_Buffer;
627             allocParamsForBufferLinear.dwBytes  = m_hwInterface->m_pakIntTileStatsSize;
628             allocParamsForBufferLinear.pBufName = "HCP Tile Level Statistics Streamout Buffer";
629             allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
630             auto resource = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
631             ENCODE_CHK_NULL_RETURN(resource);
632             m_resTileBasedStatisticsBuffer[m_statisticsBufIndex] = *resource;
633         }
634 
635         // Allocate the updated tile size buffer for PAK integration kernel
636         if (Mos_ResourceIsNull(&m_tileRecordBuffer[m_statisticsBufIndex]))
637         {
638             MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
639             MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
640             allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
641             allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
642             allocParamsForBufferLinear.Format   = Format_Buffer;
643             allocParamsForBufferLinear.dwBytes  = CODECHAL_CACHELINE_SIZE * num_tiles;
644             allocParamsForBufferLinear.pBufName = "Tile Record Buffer";
645             allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
646 
647             auto resource = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
648             ENCODE_CHK_NULL_RETURN(resource);
649             m_tileRecordBuffer[m_statisticsBufIndex] = *resource;
650         }
651 
652         return eStatus;
653     }
654 
GetTileStatusInfo(HevcTileStatusInfo & hevcTileStatsOffset,HevcTileStatusInfo & hevcFrameStatsOffset,HevcTileStatusInfo & hevcStatsSize)655     MOS_STATUS HevcEncodeTile::GetTileStatusInfo(
656         HevcTileStatusInfo &hevcTileStatsOffset,
657         HevcTileStatusInfo &hevcFrameStatsOffset,
658         HevcTileStatusInfo &hevcStatsSize)
659     {
660         ENCODE_FUNC_CALL();
661         if (!m_enabled)
662         {
663             return MOS_STATUS_SUCCESS;
664         }
665 
666         hevcTileStatsOffset  = m_hevcTileStatsOffset;
667         hevcFrameStatsOffset = m_hevcFrameStatsOffset;
668         hevcStatsSize        = m_hevcStatsSize;
669 
670         return MOS_STATUS_SUCCESS;
671     }
672 
GetTileInfo(HevcTileInfo * hevcTileInfo) const673     MOS_STATUS HevcEncodeTile::GetTileInfo(HevcTileInfo *hevcTileInfo) const
674     {
675         ENCODE_CHK_NULL_RETURN(hevcTileInfo);
676 
677         if (m_enabled)
678         {
679             hevcTileInfo->tileId = static_cast<uint16_t>(m_tileIdx);  // Tile number in a frame
680 
681             const auto currTileData = m_tileData[m_tileIdx];
682 
683             hevcTileInfo->tileColPositionInSb = static_cast<uint16_t>(currTileData.tileStartX);
684             hevcTileInfo->tileRowPositionInSb = static_cast<uint16_t>(currTileData.tileStartY);
685 
686             hevcTileInfo->tileWidthInSbMinus1  = currTileData.tileEndX - currTileData.tileStartX - 1;
687             hevcTileInfo->tileHeightInSbMinus1 = currTileData.tileEndY - currTileData.tileStartY - 1;
688 
689             hevcTileInfo->tileStartXInLCU = currTileData.tileStartX;
690             hevcTileInfo->tileStartYInLCU = currTileData.tileStartY;
691             hevcTileInfo->tileEndXInLCU   = currTileData.tileEndX;
692             hevcTileInfo->tileEndYInLCU   = currTileData.tileEndY;
693             hevcTileInfo->tileNum         = static_cast<uint16_t>(m_tileIdx);
694         }
695         return MOS_STATUS_SUCCESS;
696     }
697 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT,HevcEncodeTile)698     MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, HevcEncodeTile)
699     {
700         if (m_enabled)
701         {
702             params.tileBasedReplayMode = m_enableTileReplay;
703         }
704         else
705         {
706             params.tileBasedReplayMode = 0;
707         }
708         return MOS_STATUS_SUCCESS;
709     }
710 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,HevcEncodeTile)711     MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, HevcEncodeTile)
712     {
713         ENCODE_FUNC_CALL();
714 
715         if (!m_enabled)
716         {
717             return MOS_STATUS_SUCCESS;
718         }
719 
720         MOS_RESOURCE *tileStatisticsBuffer = const_cast<MOS_RESOURCE *>(& m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]);
721 
722         if (!Mos_ResourceIsNull(tileStatisticsBuffer))
723         {
724             params.streamOutBuffer = tileStatisticsBuffer;
725             params.streamOutOffset = m_hevcTileStatsOffset.vdencStatistics;
726         }
727 
728         return MOS_STATUS_SUCCESS;
729     }
730 
MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE,HevcEncodeTile)731     MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE, HevcEncodeTile)
732     {
733         auto hevcBasicFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
734         ENCODE_CHK_NULL_RETURN(hevcBasicFeature);
735         auto picParams = hevcBasicFeature->m_hevcPicParams;
736         ENCODE_CHK_NULL_RETURN(picParams);
737         auto seqParams = hevcBasicFeature->m_hevcSeqParams;
738         ENCODE_CHK_NULL_RETURN(seqParams);
739         auto t_sliceParams = hevcBasicFeature->m_hevcSliceParams;
740         ENCODE_CHK_NULL_RETURN(t_sliceParams);
741         CODEC_HEVC_ENCODE_SLICE_PARAMS *sliceParams = (CODEC_HEVC_ENCODE_SLICE_PARAMS *)&t_sliceParams[hevcBasicFeature->m_curNumSlices];
742 
743         uint32_t ctbSize     = 1 << (seqParams->log2_max_coding_block_size_minus3 + 3);
744         uint32_t widthInPix  = (1 << (seqParams->log2_min_coding_block_size_minus3 + 3)) * (seqParams->wFrameWidthInMinCbMinus1 + 1);
745         uint32_t widthInCtb  = (widthInPix / ctbSize) + ((widthInPix % ctbSize) ? 1 : 0);  // round up
746         uint32_t heightInPix = (1 << (seqParams->log2_min_coding_block_size_minus3 + 3)) * (seqParams->wFrameHeightInMinCbMinus1 + 1);
747         uint32_t heightInCtb = (heightInPix / ctbSize) + ((heightInPix % ctbSize) ? 1 : 0);  // round up
748         uint32_t shift       = seqParams->log2_max_coding_block_size_minus3 - seqParams->log2_min_coding_block_size_minus3;
749 
750         if (!m_enabled)
751         {
752             params.firstSuperSlice = 0;
753             // No tiling support
754             params.tileSliceStartLcuMbY      = sliceParams->slice_segment_address / widthInCtb;
755             params.nextTileSliceStartLcuMbX  = (sliceParams->slice_segment_address + sliceParams->NumLCUsInSlice) / heightInCtb;
756             params.nextTileSliceStartLcuMbY  = (sliceParams->slice_segment_address + sliceParams->NumLCUsInSlice) / widthInCtb;
757         }
758         else
759         {
760             params.tileSliceStartLcuMbX = (&m_curTileCodingParams)->TileStartLCUX;
761             params.tileSliceStartLcuMbY = (&m_curTileCodingParams)->TileStartLCUY;
762 
763             // In HEVC vdnec, always first super slice in each tile
764             params.firstSuperSlice = 1;
765 
766             params.nextTileSliceStartLcuMbX = (&m_curTileCodingParams)->TileStartLCUX + ((&m_curTileCodingParams)->TileWidthInMinCbMinus1 >> shift) + 1;
767             params.nextTileSliceStartLcuMbY = (&m_curTileCodingParams)->TileStartLCUY + ((&m_curTileCodingParams)->TileHeightInMinCbMinus1 >> shift) + 1;
768         }
769 
770         return MOS_STATUS_SUCCESS;
771     }
772 
MHW_SETPAR_DECL_SRC(HCP_PIPE_MODE_SELECT,HevcEncodeTile)773     MHW_SETPAR_DECL_SRC(HCP_PIPE_MODE_SELECT, HevcEncodeTile)
774     {
775         ENCODE_FUNC_CALL();
776 
777         // In single pipe mode, if TileBasedReplayMode is enabled,
778         // the bit stream for each tile will not be continuous
779         if (m_enabled)
780         {
781             params.bTileBasedReplayMode = m_enableTileReplay;
782         }
783         else
784         {
785             params.bTileBasedReplayMode = 0;
786         }
787 
788         return MOS_STATUS_SUCCESS;
789     }
790 
MHW_SETPAR_DECL_SRC(HCP_TILE_CODING,HevcEncodeTile)791     MHW_SETPAR_DECL_SRC(HCP_TILE_CODING, HevcEncodeTile)
792     {
793         ENCODE_FUNC_CALL();
794         if (!m_enabled)
795         {
796             return MOS_STATUS_SUCCESS;
797         }
798 
799         params.numOfTileColumnsInFrame              = m_curTileCodingParams.NumOfTileColumnsInFrame;
800         params.tileRowStoreSelect                   = m_curTileCodingParams.TileRowStoreSelect;
801         params.tileColumnStoreSelect                = m_curTileCodingParams.TileColumnStoreSelect;
802         params.tileStartLCUX                        = m_curTileCodingParams.TileStartLCUX;
803         params.tileStartLCUY                        = m_curTileCodingParams.TileStartLCUY;
804         params.isLastTileofColumn                   = m_curTileCodingParams.IsLastTileofColumn;
805         params.isLastTileofRow                      = m_curTileCodingParams.IsLastTileofRow;
806         params.tileHeightInMinCbMinus1              = m_curTileCodingParams.TileHeightInMinCbMinus1;
807         params.tileWidthInMinCbMinus1               = m_curTileCodingParams.TileWidthInMinCbMinus1;
808         params.cuRecordOffset                       = m_curTileCodingParams.CuRecordOffset;
809         params.bitstreamByteOffset                  = m_curTileCodingParams.BitstreamByteOffset;
810         params.pakTileStatisticsOffset              = m_curTileCodingParams.PakTileStatisticsOffset;
811         params.cuLevelStreamoutOffset               = m_curTileCodingParams.CuLevelStreamoutOffset;
812         params.sliceSizeStreamoutOffset             = m_curTileCodingParams.SliceSizeStreamoutOffset;
813         params.sseRowstoreOffset                    = m_curTileCodingParams.SseRowstoreOffset;
814         params.saoRowstoreOffset                    = m_curTileCodingParams.SaoRowstoreOffset;
815         params.tileSizeStreamoutOffset              = m_curTileCodingParams.TileSizeStreamoutOffset;
816         params.vp9ProbabilityCounterStreamoutOffset = 0;
817         params.nonFirstPassTile                     = m_curTileCodingParams.bTileReplayEnable && (!m_curTileCodingParams.IsFirstPass);
818         params.bitstreamByteOffsetEnable            = m_curTileCodingParams.bTileReplayEnable;
819 
820         return MOS_STATUS_SUCCESS;
821     }
822 
MHW_SETPAR_DECL_SRC(HCP_PIPE_BUF_ADDR_STATE,HevcEncodeTile)823     MHW_SETPAR_DECL_SRC(HCP_PIPE_BUF_ADDR_STATE, HevcEncodeTile)
824     {
825         ENCODE_FUNC_CALL();
826 
827         if (m_enabled && m_curTileCodingParams.NumberOfActiveBePipes > 1)
828         {
829             MOS_RESOURCE *tileStatisticsBuffer = const_cast<PMOS_RESOURCE>(&m_resTileBasedStatisticsBuffer[m_statisticsBufIndex]);
830             if (!Mos_ResourceIsNull(tileStatisticsBuffer))
831             {
832                 params.presLcuBaseAddressBuffer     = tileStatisticsBuffer;
833                 params.dwLcuStreamOutOffset         = m_hevcTileStatsOffset.hevcSliceStreamout;
834                 params.presFrameStatStreamOutBuffer = tileStatisticsBuffer;
835                 params.dwFrameStatStreamOutOffset   = m_hevcTileStatsOffset.hevcPakStatistics;
836             }
837         }
838         else
839         {
840             params.presLcuBaseAddressBuffer     = m_basicFeature->m_recycleBuf->GetBuffer(LcuBaseAddressBuffer, 0);
841             params.presFrameStatStreamOutBuffer = m_basicFeature->m_recycleBuf->GetBuffer(FrameStatStreamOutBuffer, 0);
842         }
843 
844         return MOS_STATUS_SUCCESS;
845     }
846 
MHW_SETPAR_DECL_SRC(HCP_SLICE_STATE,HevcEncodeTile)847     MHW_SETPAR_DECL_SRC(HCP_SLICE_STATE, HevcEncodeTile)
848     {
849         ENCODE_FUNC_CALL();
850 
851         if (!m_enabled)
852         {
853             return MOS_STATUS_SUCCESS;
854         }
855 
856         auto hevcFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
857         ENCODE_CHK_NULL_RETURN(hevcFeature);
858 
859         params.lastSliceInTile       = hevcFeature->m_lastSliceInTile;
860         params.lastSliceInTileColumn = (hevcFeature->m_lastSliceInTile & m_tileData[m_tileIdx].isLastTileofColumn) ? true : false;
861 
862         return MOS_STATUS_SUCCESS;
863     }
864 
MHW_SETPAR_DECL_SRC(HCP_IND_OBJ_BASE_ADDR_STATE,HevcEncodeTile)865     MHW_SETPAR_DECL_SRC(HCP_IND_OBJ_BASE_ADDR_STATE, HevcEncodeTile)
866     {
867         ENCODE_FUNC_CALL();
868 
869         if (!m_enabled)
870         {
871             return MOS_STATUS_SUCCESS;
872         }
873 
874         MOS_RESOURCE *tileRecordBuffer = const_cast<PMOS_RESOURCE>(&m_tileRecordBuffer[m_statisticsBufIndex]);
875         if (!Mos_ResourceIsNull(tileRecordBuffer))
876         {
877             params.presPakTileSizeStasBuffer   = tileRecordBuffer;
878             params.dwPakTileSizeStasBufferSize = m_hwInterface->m_tileRecordSize;
879             params.dwPakTileSizeRecordOffset   = m_hevcTileStatsOffset.tileSizeRecord;
880         }
881 
882         return MOS_STATUS_SUCCESS;
883     }
884 
MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE,HevcEncodeTile)885     MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE, HevcEncodeTile)
886     {
887         auto hevcBasicFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
888         ENCODE_CHK_NULL_RETURN(hevcBasicFeature);
889         auto picParams = hevcBasicFeature->m_hevcPicParams;
890         ENCODE_CHK_NULL_RETURN(picParams);
891         auto seqParams = hevcBasicFeature->m_hevcSeqParams;
892         ENCODE_CHK_NULL_RETURN(seqParams);
893         auto sliceParams = hevcBasicFeature->m_hevcSliceParams;
894         ENCODE_CHK_NULL_RETURN(sliceParams);
895 
896         uint32_t ctbSize          = 1 << (seqParams->log2_max_coding_block_size_minus3 + 3);
897         uint32_t widthInPix       = (1 << (seqParams->log2_min_coding_block_size_minus3 + 3)) * (seqParams->wFrameWidthInMinCbMinus1 + 1);
898         uint32_t heightInPix      = (1 << (seqParams->log2_min_coding_block_size_minus3 + 3)) * (seqParams->wFrameHeightInMinCbMinus1 + 1);
899         uint32_t minCodingBlkSize = seqParams->log2_min_coding_block_size_minus3 + 3;
900         params.ctbSize            = ctbSize;
901 
902         if (!m_enabled)
903         {
904             // No tiling support
905             params.tileWidth  = widthInPix;
906             params.tileHeight = heightInPix;
907         }
908         else
909         {
910             params.tileStartLCUX = (&m_curTileCodingParams)->TileStartLCUX;
911             params.tileStartLCUY = (&m_curTileCodingParams)->TileStartLCUY;
912 
913             params.tileWidth  = (((&m_curTileCodingParams)->TileWidthInMinCbMinus1 + 1) << minCodingBlkSize);
914             params.tileHeight = (((&m_curTileCodingParams)->TileHeightInMinCbMinus1 + 1) << minCodingBlkSize);
915 
916             // NumParEngine is not used by HW
917             //cmd.DW3.NumParEngine = tileSlcParams->dwNumberOfPipes;
918 
919             params.tileId             = m_tileIdx;
920             params.tileRowStoreSelect = (&m_curTileCodingParams)->TileRowStoreSelect;
921             params.tileEnable         = 1;
922             params.tileStreamInOffset = (&m_curTileCodingParams)->TileStreaminOffset;
923 
924             // PAK Object StreamOut Offset Computation
925             uint32_t tileLCUStreamOutByteOffset = 0;
926             if ((&m_curTileCodingParams)->TileStartLCUX != 0 || (&m_curTileCodingParams)->TileStartLCUY != 0)
927             {
928                 uint32_t NumOfCUInLCU       = (ctbSize >> 3) * (ctbSize >> 3);  // Min CU size is 8
929                 uint32_t ImgWidthInLCU      = (widthInPix + ctbSize - 1) / ctbSize;
930                 uint32_t ImgHeightInLCU     = (heightInPix + ctbSize - 1) / ctbSize;
931                 uint32_t NumLCUsCurLocation = (&m_curTileCodingParams)->TileStartLCUY * ImgWidthInLCU + (&m_curTileCodingParams)->TileStartLCUX *
932                                                                                                             (((((&m_curTileCodingParams)->TileHeightInMinCbMinus1 + 1) << minCodingBlkSize) + ctbSize - 1) / ctbSize);
933                 //For PAKObject Surface
934                 tileLCUStreamOutByteOffset = 2 * BYTES_PER_DWORD * NumLCUsCurLocation * (NUM_PAK_DWS_PER_LCU + NumOfCUInLCU * NUM_DWS_PER_CU);
935                 //Add 1 CL for size info at the beginning of each tile
936                 tileLCUStreamOutByteOffset += MHW_CACHELINE_SIZE;
937                 //CL alignment at end of every tile
938                 tileLCUStreamOutByteOffset = MOS_ROUNDUP_DIVIDE(tileLCUStreamOutByteOffset, MHW_CACHELINE_SIZE);
939             }
940 
941             params.tileLCUStreamOutOffset = tileLCUStreamOutByteOffset;
942             params.tileRowstoreOffset     = (params.tileStartLCUY == 0) ? (params.tileStartLCUX * params.ctbSize) / 32 : 0;
943         }
944 
945         return MOS_STATUS_SUCCESS;
946     }
947 
948     }  // namespace encode
949