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_av1_tile_coding_g12.cpp 24 //! \brief Defines the common interface for av1 decode tile coding 25 //! 26 27 #include "decode_av1_tile_coding_g12.h" 28 #include "decode_av1_basic_feature_g12.h" 29 #include "codec_def_common.h" 30 #include "mhw_vdbox_avp_g12_X.h" 31 #include "decode_pipeline.h" 32 33 namespace decode 34 { ~Av1DecodeTileG12()35 Av1DecodeTileG12::~Av1DecodeTileG12() 36 { 37 // tile descriptors 38 if (m_tileDesc) 39 { 40 free(m_tileDesc); 41 m_tileDesc = nullptr; 42 } 43 } 44 Init(Av1BasicFeatureG12 * basicFeature,CodechalSetting * codecSettings)45 MOS_STATUS Av1DecodeTileG12::Init(Av1BasicFeatureG12 *basicFeature, CodechalSetting *codecSettings) 46 { 47 DECODE_FUNC_CALL(); 48 DECODE_CHK_NULL(basicFeature); 49 DECODE_CHK_NULL(codecSettings); 50 51 m_basicFeature = basicFeature; 52 53 return MOS_STATUS_SUCCESS; 54 } 55 Update(CodecAv1PicParams & picParams,CodecAv1TileParams * tileParams)56 MOS_STATUS Av1DecodeTileG12::Update(CodecAv1PicParams & picParams, 57 CodecAv1TileParams *tileParams) 58 { 59 DECODE_FUNC_CALL(); 60 61 // Initialize state params for multiple tiles 62 if (m_newFrameStart) 63 { 64 m_lastTileId = -1; 65 m_curTile = -1; 66 m_tileStartOffset = 0; 67 m_firstTileInTg = 0; 68 m_tileGroupId = -1; 69 m_isTruncatedTile = false; 70 m_decPassNum = 1; 71 m_hasTileMissing = false; 72 m_hasDuplicateTile = false; 73 } 74 75 if (m_numTiles > av1MaxTileNum) 76 { 77 DECODE_ASSERTMESSAGE("Tile number exceeds the max supported number %d!", av1MaxTileNum); 78 return MOS_STATUS_INVALID_PARAMETER; 79 } 80 81 if (picParams.m_tileCols > av1MaxTileColumn || picParams.m_tileRows > av1MaxTileRow) 82 { 83 DECODE_NORMALMESSAGE("Invalid tile row/col."); 84 return MOS_STATUS_INVALID_PARAMETER; 85 } 86 87 uint16_t tileNumLimit = (picParams.m_picInfoFlags.m_fields.m_largeScaleTile) ? av1MaxTileNum : (picParams.m_tileCols * picParams.m_tileRows); 88 if (nullptr != m_tileDesc) 89 { 90 if (m_prevFrmTileNum < tileNumLimit) 91 { 92 free(m_tileDesc); 93 m_tileDesc = nullptr; 94 } 95 else 96 { 97 memset(m_tileDesc, 0, (sizeof(TileDesc) * m_prevFrmTileNum)); 98 } 99 } 100 if (nullptr == m_tileDesc) 101 { 102 m_tileDesc = (TileDesc *)malloc(sizeof(TileDesc) * tileNumLimit); 103 if (nullptr != m_tileDesc) 104 { 105 memset(m_tileDesc, 0, (sizeof(TileDesc) * tileNumLimit)); 106 } 107 } 108 m_prevFrmTileNum = tileNumLimit; 109 110 //Calculate tile info for max tile 111 DECODE_CHK_STATUS(CalcTileInfoMaxTile(picParams)); 112 113 return MOS_STATUS_SUCCESS; 114 } 115 ErrorDetectAndConceal()116 MOS_STATUS Av1DecodeTileG12::ErrorDetectAndConceal() 117 { 118 DECODE_FUNC_CALL() 119 DECODE_CHK_NULL(m_tileDesc); 120 uint64_t datasize = 0; 121 122 // detect if any tile missing 123 if (m_numTiles < m_totalTileNum) 124 { 125 if (!m_hasTileMissing) 126 { 127 m_hasTileMissing = true; 128 } 129 } 130 131 // make sure the last tile equals to m_totalTileNum-1 132 if (m_hasTileMissing) 133 { 134 if (m_lastTileId != m_totalTileNum - 1) 135 { 136 m_lastTileId = m_totalTileNum - 1; 137 m_newFrameStart = true; 138 } 139 } 140 141 // Error Concealment for Tile size 142 // m_numTiles means the tile number from application 143 // m_totalTileNum means the total number of tile, m_lastTileId means the last tile index 144 for (uint32_t i = 0; i < m_totalTileNum; i++) 145 { 146 // m_tileDesc[i].m_size + m_tileDesc[i].m_offset could oversize the maximum of uint32_t 147 datasize = (uint64_t)m_tileDesc[i].m_size + (uint64_t)m_tileDesc[i].m_offset; 148 if (datasize > m_basicFeature->m_dataSize) 149 { 150 if (i == m_lastTileId) 151 { 152 if (m_basicFeature->m_dataSize > m_tileDesc[i].m_offset) 153 { 154 m_tileDesc[i].m_size = m_basicFeature->m_dataSize - m_tileDesc[i].m_offset; 155 DECODE_ASSERTMESSAGE("The last tile size is oversize, the remaining size is %d\n", m_tileDesc[i].m_size); 156 } 157 else 158 { 159 m_tileDesc[i].m_size = 0; 160 DECODE_ASSERTMESSAGE("The last tile size is invalid, take current tile as missing tile and then set 4 byte dummy WL!!"); 161 } 162 } 163 else 164 { 165 m_tileDesc[i].m_size = 0; 166 DECODE_ASSERTMESSAGE("The non-last tile size is oversize, take current tile as missing tile and then set 4 byte dummy WL!\n"); 167 } 168 } 169 // For tile missing scenario 170 if (m_tileDesc[i].m_size == 0) 171 { 172 DECODE_ASSERTMESSAGE("The %d tile is missing, set 4 byte dummy WL!\n", i); 173 m_tileDesc[i].m_size = 4; 174 m_tileDesc[i].m_offset = 0; 175 m_tileDesc[i].m_tileRow = i / m_basicFeature->m_av1PicParams->m_tileCols; 176 m_tileDesc[i].m_tileColumn = i % m_basicFeature->m_av1PicParams->m_tileCols; 177 } 178 } 179 return MOS_STATUS_SUCCESS; 180 } 181 ParseTileInfo(const CodecAv1PicParams & picParams,CodecAv1TileParams * tileParams)182 MOS_STATUS Av1DecodeTileG12::ParseTileInfo(const CodecAv1PicParams & picParams, CodecAv1TileParams *tileParams) 183 { 184 DECODE_FUNC_CALL(); 185 186 DECODE_CHK_NULL(m_tileDesc); 187 m_totalTileNum = (picParams.m_picInfoFlags.m_fields.m_largeScaleTile) ? 188 (picParams.m_tileCountMinus1 + 1) : picParams.m_tileRows * picParams.m_tileCols; 189 190 int16_t tileId = 0; 191 int16_t tileGroupId = -1; 192 int16_t lastStartTileIdx = -1; 193 for (uint32_t i = 0; i < m_numTiles; i++) 194 { 195 DECODE_ASSERT(tileParams[i].m_badBSBufferChopping == 0);//this is to assume the whole tile is in one single bitstream buffer 196 DECODE_ASSERT(tileParams[i].m_bsTileBytesInBuffer == tileParams[i].m_bsTilePayloadSizeInBytes);//this is to assume the whole tile is in one single bitstream buffer 197 198 // Check invalid tile column and tile row 199 if (tileParams[i].m_tileColumn > picParams.m_tileCols || tileParams[i].m_tileRow > picParams.m_tileRows) 200 { 201 DECODE_ASSERTMESSAGE("Invalid tile column or tile row\n"); 202 return MOS_STATUS_INVALID_PARAMETER; 203 } 204 205 if (!picParams.m_picInfoFlags.m_fields.m_largeScaleTile) 206 { 207 //record info 208 if (tileParams[i].m_startTileIdx != lastStartTileIdx) 209 { 210 tileGroupId++; 211 } 212 lastStartTileIdx = tileParams[i].m_startTileIdx; 213 tileId = tileParams[i].m_tileColumn + tileParams[i].m_tileRow * picParams.m_tileCols; 214 if (tileParams[i].m_badBSBufferChopping == 0 || tileParams[i].m_badBSBufferChopping == 2)//if all tile data received 215 { 216 m_lastTileId = tileId;//record the last tile ID whose bitstream is available for HW to decode 217 } 218 } 219 220 // check duplicate tile 221 auto index = (picParams.m_picInfoFlags.m_fields.m_largeScaleTile) ? i : tileId; 222 if (m_tileDesc[index].m_tileIndexCount > 0 ) 223 { 224 if (tileParams[i].m_bsTileBytesInBuffer > m_tileDesc[index].m_size) 225 { 226 m_tileDesc[index].m_offset = tileParams[i].m_bsTileDataLocation; 227 m_tileDesc[index].m_size = tileParams[i].m_bsTileBytesInBuffer; 228 } 229 m_tileDesc[index].m_tileIndexCount++; 230 m_hasDuplicateTile = true; 231 } 232 else 233 { 234 m_tileDesc[index].m_offset = tileParams[i].m_bsTileDataLocation; 235 m_tileDesc[index].m_size = tileParams[i].m_bsTileBytesInBuffer; 236 m_tileDesc[index].m_tileRow = tileParams[i].m_tileRow; 237 m_tileDesc[index].m_tileColumn = tileParams[i].m_tileColumn; 238 m_tileDesc[index].m_tileIndexCount++; 239 } 240 241 if (!picParams.m_picInfoFlags.m_fields.m_largeScaleTile) 242 { 243 m_tileDesc[index].m_tileGroupId = (uint16_t)tileGroupId; 244 m_tileDesc[index].m_lastInGroup = (tileId == tileParams[i].m_endTileIdx) ? true : false; 245 m_tileDesc[index].m_tileNum = tileId - tileParams[i].m_startTileIdx; 246 } 247 else 248 { 249 //No TG for ext-tile, set TG related params to 0 250 m_tileDesc[index].m_tileGroupId = 0; 251 m_tileDesc[index].m_lastInGroup = 0; 252 m_tileDesc[index].m_tileNum = 0; 253 254 //ext-tile specific params 255 m_tileDesc[index].m_tileIndex = tileParams[i].m_tileIndex; 256 m_tileDesc[index].m_anchorFrameIdx = tileParams[i].m_anchorFrameIdx.FrameIdx; 257 } 258 } 259 260 if ((m_lastTileId + 1) == m_totalTileNum) 261 { 262 m_newFrameStart = true; 263 } 264 else 265 { 266 m_newFrameStart = false; 267 } 268 269 // Do error detection and concealment 270 DECODE_CHK_STATUS(ErrorDetectAndConceal()); 271 272 return MOS_STATUS_SUCCESS; 273 } 274 CalculateTileCols(CodecAv1PicParams & picParams)275 MOS_STATUS Av1DecodeTileG12::CalculateTileCols(CodecAv1PicParams & picParams) 276 { 277 DECODE_FUNC_CALL(); 278 279 int32_t mibSizeLog2 = picParams.m_seqInfoFlags.m_fields.m_use128x128Superblock ? av1MaxMibSizeLog2 : av1MinMibSizeLog2; 280 int32_t miCols = MOS_ALIGN_CEIL(m_miCols, 1 << mibSizeLog2); 281 int32_t sbCols = miCols >> mibSizeLog2; 282 283 //calc tile col start for all the tiles except the last one 284 uint16_t i, start_sb = 0; 285 for (i = 0, start_sb = 0; i < picParams.m_tileCols - 1; i++) 286 { 287 m_tileColStartSb[i] = start_sb;//calc tile col start 288 start_sb += picParams.m_widthInSbsMinus1[i] + 1; 289 } 290 291 //calc for the last tile 292 m_tileColStartSb[i] = start_sb; 293 DECODE_CHK_COND(sbCols < (start_sb + 1), "Invalid tile col start of the last tile"); 294 picParams.m_widthInSbsMinus1[i] = sbCols - start_sb - 1; 295 296 return MOS_STATUS_SUCCESS; 297 } 298 CalculateTileRows(CodecAv1PicParams & picParams)299 MOS_STATUS Av1DecodeTileG12::CalculateTileRows(CodecAv1PicParams &picParams) 300 { 301 DECODE_FUNC_CALL(); 302 303 int32_t mibSizeLog2 = picParams.m_seqInfoFlags.m_fields.m_use128x128Superblock ? av1MaxMibSizeLog2 : av1MinMibSizeLog2; 304 int32_t miRows = MOS_ALIGN_CEIL(m_miRows, 1 << mibSizeLog2); 305 int32_t sbRows = miRows >> mibSizeLog2; 306 307 //calc tile row start for all the tiles except the last one 308 uint16_t i, start_sb; 309 for (i = 0, start_sb = 0; i < picParams.m_tileRows - 1; i++) 310 { 311 m_tileRowStartSb[i] = start_sb;//calc tile Row start 312 start_sb += picParams.m_heightInSbsMinus1[i] + 1; 313 } 314 315 //calc for the last tile 316 m_tileRowStartSb[i] = start_sb; 317 DECODE_CHK_COND(sbRows < (start_sb + 1), "Invalid tile row start of the last tile"); 318 picParams.m_heightInSbsMinus1[i] = sbRows - start_sb - 1; 319 320 return MOS_STATUS_SUCCESS; 321 } 322 CalcTileInfoMaxTile(CodecAv1PicParams & picParams)323 MOS_STATUS Av1DecodeTileG12::CalcTileInfoMaxTile(CodecAv1PicParams &picParams) 324 { 325 DECODE_FUNC_CALL(); 326 327 m_miCols = MOS_ALIGN_CEIL(picParams.m_frameWidthMinus1 + 1, 8) >> av1MiSizeLog2; 328 m_miRows = MOS_ALIGN_CEIL(picParams.m_frameHeightMinus1 + 1, 8) >> av1MiSizeLog2; 329 DECODE_CHK_STATUS(CalculateTileCols(picParams)); 330 DECODE_CHK_STATUS(CalculateTileRows(picParams)); 331 332 return MOS_STATUS_SUCCESS; 333 } 334 CalcNumPass(const CodecAv1PicParams & picParams,CodecAv1TileParams * tileParams)335 MOS_STATUS Av1DecodeTileG12::CalcNumPass(const CodecAv1PicParams &picParams, CodecAv1TileParams *tileParams) 336 { 337 DECODE_FUNC_CALL(); 338 339 uint16_t passNum; 340 uint16_t startTile = m_lastTileId + 1;//record before parsing new bitstream portion 341 342 DECODE_CHK_STATUS(ParseTileInfo(picParams, tileParams)); 343 344 if (picParams.m_picInfoFlags.m_fields.m_largeScaleTile) 345 { 346 passNum = picParams.m_tileCountMinus1 + 1; 347 m_curTile = 0; 348 } 349 else 350 { 351 passNum = m_lastTileId - startTile + 1; 352 m_curTile = startTile; 353 } 354 355 // Check invalid tile num 356 if (passNum < 1) 357 { 358 DECODE_ASSERTMESSAGE("valid tile doesn't exist in bitstream\n"); 359 return MOS_STATUS_MORE_DATA; 360 } 361 362 m_decPassNum = passNum; 363 return MOS_STATUS_SUCCESS; 364 } 365 GetUpscaleConvolveStepX0(const CodecAv1PicParams & picParams,bool isChroma)366 void Av1DecodeTileG12::GetUpscaleConvolveStepX0(const CodecAv1PicParams &picParams, bool isChroma) 367 { 368 DECODE_FUNC_CALL(); 369 370 int32_t ssX = isChroma && picParams.m_seqInfoFlags.m_fields.m_subsamplingX; 371 int32_t downscaledPlaneWidth = ROUND_POWER_OF_TWO(picParams.m_frameWidthMinus1 + 1, ssX); 372 int32_t upscaledPlaneWidth = ROUND_POWER_OF_TWO(picParams.m_superResUpscaledWidthMinus1 + 1, ssX); 373 374 //calculate step 375 int32_t xStepQn = ((downscaledPlaneWidth << av1RsScaleSubpelBits) + upscaledPlaneWidth / 2) / upscaledPlaneWidth; 376 if (isChroma) 377 { 378 m_chromaXStepQn = xStepQn; 379 } 380 else 381 { 382 m_lumaXStepQn = xStepQn; 383 } 384 385 //Calculate x0_qn for each tile column 386 int32_t err = upscaledPlaneWidth * xStepQn - (downscaledPlaneWidth << av1RsScaleSubpelBits); 387 int32_t x0 = 388 (-((upscaledPlaneWidth - downscaledPlaneWidth) << (av1RsScaleSubpelBits - 1)) + 389 upscaledPlaneWidth / 2) / 390 upscaledPlaneWidth + 391 av1RsScaleExtraOff - err / 2; 392 x0 = (int32_t)((uint32_t)x0 & av1RsScaleSubpelMask); 393 394 if (picParams.m_tileCols > 64) 395 { 396 DECODE_ASSERTMESSAGE("Array index exceeds upper bound."); 397 return; 398 } 399 400 for (auto col = 0; col < picParams.m_tileCols; col++) 401 { 402 if (isChroma) 403 { 404 m_chromaX0Qn[col] = x0; 405 } 406 else 407 { 408 m_lumaX0Qn[col] = x0; 409 } 410 411 int32_t tileColEndSb; 412 if (col < picParams.m_tileCols - 1) 413 { 414 tileColEndSb = m_tileColStartSb[col + 1]; 415 } 416 else 417 { 418 tileColEndSb = m_tileColStartSb[picParams.m_tileCols - 1] + picParams.m_widthInSbsMinus1[picParams.m_tileCols - 1]; 419 420 } 421 int32_t mibSizeLog2 = picParams.m_seqInfoFlags.m_fields.m_use128x128Superblock ? av1MaxMibSizeLog2 : av1MinMibSizeLog2; 422 423 int32_t miColEnd = tileColEndSb << mibSizeLog2; 424 miColEnd = AOMMIN(miColEnd, m_miCols); 425 int32_t downscaledX1 = miColEnd << (av1MiSizeLog2 - ssX); 426 int32_t downscaledX0 = m_tileColStartSb[col] << mibSizeLog2 << (av1MiSizeLog2 - ssX); 427 428 int32_t srcWidth = downscaledX1 - downscaledX0; 429 int32_t upscaledX0 = (downscaledX0 * picParams.m_superresScaleDenominator) / av1ScaleNumerator; 430 int32_t upscaledX1; 431 if (col == picParams.m_tileCols - 1) 432 { 433 upscaledX1 = upscaledPlaneWidth; 434 } 435 else 436 { 437 upscaledX1 = (downscaledX1 * picParams.m_superresScaleDenominator) / av1ScaleNumerator; 438 } 439 int32_t dstWidth = upscaledX1 - upscaledX0; 440 441 // Update the fractional pixel offset to prepare for the next tile column. 442 x0 += (dstWidth * xStepQn) - (srcWidth << av1RsScaleSubpelBits); 443 } 444 } 445 446 } // namespace decode 447