1 /*
2 * Copyright (c) 2021-2024, 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_aqm_feature.cpp
24 //! \brief    Defines the common interface for aqm feature
25 //!
26 
27 #include <iomanip>
28 
29 #include "encode_aqm_feature.h"
30 #include "encode_feature_manager.h"
31 #include "encode_utils.h"
32 #include "media_perf_profiler.h"
33 
34 namespace encode
35 {
EncodeAqmFeature(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)36 EncodeAqmFeature::EncodeAqmFeature(
37     MediaFeatureManager *featureManager,
38     EncodeAllocator *    allocator,
39     CodechalHwInterfaceNext *hwInterface,
40     void *               constSettings) : MediaFeature(constSettings),
41                            m_hwInterface(hwInterface),
42                            m_allocator(allocator)
43 {
44     ENCODE_FUNC_CALL();
45 
46     m_featureManager = featureManager;
47 
48     auto encFeatureManager = dynamic_cast<EncodeFeatureManager *>(featureManager);
49     ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
50 
51     if (hwInterface)
52     {
53         m_mosCtx = hwInterface->GetOsInterface()->pOsContext;
54         m_userSettingPtr = hwInterface->GetOsInterface()->pfnGetUserSettingInstance(hwInterface->GetOsInterface());
55     }
56 
57     m_basicFeature = dynamic_cast<EncodeBasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
58     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
59 
60 #if (_DEBUG || _RELEASE_INTERNAL)
61     MediaUserSetting::Value outValue;
62     ReadUserSetting(
63         m_userSettingPtr,
64         outValue,
65         "VDAQM Enable",
66         MediaUserSetting::Group::Sequence);
67 
68     m_metricsDumpMode   = outValue.Get<uint8_t>();
69 
70 #endif
71 
72     if (m_metricsDumpMode > 0)
73     {
74         m_enabled = true;
75     }
76 #if _MEDIA_RESERVED
77 #if USE_CODECHAL_DEBUG_TOOL
78     MetricsDump();
79 #endif
80 #endif
81 }
82 
~EncodeAqmFeature()83 EncodeAqmFeature::~EncodeAqmFeature()
84 {
85     if (m_enabled)
86     {
87         FreeResources();
88 #if _MEDIA_RESERVED
89 #if USE_CODECHAL_DEBUG_TOOL
90         CloseDumpFiles();
91 #endif
92 #endif
93     }
94 }
95 
EncodeAqmFeatureFunction0(uint32_t frameWidth,uint32_t frameHeight,uint8_t index)96 uint32_t EncodeAqmFeature::EncodeAqmFeatureFunction0(uint32_t frameWidth, uint32_t frameHeight, uint8_t index)
97 {
98     uint32_t width  = (frameWidth + (1 << index) - 1) >> index;
99     uint32_t height = (frameHeight + (1 << index) - 1) >> index;
100     return (MOS_ALIGN_CEIL(MOS_ALIGN_CEIL(width, 4) / 4, CL_SIZE_BYTES) * (MOS_ALIGN_CEIL(height, 4) / 4));
101 }
102 
Update(void * params)103 MOS_STATUS EncodeAqmFeature::Update(void *params)
104 {
105     if (m_enabled)
106     {
107         ENCODE_CHK_STATUS_RETURN(AllocateResources());
108     }
109 
110     return MOS_STATUS_SUCCESS;
111 }
112 
AllocateResources()113 MOS_STATUS EncodeAqmFeature::AllocateResources()
114 {
115     ENCODE_FUNC_CALL();
116 
117     if (m_AllocatedResources)
118     {
119         return MOS_STATUS_SUCCESS;
120     }
121 
122     MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
123     MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
124 
125     allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
126     allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
127     allocParamsForBufferLinear.Format   = Format_Buffer;
128     allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ;
129 
130     uint32_t rowstoreBufferSize[5] = {(m_basicFeature->m_oriFrameWidth / 4 + 1), 3391, 1665, 833, 417};
131     for (int i = 0; i < 5; i++)
132     {
133         std::string bufName                 = "Index" + std::to_string(i) + "LineRowstoreBuffer";
134         allocParamsForBufferLinear.dwBytes  = rowstoreBufferSize[i] * CL_SIZE_BYTES * m_numRowStore;
135         allocParamsForBufferLinear.pBufName = &*bufName.begin();
136         EncodeAqmFeatureMember0[i]          = m_allocator->AllocateResource(allocParamsForBufferLinear, false);
137         EncodeAqmFeatureMember1[i]          = rowstoreBufferSize[i] * CL_SIZE_BYTES;
138     }
139 
140     EncodeAqmFeatureMember2    = ((sizeof(AQM_Ouput_Format) + CL_SIZE_BYTES - 1) / CL_SIZE_BYTES) * CL_SIZE_BYTES * m_numTiles;
141     EncodeAqmFeatureMember3[0] = 0;
142     EncodeAqmFeatureMember3[1] = EncodeAqmFeatureFunction0(m_basicFeature->m_oriFrameWidth, m_basicFeature->m_oriFrameHeight, 1);
143     EncodeAqmFeatureMember3[2] = EncodeAqmFeatureFunction0(m_basicFeature->m_oriFrameWidth, m_basicFeature->m_oriFrameHeight, 2);
144     EncodeAqmFeatureMember3[3] = EncodeAqmFeatureFunction0(m_basicFeature->m_oriFrameWidth, m_basicFeature->m_oriFrameHeight, 3);
145     EncodeAqmFeatureMember3[4] = EncodeAqmFeatureFunction0(m_basicFeature->m_oriFrameWidth, m_basicFeature->m_oriFrameHeight, 4);
146 
147     // allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
148 
149     allocParamsForBufferLinear.dwBytes  = EncodeAqmFeatureMember2;
150     allocParamsForBufferLinear.pBufName = "VdaqmBuffer0";
151     m_basicFeature->m_recycleBuf->RegisterResource(RecycleResId::VdaqmBuffer0, allocParamsForBufferLinear, EncodeBasicFeature::m_uncompressedSurfaceNum);
152 
153     allocParamsForBufferLinear.dwBytes  = EncodeAqmFeatureMember3[1];
154     allocParamsForBufferLinear.pBufName = "VdaqmBuffer1";
155     m_basicFeature->m_recycleBuf->RegisterResource(RecycleResId::VdaqmBuffer1, allocParamsForBufferLinear, EncodeBasicFeature::m_uncompressedSurfaceNum);
156 
157     allocParamsForBufferLinear.dwBytes  = EncodeAqmFeatureMember3[2];
158     allocParamsForBufferLinear.pBufName = "VdaqmBuffer2";
159     m_basicFeature->m_recycleBuf->RegisterResource(RecycleResId::VdaqmBuffer2, allocParamsForBufferLinear, EncodeBasicFeature::m_uncompressedSurfaceNum);
160 
161     allocParamsForBufferLinear.dwBytes  = EncodeAqmFeatureMember3[3];
162     allocParamsForBufferLinear.pBufName = "VdaqmBuffer3";
163     m_basicFeature->m_recycleBuf->RegisterResource(RecycleResId::VdaqmBuffer3, allocParamsForBufferLinear, EncodeBasicFeature::m_uncompressedSurfaceNum);
164 
165     allocParamsForBufferLinear.dwBytes  = EncodeAqmFeatureMember3[4];
166     allocParamsForBufferLinear.pBufName = "VdaqmBuffer4";
167     m_basicFeature->m_recycleBuf->RegisterResource(RecycleResId::VdaqmBuffer4, allocParamsForBufferLinear, EncodeBasicFeature::m_uncompressedSurfaceNum);
168 
169     m_AllocatedResources = true;
170 
171     return MOS_STATUS_SUCCESS;
172 }
173 
FreeResources()174 MOS_STATUS EncodeAqmFeature::FreeResources()
175 {
176     ENCODE_FUNC_CALL();
177 
178     if (m_AllocatedResources)
179     {
180         for (uint8_t index = 0; index < AQM_INDEX; index++)
181             m_allocator->DestroyResource(EncodeAqmFeatureMember0[index]);
182     }
183 
184     m_AllocatedResources = false;
185 
186     return MOS_STATUS_SUCCESS;
187 }
188 
MHW_SETPAR_DECL_SRC(AQM_FRAME_START,EncodeAqmFeature)189 MHW_SETPAR_DECL_SRC(AQM_FRAME_START, EncodeAqmFeature)
190 {
191     if (m_enabled)
192     {
193         params.aqmFrameStart = 1;
194     }
195 
196     return MOS_STATUS_SUCCESS;
197 }
198 
MHW_SETPAR_DECL_SRC(AQM_PIC_STATE,EncodeAqmFeature)199 MHW_SETPAR_DECL_SRC(AQM_PIC_STATE, EncodeAqmFeature)
200 {
201     if (m_enabled)
202     {
203         params.frameWidthInPixelMinus1  = MOS_ALIGN_CEIL(m_basicFeature->m_oriFrameWidth, 8) - 1;
204         params.FrameHeightInPixelMinus1 = MOS_ALIGN_CEIL(m_basicFeature->m_oriFrameHeight, 8) - 1;
205         params.vdaqmEnable              = m_enabled;
206         params.tileBasedEngine          = m_tileBasedEngine;
207         params.chromasubsampling        = m_basicFeature->m_chromaFormat - 1;
208         params.aqmMode                  = m_aqmMode;
209         params.sseEnable                = true;
210 #if _MEDIA_RESERVED
211 #define AQM_PIC_STATE_SETPAR_EXT
212 #include "encode_aqm_feature_ext.h"
213 #undef AQM_PIC_STATE_SETPAR_EXT
214 #else
215         params.extSettings.emplace_back(
216             [this](uint32_t *data) {
217                 data[2]  |= 0x1e;
218                 data[3]  |= 0x1a334d66;
219                 data[4]  |= 0x809ab3cd;
220                 data[5]  |= 0xe6000000;
221                 data[6]  |= 0x80001;
222                 data[7]  |= 0x700025;
223                 data[8]  |= 0x11000da;
224                 data[9]  |= 0x80001;
225                 data[10] |= 0x700025;
226                 data[11] |= 0x11000da;
227 
228                 return MOS_STATUS_SUCCESS;
229             });
230 #endif
231         if (m_basicFeature->m_bitDepth == 8)
232         {
233             params.pixelbitdepth = 0;
234         }
235         else if (m_basicFeature->m_bitDepth == 10)
236         {
237             params.pixelbitdepth = 1;
238         }
239         else if (m_basicFeature->m_bitDepth == 12)
240         {
241             params.pixelbitdepth = 2;
242         }
243     }
244 
245     return MOS_STATUS_SUCCESS;
246 }
247 
MHW_SETPAR_DECL_SRC(AQM_PIPE_BUF_ADDR_STATE,EncodeAqmFeature)248 MHW_SETPAR_DECL_SRC(AQM_PIPE_BUF_ADDR_STATE, EncodeAqmFeature)
249 {
250     if (m_enabled)
251     {
252         auto bIdx = m_basicFeature->m_currOriginalPic.FrameIdx;
253 
254         for (uint8_t index = 0; index < AQM_INDEX; index++)
255         {
256             params.AqmPipeBufAddrStatePar0[index] = EncodeAqmFeatureMember0[index];
257             params.AqmPipeBufAddrStatePar1[index] = EncodeAqmFeatureMember1[index] * m_currPipeNum;
258         }
259 
260         params.AqmPipeBufAddrStatePar4[0] = nullptr;
261         params.AqmPipeBufAddrStatePar4[1] = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::VdaqmBuffer1, bIdx);
262         params.AqmPipeBufAddrStatePar4[2] = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::VdaqmBuffer2, bIdx);
263         params.AqmPipeBufAddrStatePar4[3] = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::VdaqmBuffer3, bIdx);
264         params.AqmPipeBufAddrStatePar4[4] = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::VdaqmBuffer4, bIdx);
265         params.AqmPipeBufAddrStatePar2    = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::VdaqmBuffer0, bIdx);
266     }
267 
268     return MOS_STATUS_SUCCESS;
269 }
270 
271 #if USE_CODECHAL_DEBUG_TOOL
UpdateFrameDisplayOrder(const uint16_t pictureCodingType,const uint32_t framePOC,const uint32_t gopPicSize)272 MOS_STATUS EncodeAqmFeature::UpdateFrameDisplayOrder(const uint16_t pictureCodingType, const uint32_t framePOC, const uint32_t gopPicSize)
273 {
274     if (pictureCodingType == I_TYPE)
275     {
276         m_frameNumPrevious += m_gopSizePrevious;
277     }
278     uint32_t    displayOrderInGOP   = framePOC;
279     uint32_t    displayOrderInSeq   = displayOrderInGOP + m_frameNumPrevious;
280     m_gopSizePrevious               = gopPicSize;
281     m_frameIdxQueue.push(displayOrderInSeq);
282     return MOS_STATUS_SUCCESS;
283 }
284 #endif
285 
286 #if _MEDIA_RESERVED
287 #define AQM_FEATURE_SOURCE_EXT
288 #include "encode_aqm_feature_ext.h"
289 #undef AQM_FEATURE_SOURCE_EXT
290 #endif
291 
GetFrameMSE(AQM_Ouput_Format * pDataFrame,uint32_t (& MSE)[3])292 MOS_STATUS EncodeAqmFeature::GetFrameMSE(AQM_Ouput_Format* pDataFrame, uint32_t (&MSE)[3])
293 {
294     ENCODE_CHK_NULL_RETURN(pDataFrame);
295 
296     uint64_t SSE[3] = {};
297     uint32_t areaSum = 0;
298 
299     // Get Tile MSE
300     uint32_t offsetAqmTile = MOS_ALIGN_CEIL(sizeof(AQM_Ouput_Format), CL_SIZE_BYTES);
301     for (uint32_t tileIdx = 0; tileIdx < m_numTiles && tileIdx < ENCODE_VDENC_MAX_TILE_NUM; tileIdx++)
302     {
303         AQM_Ouput_Format* pTileVdaqmInfo = (AQM_Ouput_Format*)((char*)pDataFrame + offsetAqmTile * tileIdx);
304         ENCODE_CHK_NULL_RETURN(pTileVdaqmInfo);
305 
306         uint32_t area   =   m_tile_width[tileIdx] * m_tile_height[tileIdx];
307         SSE[0]          +=  (uint64_t)pTileVdaqmInfo->SSEY * (uint64_t)area;
308         SSE[1]          +=  (uint64_t)pTileVdaqmInfo->SSEU * (uint64_t)area;
309         SSE[2]          +=  (uint64_t)pTileVdaqmInfo->SSEV * (uint64_t)area;
310         areaSum         += area;
311     }
312 
313     if (areaSum == 0)
314     {
315         ENCODE_ASSERTMESSAGE("frame pixel num cal by each tile is zero, sth must be wrong!");
316         return MOS_STATUS_INVALID_PARAMETER;
317     }
318 
319     MSE[0] = (uint32_t)(SSE[0] / (uint64_t)areaSum);
320     MSE[1] = (uint32_t)(SSE[1] / (uint64_t)areaSum);
321     MSE[2] = (uint32_t)(SSE[2] / (uint64_t)areaSum);
322 
323     return MOS_STATUS_SUCCESS;
324 }
325 
ReportQualityInfoFrame(uint32_t statBufIdx,EncodeStatusReportData & statusReportData)326 MOS_STATUS EncodeAqmFeature::ReportQualityInfoFrame(uint32_t statBufIdx, EncodeStatusReportData& statusReportData)
327 {
328     ENCODE_FUNC_CALL();
329 
330     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
331 
332     PMOS_RESOURCE  pBuffer = m_basicFeature->m_recycleBuf->GetBuffer(RecycleResId::VdaqmBuffer0, statBufIdx);
333     ENCODE_CHK_NULL_RETURN(pBuffer);
334 
335     AQM_Ouput_Format* pDataFrameStas = (AQM_Ouput_Format*)m_allocator->LockResourceForRead(pBuffer);
336     ENCODE_CHK_NULL_RETURN(pDataFrameStas);
337 
338     ENCODE_CHK_STATUS_RETURN(GetFrameMSE(pDataFrameStas, statusReportData.MSE));
339 
340     ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(pBuffer));
341 
342     return eStatus;
343 }
344 }  // namespace encode
345