1 /* 2 * Copyright (c) 2019, 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_av1_stream_in.cpp 24 //! \brief Defines the common interface for encode av1 stream in utility 25 //! 26 27 #include "encode_av1_stream_in.h" 28 #include "encode_tile.h" 29 #include "encode_av1_basic_feature.h" 30 #include "mos_solo_generic.h" 31 32 namespace encode 33 { ~Av1StreamIn()34 Av1StreamIn::~Av1StreamIn() 35 { 36 ENCODE_FUNC_CALL(); 37 if (m_LcuMap != nullptr) 38 { 39 MOS_FreeMemory(m_LcuMap); 40 } 41 42 MOS_SafeFreeMemory(m_streamInTemp); 43 } 44 SetCommonParams(uint8_t tu,CommonStreamInParams & params)45 static void SetCommonParams(uint8_t tu, CommonStreamInParams& params) 46 { 47 params.MaxCuSize = 3; 48 params.MaxTuSize = 3; 49 switch (tu) 50 { 51 case 2: 52 params.NumImePredictors = 12; 53 params.NumMergeCandidateCu8x8 = 3; 54 params.NumMergeCandidateCu16x16 = 3; 55 params.NumMergeCandidateCu32x32 = 3; 56 params.NumMergeCandidateCu64x64 = 3; 57 break; 58 case 4: 59 params.NumImePredictors = 8; 60 params.NumMergeCandidateCu8x8 = 2; 61 params.NumMergeCandidateCu16x16 = 2; 62 params.NumMergeCandidateCu32x32 = 3; 63 params.NumMergeCandidateCu64x64 = 3; 64 break; 65 case 7: 66 params.NumImePredictors = 4; 67 params.NumMergeCandidateCu8x8 = 2; 68 params.NumMergeCandidateCu16x16 = 1; 69 params.NumMergeCandidateCu32x32 = 2; 70 params.NumMergeCandidateCu64x64 = 2; 71 break; 72 default: 73 MHW_ASSERTMESSAGE("Invalid TU provided!"); 74 } 75 } 76 Init(Av1BasicFeature * basicFeature,EncodeAllocator * allocator,PMOS_INTERFACE osInterface)77 MOS_STATUS Av1StreamIn::Init(Av1BasicFeature *basicFeature, EncodeAllocator *allocator, PMOS_INTERFACE osInterface) 78 { 79 ENCODE_FUNC_CALL(); 80 m_basicFeature = basicFeature; 81 ENCODE_CHK_NULL_RETURN(m_basicFeature); 82 ENCODE_CHK_NULL_RETURN(m_basicFeature->m_av1PicParams); 83 ENCODE_CHK_NULL_RETURN(m_basicFeature->m_recycleBuf); 84 m_allocator = allocator; 85 ENCODE_CHK_NULL_RETURN(m_allocator); 86 m_osInterface = osInterface; 87 ENCODE_CHK_NULL_RETURN(m_osInterface); 88 89 SetCommonParams(m_basicFeature->m_targetUsage, m_commonPar); 90 91 if (!m_initialized || m_basicFeature->m_resolutionChanged) 92 { 93 MOS_ALLOC_GFXRES_PARAMS allocParams; 94 MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS)); 95 allocParams.Type = MOS_GFXRES_BUFFER; 96 allocParams.TileType = MOS_TILE_LINEAR; 97 allocParams.Format = Format_Buffer; 98 99 auto CurFrameWidth = m_basicFeature->m_av1PicParams->frame_width_minus1 + 1; 100 auto CurFrameHeight = m_basicFeature->m_av1PicParams->frame_height_minus1 + 1; 101 102 allocParams.dwBytes = (MOS_ALIGN_CEIL(CurFrameWidth, 64) / m_streamInBlockSize) * 103 (MOS_ALIGN_CEIL(CurFrameHeight, 64) / m_streamInBlockSize) * CODECHAL_CACHELINE_SIZE; 104 105 m_streamInSize = allocParams.dwBytes; 106 m_streamInTemp = (uint8_t *)MOS_AllocAndZeroMemory(m_streamInSize); 107 ENCODE_CHK_NULL_RETURN(m_streamInTemp); 108 109 allocParams.pBufName = "Av1 StreamIn Data Buffer"; 110 allocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_WRITE; 111 m_basicFeature->m_recycleBuf->RegisterResource(RecycleResId::StreamInBuffer, allocParams); 112 113 m_widthInLCU = MOS_ALIGN_CEIL(CurFrameWidth, 64) / 64; 114 m_heightInLCU = MOS_ALIGN_CEIL(CurFrameHeight, 64) / 64; 115 116 if (m_LcuMap != nullptr) 117 { 118 MOS_FreeMemory(m_LcuMap); 119 m_LcuMap = nullptr; 120 } 121 122 if (m_LcuMap == nullptr) 123 { 124 m_LcuMap = static_cast<uint32_t *>(MOS_AllocAndZeroMemory(m_widthInLCU * m_heightInLCU * sizeof(uint32_t))); 125 } 126 ENCODE_CHK_STATUS_RETURN(SetupLCUMap()); 127 m_initialized = true; 128 } 129 130 return MOS_STATUS_SUCCESS; 131 } 132 Update()133 MOS_STATUS Av1StreamIn::Update() 134 { 135 ENCODE_FUNC_CALL(); 136 if (!m_enabled) 137 { 138 ENCODE_CHK_NULL_RETURN(m_streamInTemp); 139 MOS_ZeroMemory(m_streamInTemp, m_streamInSize); 140 141 ENCODE_CHK_STATUS_RETURN(StreamInInit(m_streamInTemp)); 142 143 m_enabled = true; 144 } 145 return MOS_STATUS_SUCCESS; 146 } 147 CalculateTilesBoundary(PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams,uint32_t * rowBd,uint32_t * colBd)148 static MOS_STATUS 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 < av1PicParams->tile_cols; 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 < av1PicParams->tile_rows; 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 Reset()173 void Av1StreamIn::Reset() 174 { 175 ENCODE_FUNC_CALL(); 176 m_enabled = false; 177 } 178 GetLCUAddr(uint32_t x,uint32_t y) const179 uint32_t Av1StreamIn::GetLCUAddr(uint32_t x, uint32_t y) const 180 { 181 ENCODE_FUNC_CALL(); 182 183 PCODEC_AV1_ENCODE_PICTURE_PARAMS av1PicParams = 184 m_basicFeature->m_av1PicParams; 185 ENCODE_CHK_NULL_RETURN(av1PicParams); 186 187 uint32_t colBd[m_maxTileBdNum] = { 0 }; 188 uint32_t rowBd[m_maxTileBdNum] = { 0 }; 189 ENCODE_CHK_STATUS_RETURN(CalculateTilesBoundary(av1PicParams, &rowBd[0], &colBd[0])); 190 191 uint32_t tileX = 0, tileY = 0, CtbAddrRStoTS = 0; 192 for (auto j = 0; j < av1PicParams->tile_cols; j++) 193 { 194 if (x >= colBd[j]) 195 { 196 tileX = j; 197 } 198 } 199 200 for (auto k = 0; k < av1PicParams->tile_rows; k++) 201 { 202 if (y >= rowBd[k]) 203 { 204 tileY = k; 205 } 206 } 207 208 uint32_t widthinLCU = MOS_ROUNDUP_DIVIDE((av1PicParams->frame_width_minus1 +1), 64); 209 210 CtbAddrRStoTS = widthinLCU * rowBd[tileY] + (av1PicParams->height_in_sbs_minus_1[tileY] + 1) * colBd[tileX]; 211 CtbAddrRStoTS += (y - rowBd[tileY]) * (av1PicParams->width_in_sbs_minus_1[tileX] + 1 ) + x - colBd[tileX]; 212 213 return CtbAddrRStoTS; 214 } 215 SetupLCUMap()216 MOS_STATUS Av1StreamIn::SetupLCUMap() 217 { 218 ENCODE_FUNC_CALL(); 219 220 ENCODE_CHK_NULL_RETURN(m_basicFeature); 221 222 for (uint32_t y = 0; y < m_heightInLCU; y++) 223 { 224 for (uint32_t x = 0; x < m_widthInLCU; x++) 225 { 226 uint32_t Lcu_Offset = GetLCUAddr(x, y); 227 uint32_t lcu_Index = y * m_widthInLCU + x; 228 m_LcuMap[lcu_Index] = Lcu_Offset; 229 } 230 } 231 232 return MOS_STATUS_SUCCESS; 233 } 234 GetCuOffset(uint32_t xIdx,uint32_t yIdx) const235 uint32_t Av1StreamIn::GetCuOffset(uint32_t xIdx, uint32_t yIdx) const 236 { 237 uint32_t lcu_Index = yIdx / m_num32x32BlocksInLCUOnedimension * m_widthInLCU + xIdx / m_num32x32BlocksInLCUOnedimension; 238 uint32_t Lcu_Offset = m_LcuMap[lcu_Index]; 239 return Lcu_Offset * m_num32x32BlocksInLCU + (yIdx % m_num32x32BlocksInLCUOnedimension) * m_num32x32BlocksInLCUOnedimension + 240 (xIdx % m_num32x32BlocksInLCUOnedimension); 241 } 242 GetStreamInBuffer()243 VdencStreamInState* Av1StreamIn::GetStreamInBuffer() 244 { 245 ENCODE_FUNC_CALL(); 246 247 return (VdencStreamInState *)m_streamInTemp; 248 } 249 ReturnStreamInBuffer()250 MOS_STATUS Av1StreamIn::ReturnStreamInBuffer() 251 { 252 ENCODE_FUNC_CALL(); 253 254 m_streamInBuffer = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::StreamInBuffer, m_basicFeature->m_frameNum); 255 ENCODE_CHK_NULL_RETURN(m_streamInBuffer); 256 257 uint8_t *streaminBuffer = (uint8_t *)m_allocator->LockResourceForWrite(m_streamInBuffer); 258 ENCODE_CHK_NULL_RETURN(streaminBuffer); 259 260 MOS_SecureMemcpy(streaminBuffer, m_streamInSize, m_streamInTemp, m_streamInSize); 261 262 m_allocator->UnLock(m_streamInBuffer); 263 264 return MOS_STATUS_SUCCESS; 265 } 266 StreamInInit(uint8_t * streamInBuffer)267 MOS_STATUS Av1StreamIn::StreamInInit(uint8_t *streamInBuffer) 268 { 269 ENCODE_CHK_NULL_RETURN(m_osInterface); 270 uint16_t numLCUs = m_widthInLCU * m_heightInLCU; 271 memset(streamInBuffer, 0, numLCUs * m_num32x32BlocksInLCU * sizeof(VdencStreamInState)); 272 Av1FrameType frame_type = static_cast<Av1FrameType>(m_basicFeature->m_av1PicParams->PicFlags.fields.frame_type); 273 MEDIA_WA_TABLE *pWaTable = m_osInterface->pfnGetWaTable(m_osInterface); 274 ENCODE_CHK_NULL_RETURN(pWaTable); 275 276 for (uint16_t LcuAddr = 0; LcuAddr < numLCUs; LcuAddr++) 277 { 278 for (uint16_t CuAddr = 0; CuAddr < m_num32x32BlocksInLCU; CuAddr++) 279 { 280 VdencStreamInState* pStreamIn32x32 = (VdencStreamInState *)(streamInBuffer) + LcuAddr * m_num32x32BlocksInLCU + CuAddr; 281 282 if (MEDIA_IS_WA(pWaTable, Wa_22011549751) && frame_type == keyFrame && !m_osInterface->bSimIsActive && !Mos_Solo_Extension((MOS_CONTEXT_HANDLE)m_osInterface->pOsContext)) 283 { 284 pStreamIn32x32->DW0.MaxCuSize = 3; 285 pStreamIn32x32->DW0.MaxTuSize = 3; 286 pStreamIn32x32->DW0.NumImePredictors = 0; 287 pStreamIn32x32->DW6.NumMergeCandidateCu8x8 = 2; 288 pStreamIn32x32->DW6.NumMergeCandidateCu16x16 = 0; 289 pStreamIn32x32->DW6.NumMergeCandidateCu32x32 = 0; 290 pStreamIn32x32->DW6.NumMergeCandidateCu64x64 = 0; 291 } 292 else 293 { 294 pStreamIn32x32->DW0.MaxCuSize = m_commonPar.MaxCuSize; 295 pStreamIn32x32->DW0.MaxTuSize = m_commonPar.MaxTuSize; 296 pStreamIn32x32->DW0.NumImePredictors = m_commonPar.NumImePredictors; 297 pStreamIn32x32->DW6.NumMergeCandidateCu8x8 = m_commonPar.NumMergeCandidateCu8x8; 298 pStreamIn32x32->DW6.NumMergeCandidateCu16x16 = m_commonPar.NumMergeCandidateCu16x16; 299 pStreamIn32x32->DW6.NumMergeCandidateCu32x32 = m_commonPar.NumMergeCandidateCu32x32; 300 pStreamIn32x32->DW6.NumMergeCandidateCu64x64 = m_commonPar.NumMergeCandidateCu64x64; 301 } 302 } 303 } 304 return MOS_STATUS_SUCCESS; 305 } 306 GetCommonParams() const307 const CommonStreamInParams& Av1StreamIn::GetCommonParams() const 308 { 309 return m_commonPar; 310 } 311 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE,Av1StreamIn)312 MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, Av1StreamIn) 313 { 314 if (m_enabled) 315 { 316 ENCODE_CHK_NULL_RETURN(m_basicFeature); 317 ENCODE_CHK_NULL_RETURN(m_basicFeature->m_trackedBuf); 318 319 params.streamInBuffer = m_streamInBuffer; 320 } 321 322 return MOS_STATUS_SUCCESS; 323 } 324 MHW_SETPAR_DECL_SRC(VDENC_CMD2,Av1StreamIn)325 MHW_SETPAR_DECL_SRC(VDENC_CMD2, Av1StreamIn) 326 { 327 params.vdencStreamIn = m_enabled; 328 329 return MOS_STATUS_SUCCESS; 330 } 331 } // namespace encode 332