1 /*
2 * Copyright (c) 2019-2022, 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 decode_hevc_tile_coding.cpp
24 //! \brief Defines the common interface for decode hevc tile coding
25 //!
26
27 #include "decode_hevc_tile_coding.h"
28 #include "decode_hevc_basic_feature.h"
29 #include "codec_def_common.h"
30 #include "decode_pipeline.h"
31
32 namespace decode
33 {
~HevcTileCoding()34 HevcTileCoding::~HevcTileCoding()
35 {
36 for (auto sliceTileInfo : m_sliceTileInfoList)
37 {
38 MOS_DeleteArray(sliceTileInfo->tileArrayBuf);
39 MOS_Delete(sliceTileInfo);
40 }
41 m_sliceTileInfoList.clear();
42
43 if (m_pCtbAddrRsToTs)
44 {
45 MOS_FreeMemory(m_pCtbAddrRsToTs);
46 }
47 }
48
Init(HevcBasicFeature * basicFeature,CodechalSetting * codecSettings)49 MOS_STATUS HevcTileCoding::Init(HevcBasicFeature *basicFeature, CodechalSetting *codecSettings)
50 {
51 DECODE_FUNC_CALL();
52 DECODE_CHK_NULL(basicFeature);
53 DECODE_CHK_NULL(codecSettings);
54
55 m_basicFeature = basicFeature;
56
57 return MOS_STATUS_SUCCESS;
58 }
59
UpdatePicture(const CODEC_HEVC_PIC_PARAMS & picParams)60 MOS_STATUS HevcTileCoding::UpdatePicture(const CODEC_HEVC_PIC_PARAMS & picParams)
61 {
62 DECODE_FUNC_CALL();
63 if (picParams.tiles_enabled_flag == 1)
64 {
65 DECODE_CHK_STATUS(GetAllTileInfo(picParams, m_basicFeature->m_widthInCtb,
66 m_basicFeature->m_heightInCtb));
67 }
68
69 return MOS_STATUS_SUCCESS;
70 }
71
UpdateSlice(const CODEC_HEVC_PIC_PARAMS & picParams,const PCODEC_HEVC_SLICE_PARAMS sliceParams)72 MOS_STATUS HevcTileCoding::UpdateSlice(const CODEC_HEVC_PIC_PARAMS & picParams,
73 const PCODEC_HEVC_SLICE_PARAMS sliceParams)
74 {
75 DECODE_FUNC_CALL();
76
77 if (m_basicFeature->m_shortFormatInUse)
78 {
79 return MOS_STATUS_SUCCESS;
80 }
81
82 for (uint32_t slcIdx = 0; slcIdx < m_basicFeature->m_numSlices; slcIdx++)
83 {
84 SliceTileInfo* sliceTileInfo = AllocateSliceTileInfo(slcIdx);
85 DECODE_CHK_NULL(sliceTileInfo);
86
87 if (m_basicFeature->IsIndependentSlice(slcIdx))
88 {
89 sliceTileInfo->origCtbX = sliceParams[slcIdx].slice_segment_address % m_basicFeature->m_widthInCtb;
90 sliceTileInfo->origCtbY = sliceParams[slcIdx].slice_segment_address / m_basicFeature->m_widthInCtb;
91
92 }
93 else
94 {
95 // Dependent slice share same orig ctbx and ctby with previous slice in real tile and separate tile mode.
96 for (int32_t index = slcIdx - 1; index >= 0; --index) //search backword
97 {
98 if(!sliceParams[index].LongSliceFlags.fields.dependent_slice_segment_flag) //independent slice
99 {
100 sliceTileInfo->origCtbX = sliceParams[index].slice_segment_address % m_basicFeature->m_widthInCtb;
101 sliceTileInfo->origCtbY = sliceParams[index].slice_segment_address / m_basicFeature->m_widthInCtb;
102
103 break;
104 }
105 }
106 }
107 }
108
109 if (picParams.tiles_enabled_flag == 1)
110 {
111 for (uint32_t slcIdx = 0; slcIdx < m_basicFeature->m_numSlices; slcIdx++)
112 {
113 SliceTileInfo* sliceTileInfo = m_sliceTileInfoList[slcIdx];
114 DECODE_CHK_NULL(sliceTileInfo);
115 sliceTileInfo->sliceTileX = ComputeSliceTileX(picParams, sliceParams[slcIdx]);
116 sliceTileInfo->sliceTileY = ComputeSliceTileY(picParams, sliceParams[slcIdx]);
117 }
118 }
119
120 return MOS_STATUS_SUCCESS;
121 }
122
UpdateSliceTileInfo()123 MOS_STATUS HevcTileCoding::UpdateSliceTileInfo()
124 {
125 DECODE_FUNC_CALL();
126
127 if (m_basicFeature->m_shortFormatInUse)
128 {
129 return MOS_STATUS_SUCCESS;
130 }
131
132 const CODEC_HEVC_PIC_PARAMS& picParams = *(m_basicFeature->m_hevcPicParams);
133 const PCODEC_HEVC_SLICE_PARAMS sliceParams = m_basicFeature->m_hevcSliceParams;
134
135 DECODE_CHK_COND(m_basicFeature->m_numSlices > m_sliceTileInfoList.size(),
136 "Number of slices is exceeds the size of tile info list!");
137
138 /* To generate RsToTs convert table per frame */
139 if (picParams.tiles_enabled_flag == 1)
140 {
141 uint32_t picSizeInCtbsY = m_basicFeature->m_widthInCtb * m_basicFeature->m_heightInCtb;
142 if (nullptr == m_pCtbAddrRsToTs || m_CurRsToTsTableSize < picSizeInCtbsY)
143 {
144 if (m_pCtbAddrRsToTs)
145 {
146 MOS_FreeMemory(m_pCtbAddrRsToTs);
147 }
148 m_pCtbAddrRsToTs = (uint32_t *)MOS_AllocAndZeroMemory(picSizeInCtbsY * sizeof(uint32_t));
149 DECODE_CHK_NULL(m_pCtbAddrRsToTs);
150 m_CurRsToTsTableSize = picSizeInCtbsY;
151 }
152 RsToTsAddrConvert(picParams, picSizeInCtbsY);
153 }
154
155 for (uint32_t slcIdx = 0; slcIdx < m_basicFeature->m_numSlices; slcIdx++)
156 {
157 SliceTileInfo* sliceTileInfo = m_sliceTileInfoList[slcIdx];
158 DECODE_CHK_NULL(sliceTileInfo);
159
160 if (slcIdx == 0)
161 {
162 sliceTileInfo->firstSliceOfTile = true;
163 }
164 else
165 {
166 auto tileInfo = GetSliceTileInfo(slcIdx-1);
167 DECODE_CHK_NULL(tileInfo);
168 sliceTileInfo->firstSliceOfTile = tileInfo->numTiles > 0;
169 }
170
171 bool lastSlice = m_basicFeature->IsLastSlice(slcIdx);
172 sliceTileInfo->numTiles = ComputeTileNumForSlice(picParams, slcIdx,
173 sliceTileInfo->sliceTileX, sliceTileInfo->sliceTileY, lastSlice);
174 if(sliceTileInfo->numTiles > (picParams.num_tile_columns_minus1+1)*(picParams.num_tile_rows_minus1+1))
175 {
176 DECODE_ASSERTMESSAGE("Number of slice tile is exceeds the number of total tile!\n");
177 return MOS_STATUS_INVALID_PARAMETER;
178 }
179 // Case 1: multiple tiles in single slice, this is the last slice in tile.
180 // Case 2: multiple slices in single tile, these slices share same tile position which means numTilesInSlice is 0.
181 sliceTileInfo->lastSliceOfTile = (sliceTileInfo->numTiles > 0);
182
183 if (picParams.tiles_enabled_flag == 1 && sliceTileInfo->numTiles > 1)
184 {
185 if (sliceTileInfo->numTiles > sliceTileInfo->tileArraySize)
186 {
187 MOS_DeleteArray(sliceTileInfo->tileArrayBuf);
188 sliceTileInfo->tileArrayBuf = MOS_NewArray(SubTileInfo, sliceTileInfo->numTiles);
189 DECODE_CHK_NULL(sliceTileInfo->tileArrayBuf);
190 sliceTileInfo->tileArraySize = sliceTileInfo->numTiles;
191 }
192 DECODE_CHK_STATUS(UpdateSubTileInfo(picParams, sliceParams[slcIdx], *sliceTileInfo));
193 }
194
195 uint16_t tileStartCtbX = GetTileCtbX(sliceTileInfo->sliceTileX);
196 uint16_t tileStartCtbY = GetTileCtbY(sliceTileInfo->sliceTileY);
197 uint16_t subStreamCount = (sliceTileInfo->numTiles > 0) ? sliceTileInfo->numTiles : 1;
198 for (uint16_t tileId = 0; tileId < subStreamCount; tileId++)
199 {
200 if (sliceTileInfo->firstSliceOfTile)
201 {
202 /* Check the startCtbX and startCtbY for firstsliceoftile and firsttileofslice */
203 if (tileId == 0)
204 {
205 uint32_t slicestartCtbX = sliceParams[slcIdx].slice_segment_address % m_basicFeature->m_widthInCtb;
206 uint32_t slicestartCtbY = sliceParams[slcIdx].slice_segment_address / m_basicFeature->m_widthInCtb;
207 if (slicestartCtbY != tileStartCtbY || slicestartCtbX != tileStartCtbX)
208 {
209 DECODE_ASSERTMESSAGE("slicestartCtbX(%d) does not equal to tilestartCtbX(%d) or slicestartCtbY(%d) does not equal to tilestartCtbY(%d)\n",
210 slicestartCtbX, tileStartCtbX, slicestartCtbY, tileStartCtbY);
211 return MOS_STATUS_INVALID_PARAMETER;
212 }
213 }
214 }
215 }
216
217 /* Check slice segment address in tile scan should be increasing */
218 if (picParams.tiles_enabled_flag == 1)
219 {
220 if ((m_pCtbAddrRsToTs != nullptr) && (slcIdx > 0))
221 {
222 if (m_pCtbAddrRsToTs[sliceParams[slcIdx].slice_segment_address] <= m_pCtbAddrRsToTs[sliceParams[slcIdx - 1].slice_segment_address]) // Tile scan address is not increasing
223 {
224 DECODE_ASSERTMESSAGE("Address in tile scan is not increasing, %dth slice tile scan address = %d, %dth slice tile scan address = %d\n",
225 slcIdx - 1,
226 m_pCtbAddrRsToTs[sliceParams[slcIdx - 1].slice_segment_address],
227 slcIdx,
228 m_pCtbAddrRsToTs[sliceParams[slcIdx].slice_segment_address]);
229 return MOS_STATUS_INVALID_PARAMETER;
230 }
231 }
232 }
233 }
234
235 return MOS_STATUS_SUCCESS;
236 }
237
UpdateSubTileInfo(const CODEC_HEVC_PIC_PARAMS & picParams,const CODEC_HEVC_SLICE_PARAMS & sliceParams,SliceTileInfo & sliceTileInfo)238 MOS_STATUS HevcTileCoding::UpdateSubTileInfo(const CODEC_HEVC_PIC_PARAMS & picParams,
239 const CODEC_HEVC_SLICE_PARAMS & sliceParams,
240 SliceTileInfo &sliceTileInfo)
241 {
242 if (sliceTileInfo.numTiles > 1)
243 {
244 if (!picParams.entropy_coding_sync_enabled_flag)
245 {
246 DECODE_CHK_COND(sliceTileInfo.numTiles != (sliceParams.num_entry_point_offsets + 1),
247 "tiles number does not equal to current num_entry_point_offsets.");
248 }
249 }
250
251 uint32_t* entryPointOffsets = nullptr;
252 if (m_basicFeature->m_hevcSubsetParams != nullptr)
253 {
254 auto hevcSubsetParams = m_basicFeature->m_hevcSubsetParams;
255 entryPointOffsets = &hevcSubsetParams->entry_point_offset_minus1[sliceParams.EntryOffsetToSubsetArray];
256 }
257
258 uint16_t tileX = sliceTileInfo.sliceTileX;
259 uint16_t tileY = sliceTileInfo.sliceTileY;
260 uint32_t bsdOffset = 0;
261
262 for (uint16_t i = 0; i < sliceTileInfo.numTiles; i++)
263 {
264 sliceTileInfo.tileArrayBuf[i].tileX = tileX;
265 sliceTileInfo.tileArrayBuf[i].tileY = tileY;
266 sliceTileInfo.tileArrayBuf[i].ctbX = GetTileCtbX(tileX);
267 sliceTileInfo.tileArrayBuf[i].ctbY = GetTileCtbY(tileY);
268 sliceTileInfo.tileArrayBuf[i].bsdOffset = bsdOffset;
269
270 if (i == 0)
271 {
272 sliceTileInfo.tileArrayBuf[i].bsdLength = sliceParams.ByteOffsetToSliceData +
273 sliceParams.NumEmuPrevnBytesInSliceHdr;
274 sliceTileInfo.tileArrayBuf[i].bsdLength += (entryPointOffsets != nullptr) ? entryPointOffsets[i] + 1 : 1;
275 }
276 else if (i == sliceTileInfo.numTiles - 1)
277 {
278 sliceTileInfo.tileArrayBuf[i].bsdLength = sliceParams.slice_data_size -
279 sliceTileInfo.tileArrayBuf[i].bsdOffset;
280 }
281 else
282 {
283 sliceTileInfo.tileArrayBuf[i].bsdLength = (entryPointOffsets != nullptr) ? entryPointOffsets[i] + 1 : 1;
284 }
285
286 // Check BSD data length
287 DECODE_CHK_COND(sliceTileInfo.tileArrayBuf[i].bsdLength > sliceParams.slice_data_size, "Slice tile bsd length exceeds slice data size!");
288
289 bsdOffset += sliceTileInfo.tileArrayBuf[i].bsdLength;
290
291 if (++tileX > picParams.num_tile_columns_minus1)
292 {
293 tileX = 0;
294 ++tileY;
295 }
296 }
297
298 return MOS_STATUS_SUCCESS;
299 }
300
RsToTsAddrConvert(const CODEC_HEVC_PIC_PARAMS & picParams,uint32_t picSizeInCtbsY)301 MOS_STATUS HevcTileCoding::RsToTsAddrConvert(const CODEC_HEVC_PIC_PARAMS &picParams, uint32_t picSizeInCtbsY)
302 {
303 uint32_t tbX = 0;
304 uint32_t tbY = 0;
305 uint32_t ctbAddrRs = 0;
306 uint32_t colBd[HEVC_NUM_MAX_TILE_COLUMN + 1] = {0};
307 uint32_t rowBd[HEVC_NUM_MAX_TILE_ROW + 1] = {0};
308 uint32_t colWidth[HEVC_NUM_MAX_TILE_COLUMN + 1] = {0};
309 uint32_t rowHeight[HEVC_NUM_MAX_TILE_ROW + 1] = {0};
310 uint8_t i = 0, j = 0;
311
312 if (picParams.tiles_enabled_flag && picParams.uniform_spacing_flag)
313 {
314 for (i = 0; i <= picParams.num_tile_columns_minus1; i++)
315 {
316 colWidth[i] = ((i + 1) * m_basicFeature->m_widthInCtb) / (picParams.num_tile_columns_minus1 + 1) -
317 (i * m_basicFeature->m_widthInCtb) / (picParams.num_tile_columns_minus1 + 1);
318 }
319
320 for (j = 0; j <= picParams.num_tile_rows_minus1; j++)
321 {
322 rowHeight[j] = ((j + 1) * m_basicFeature->m_heightInCtb) / (picParams.num_tile_rows_minus1 + 1) -
323 (j * m_basicFeature->m_heightInCtb) / (picParams.num_tile_rows_minus1 + 1);
324 }
325 }
326 else
327 {
328 colWidth[picParams.num_tile_columns_minus1] = m_basicFeature->m_widthInCtb;
329 for (i = 0; i < picParams.num_tile_columns_minus1; i++)
330 {
331 colWidth[i] = picParams.column_width_minus1[i] + 1;
332 colWidth[picParams.num_tile_columns_minus1] -= colWidth[i];
333 }
334
335 rowHeight[picParams.num_tile_rows_minus1] = m_basicFeature->m_heightInCtb;
336 for (j = 0; j < picParams.num_tile_rows_minus1; j++)
337 {
338 rowHeight[j] = picParams.row_height_minus1[j] + 1;
339 rowHeight[picParams.num_tile_rows_minus1] -= rowHeight[j];
340 }
341 }
342
343 /* The list colBd[i] for i ranging from 0 to num_tile_columns_minus1 + 1, inclusive,
344 * specifying the location of the i-th tile column boundary in units of CTBs */
345 for (colBd[0] = 0, i = 0; i <= picParams.num_tile_columns_minus1; i ++)
346 {
347 colBd[i + 1] = colBd[i] + colWidth[i];
348 }
349
350 /* The list rowBd[j] for j ranging from 0 to num_tile_rows_minus1 + 1, inclusive,
351 * specifying the location of the j-th tile row boundary in units of CTBs */
352 for (rowBd[0] = 0, j = 0; j <= picParams.num_tile_rows_minus1; j ++)
353 {
354 rowBd[j + 1] = rowBd[j] + rowHeight[j];
355 }
356
357 /* The list CtbAddrRsToTs[ctbAddrRs] for ctbAddrRs ranging from 0 to PicSizeInCtbsY - 1, inclusive,
358 * specifying the conversion from a CTB address in CTB raster scan of a picture to a CTB address in tile scan */
359 uint16_t tileX = 0, tileY = 0;
360 for (ctbAddrRs = 0; ctbAddrRs < picSizeInCtbsY; ctbAddrRs++)
361 {
362 tbX = ctbAddrRs % m_basicFeature->m_widthInCtb;
363 tbY = ctbAddrRs / m_basicFeature->m_widthInCtb;
364
365 for (j = 0; j <= picParams.num_tile_rows_minus1; j++)
366 {
367 if (tbY >= rowBd[j])
368 {
369 tileY = j;
370 }
371 }
372
373 for (i = 0; i <= picParams.num_tile_columns_minus1; i++)
374 {
375 if (tbX >= colBd[i])
376 {
377 tileX = i;
378 }
379 }
380
381 m_pCtbAddrRsToTs[ctbAddrRs] = 0;
382 for (i = 0; i < tileX; i++)
383 {
384 m_pCtbAddrRsToTs[ctbAddrRs] += rowHeight[tileY] * colWidth[i];
385 }
386 for (j = 0; j < tileY; j++)
387 {
388 m_pCtbAddrRsToTs[ctbAddrRs] += m_basicFeature->m_widthInCtb * rowHeight[j];
389 }
390
391 m_pCtbAddrRsToTs[ctbAddrRs] += (tbY - rowBd[tileY]) * colWidth[tileX] + tbX - colBd[tileX];
392 }
393
394 return MOS_STATUS_SUCCESS;
395 }
396
GetSliceTileX(uint32_t sliceIndex)397 uint16_t HevcTileCoding::GetSliceTileX(uint32_t sliceIndex)
398 {
399 if (sliceIndex >= m_sliceTileInfoList.size())
400 {
401 return 0;
402 }
403 return m_sliceTileInfoList[sliceIndex]->sliceTileX;
404 }
405
GetSliceTileY(uint32_t sliceIndex)406 uint16_t HevcTileCoding::GetSliceTileY(uint32_t sliceIndex)
407 {
408 if (sliceIndex >= m_sliceTileInfoList.size())
409 {
410 return 0;
411 }
412 return m_sliceTileInfoList[sliceIndex]->sliceTileY;
413 }
414
AllocateSliceTileInfo(uint32_t sliceIndex)415 HevcTileCoding::SliceTileInfo* HevcTileCoding::AllocateSliceTileInfo(uint32_t sliceIndex)
416 {
417 SliceTileInfo* sliceTileInfo;
418 if (sliceIndex < m_sliceTileInfoList.size())
419 {
420 sliceTileInfo = m_sliceTileInfoList[sliceIndex];
421 DECODE_ASSERT(sliceTileInfo != nullptr);
422
423 sliceTileInfo->sliceTileX = 0;
424 sliceTileInfo->sliceTileY = 0;
425 sliceTileInfo->firstSliceOfTile = false;
426 sliceTileInfo->lastSliceOfTile = false;
427 sliceTileInfo->origCtbX = 0;
428 sliceTileInfo->origCtbY = 0;
429 sliceTileInfo->numTiles = 0;
430 }
431 else
432 {
433 sliceTileInfo = MOS_New(SliceTileInfo);
434 if (sliceTileInfo != nullptr)
435 {
436 MOS_ZeroMemory(sliceTileInfo, sizeof(SliceTileInfo));
437 m_sliceTileInfoList.push_back(sliceTileInfo);
438 }
439 }
440 return sliceTileInfo;
441 }
442
GetAllTileInfo(const CODEC_HEVC_PIC_PARAMS & picParams,uint32_t widthInCtb,uint32_t heightInCtb)443 MOS_STATUS HevcTileCoding::GetAllTileInfo(const CODEC_HEVC_PIC_PARAMS & picParams,
444 uint32_t widthInCtb, uint32_t heightInCtb)
445 {
446 DECODE_FUNC_CALL();
447
448 if (picParams.uniform_spacing_flag == 1)
449 {
450 for (auto i = 0; i <= picParams.num_tile_columns_minus1; i++)
451 {
452 m_tileColWidth[i] = ((i + 1) * widthInCtb) / (picParams.num_tile_columns_minus1 + 1) -
453 (i * widthInCtb) / (picParams.num_tile_columns_minus1 + 1);
454 }
455
456 for (auto i = 0; i <= picParams.num_tile_rows_minus1; i++)
457 {
458 m_tileRowHeight[i] = ((i + 1) * heightInCtb) / (picParams.num_tile_rows_minus1 + 1) -
459 (i * heightInCtb) / (picParams.num_tile_rows_minus1 + 1);
460 }
461 }
462 else
463 {
464 m_tileColWidth[picParams.num_tile_columns_minus1] = widthInCtb & 0xffff;
465 for (auto i = 0; i < picParams.num_tile_columns_minus1; i++)
466 {
467 m_tileColWidth[i] = picParams.column_width_minus1[i] + 1;
468 m_tileColWidth[picParams.num_tile_columns_minus1] -= m_tileColWidth[i];
469 }
470
471 m_tileRowHeight[picParams.num_tile_rows_minus1] = heightInCtb & 0xffff;
472 for (auto i = 0; i < picParams.num_tile_rows_minus1; i++)
473 {
474 m_tileRowHeight[i] = picParams.row_height_minus1[i] + 1;
475 m_tileRowHeight[picParams.num_tile_rows_minus1] -= m_tileRowHeight[i];
476 }
477 }
478
479 return MOS_STATUS_SUCCESS;
480 }
481
GetTileColWidth()482 const uint16_t *HevcTileCoding::GetTileColWidth()
483 {
484 return m_tileColWidth;
485 }
486
GetTileRowHeight()487 const uint16_t *HevcTileCoding::GetTileRowHeight()
488 {
489 return m_tileRowHeight;
490 }
491
GetSliceTileInfo(uint32_t sliceIndex)492 const HevcTileCoding::SliceTileInfo *HevcTileCoding::GetSliceTileInfo(uint32_t sliceIndex)
493 {
494 if (sliceIndex >= m_sliceTileInfoList.size())
495 {
496 return nullptr;
497 }
498 return m_sliceTileInfoList[sliceIndex];
499 }
500
ComputeSliceTileX(const CODEC_HEVC_PIC_PARAMS & picParams,const CODEC_HEVC_SLICE_PARAMS & slc)501 uint16_t HevcTileCoding::ComputeSliceTileX(const CODEC_HEVC_PIC_PARAMS & picParams,
502 const CODEC_HEVC_SLICE_PARAMS & slc)
503 {
504 DECODE_FUNC_CALL();
505
506 uint16_t ctbX, ctbStart = 0;
507
508 ctbX = slc.slice_segment_address % m_basicFeature->m_widthInCtb;
509 for (uint16_t i = 0; i <= picParams.num_tile_columns_minus1; i++)
510 {
511 if (ctbX >= ctbStart && ctbX < ctbStart + m_tileColWidth[i])
512 {
513 return i;
514 }
515 ctbStart += m_tileColWidth[i];
516 }
517 return 0;
518 }
519
ComputeSliceTileY(const CODEC_HEVC_PIC_PARAMS & picParams,const CODEC_HEVC_SLICE_PARAMS & slc)520 uint16_t HevcTileCoding::ComputeSliceTileY(const CODEC_HEVC_PIC_PARAMS & picParams,
521 const CODEC_HEVC_SLICE_PARAMS & slc)
522 {
523 DECODE_FUNC_CALL();
524
525 uint32_t ctbY, ctbStart = 0;
526
527 ctbY = slc.slice_segment_address / m_basicFeature->m_widthInCtb;
528 for (uint16_t i = 0; i <= picParams.num_tile_rows_minus1; i++)
529 {
530 if (ctbY >= ctbStart && ctbY < ctbStart + m_tileRowHeight[i])
531 {
532 return i;
533 }
534 ctbStart += m_tileRowHeight[i];
535 }
536 return 0;
537 }
538
ComputeTileNumForSlice(const CODEC_HEVC_PIC_PARAMS & picParams,uint32_t sliceIdx,uint16_t sliceTileX,uint16_t sliceTileY,bool lastSlice)539 uint16_t HevcTileCoding::ComputeTileNumForSlice(const CODEC_HEVC_PIC_PARAMS & picParams,
540 uint32_t sliceIdx,
541 uint16_t sliceTileX,
542 uint16_t sliceTileY,
543 bool lastSlice)
544 {
545 uint16_t numTiles;
546 if (lastSlice)
547 {
548 numTiles = (picParams.num_tile_columns_minus1 + 1) *
549 (picParams.num_tile_rows_minus1 + 1 - sliceTileY) - sliceTileX;
550 }
551 else
552 {
553 uint32_t nextTileX = GetSliceTileX(sliceIdx + 1);
554 uint32_t nextTileY = GetSliceTileY(sliceIdx + 1);
555 numTiles = (picParams.num_tile_columns_minus1 + 1) * (nextTileY - sliceTileY) +
556 nextTileX - sliceTileX;
557 }
558 return numTiles;
559 }
560
GetTileCtbX(uint16_t col)561 uint16_t HevcTileCoding::GetTileCtbX(uint16_t col)
562 {
563 DECODE_FUNC_CALL();
564
565 uint16_t ctbX = 0;
566 for (uint16_t i = 0; i < col; i++)
567 {
568 ctbX += m_tileColWidth[i];
569 }
570 return ctbX;
571 }
572
GetTileCtbY(uint16_t row)573 uint16_t HevcTileCoding::GetTileCtbY(uint16_t row)
574 {
575 DECODE_FUNC_CALL();
576
577 uint16_t ctbY = 0;
578 for (uint16_t i = 0; i < row; i++)
579 {
580 ctbY += m_tileRowHeight[i];
581 }
582 return ctbY;
583 }
584
585 }
586