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