1 /*
2 * Copyright (c) 2023, 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_avc_vdenc_fast_pass.cpp
24 //! \brief    Defines the common interface for encode avc Xe2_HPM+ fast pass feature
25 //!
26 
27 #include "encode_avc_vdenc_fastpass.h"
28 #include "encode_avc_vdenc_feature_manager.h"
29 #include <array>
30 
31 namespace encode
32 {
33 
AvcVdencFastPass(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)34 AvcVdencFastPass::AvcVdencFastPass(
35     MediaFeatureManager *featureManager,
36     EncodeAllocator *allocator,
37     CodechalHwInterfaceNext *hwInterface,
38     void *constSettings) :
39     MediaFeature(constSettings)
40 {
41     auto encFeatureManager = dynamic_cast<EncodeAvcVdencFeatureManager *>(featureManager);
42     ENCODE_CHK_NULL_NO_STATUS_RETURN(encFeatureManager);
43 
44     m_basicFeature = dynamic_cast<AvcBasicFeature *>(encFeatureManager->GetFeature(FeatureIDs::basicFeature));
45     ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
46     if (hwInterface)
47     {
48         m_userSettingPtr = hwInterface->GetOsInterface()->pfnGetUserSettingInstance(hwInterface->GetOsInterface());
49     }
50     //regkey to control fast pass encode settings
51     MediaUserSetting::Value outValue;
52     ReadUserSetting(m_userSettingPtr,
53         outValue,
54         "Enable Fast Pass Encode",
55         MediaUserSetting::Group::Sequence);
56 
57     m_enabled = outValue.Get<bool>();
58     if (m_enabled)
59     {
60         MediaUserSetting::Value outValue_ratio;
61         MediaUserSetting::Value outValue_type;
62 #if (_DEBUG || _RELEASE_INTERNAL)
63 
64         ReadUserSetting(m_userSettingPtr,
65             outValue_ratio,
66             "Fast Pass Encode Downscale Ratio",
67             MediaUserSetting::Group::Sequence);
68         ReadUserSetting(m_userSettingPtr,
69             outValue_type,
70             "Fast Pass Encode Downscale Type",
71             MediaUserSetting::Group::Sequence);
72 #endif
73 
74         if (outValue_ratio.Get<int32_t>() == 0)
75         {
76             m_fastPassShiftIndex = 2;
77         }
78         else if (outValue_ratio.Get<int32_t>() == 1)
79         {
80             m_fastPassShiftIndex = 1;
81         }
82         else
83             m_fastPassShiftIndex = 2;
84         m_fastPassDownScaleType = (uint8_t)outValue_type.Get<int32_t>();
85     }
86 }
87 
Update(void * params)88 MOS_STATUS AvcVdencFastPass::Update(void *params)
89 {
90     if (!m_enabled)
91     {
92         return MOS_STATUS_SUCCESS;
93     }
94     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS avcSeqParams = m_basicFeature->m_seqParam;
95     ENCODE_CHK_NULL_RETURN(avcSeqParams);
96 
97     m_dsWidth  = MOS_ALIGN_FLOOR(avcSeqParams->FrameWidth >> m_fastPassShiftIndex, 16);
98     m_dsHeight = MOS_ALIGN_FLOOR(avcSeqParams->FrameHeight >> m_fastPassShiftIndex, 16);
99     return MOS_STATUS_SUCCESS;
100 }
101 
MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT,AvcVdencFastPass)102 MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, AvcVdencFastPass)
103 {
104     ENCODE_FUNC_CALL();
105 
106     if (m_enabled)
107     {
108         params.fastPassEn    = m_enabled;
109         params.fastPassScale = m_fastPassShiftIndex == 2 ? 0 : 1;  // fastPassScale:0 indicates 4x4 ds, fastPassScale:1 indicates 2x2 ds
110         params.DownScaleType = m_fastPassDownScaleType;            // DownScaleType:0 indicates bilinear, DownScaleType:1 indicates NN
111     }
112 
113     return MOS_STATUS_SUCCESS;
114 }
115 
MHW_SETPAR_DECL_SRC(VDENC_REF_SURFACE_STATE,AvcVdencFastPass)116 MHW_SETPAR_DECL_SRC(VDENC_REF_SURFACE_STATE, AvcVdencFastPass)
117 {
118     ENCODE_FUNC_CALL();
119 
120     if (m_enabled)
121     {
122         params.width  = MOS_ALIGN_FLOOR(m_basicFeature->m_reconSurface.dwWidth >> m_fastPassShiftIndex, 16);
123         params.height = MOS_ALIGN_FLOOR(m_basicFeature->m_reconSurface.dwHeight >> m_fastPassShiftIndex, 16);
124     }
125 
126     return MOS_STATUS_SUCCESS;
127 }
MHW_SETPAR_DECL_SRC(VDENC_AVC_IMG_STATE,AvcVdencFastPass)128 MHW_SETPAR_DECL_SRC(VDENC_AVC_IMG_STATE, AvcVdencFastPass)
129 {
130     ENCODE_FUNC_CALL();
131 
132     if (m_enabled)
133     {
134         params.pictureHeightMinusOne = (m_dsHeight / 16) - 1;
135         params.pictureWidth          = m_dsWidth / 16;
136     }
137 
138     return MOS_STATUS_SUCCESS;
139 }
MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE,AvcVdencFastPass)140 MHW_SETPAR_DECL_SRC(VDENC_WALKER_STATE, AvcVdencFastPass)
141 {
142     ENCODE_FUNC_CALL();
143 
144     if (m_enabled)
145     {
146         auto frameHeight      = m_dsHeight / 16;
147         auto frameWidth       = m_dsWidth / 16;
148 
149         auto     sliceParams               = &(m_basicFeature->m_sliceParams[m_basicFeature->m_curNumSlices]);
150         uint32_t MbNums                    = frameHeight * frameWidth;
151         auto     nextsliceMbStartYPosition = (sliceParams->first_mb_in_slice + MbNums) / frameWidth;
152         params.tileSliceStartLcuMbY        = sliceParams->first_mb_in_slice / frameWidth;
153         params.nextTileSliceStartLcuMbY    = nextsliceMbStartYPosition > frameHeight ? frameHeight : nextsliceMbStartYPosition;
154     }
155 
156     return MOS_STATUS_SUCCESS;
157 }
MHW_SETPAR_DECL_SRC(MFX_AVC_IMG_STATE,AvcVdencFastPass)158 MHW_SETPAR_DECL_SRC(MFX_AVC_IMG_STATE, AvcVdencFastPass)
159 {
160     ENCODE_FUNC_CALL();
161 
162     if (m_enabled)
163     {
164         uint32_t numMBs    = (m_dsWidth / 16) * (m_dsHeight / 16);
165         params.frameSize   = (numMBs > 0xFFFF) ? 0xFFFF : numMBs;
166         params.frameHeight = (m_dsHeight / 16) - 1;
167         params.frameWidth  = (m_dsWidth / 16) - 1;
168     }
169 
170     return MOS_STATUS_SUCCESS;
171 }
MHW_SETPAR_DECL_SRC(MFX_AVC_SLICE_STATE,AvcVdencFastPass)172 MHW_SETPAR_DECL_SRC(MFX_AVC_SLICE_STATE, AvcVdencFastPass)
173 {
174     ENCODE_FUNC_CALL();
175 
176     if (m_enabled)
177     {
178         auto     sliceParams = &(m_basicFeature->m_sliceParams[m_basicFeature->m_curNumSlices]);
179         uint32_t startMbNum  = sliceParams->first_mb_in_slice * (1 + m_basicFeature->m_seqParam->mb_adaptive_frame_field_flag);
180         uint16_t widthInMb   = m_dsWidth / 16;
181         uint16_t heightInMb  = m_dsHeight / 16;
182         uint16_t MbNums      = widthInMb * heightInMb;
183 
184         params.sliceHorizontalPosition     = startMbNum % widthInMb;
185         params.sliceVerticalPosition       = startMbNum / widthInMb;
186         params.nextSliceHorizontalPosition = (startMbNum + MbNums) % widthInMb;
187         params.nextSliceVerticalPosition   = (startMbNum + MbNums) / widthInMb;
188         params.isLastSlice                 = (startMbNum + MbNums) >= (uint32_t)(widthInMb * heightInMb);
189     }
190 
191     return MOS_STATUS_SUCCESS;
192 }
MHW_SETPAR_DECL_SRC(VDENC_DS_REF_SURFACE_STATE,AvcVdencFastPass)193 MHW_SETPAR_DECL_SRC(VDENC_DS_REF_SURFACE_STATE, AvcVdencFastPass)
194 {
195     ENCODE_FUNC_CALL();
196 
197     if (m_enabled)
198     {
199         uint32_t dsWidth4x  = m_dsWidth / 4;
200         uint32_t dsHeight4x = m_dsHeight / 4;
201 
202         params.heightStage1 = dsHeight4x;
203         params.widthStage1  = dsWidth4x;
204     }
205 
206     return MOS_STATUS_SUCCESS;
207 }
208 
MHW_SETPAR_DECL_SRC(VDENC_CMD3,AvcVdencFastPass)209 MHW_SETPAR_DECL_SRC(VDENC_CMD3, AvcVdencFastPass)
210 {
211     ENCODE_FUNC_CALL();
212 
213     if (m_enabled)
214     {
215         PCODEC_AVC_ENCODE_SEQUENCE_PARAMS avcSeqParams = m_basicFeature->m_seqParam;
216         ENCODE_CHK_NULL_RETURN(avcSeqParams);
217         PCODEC_AVC_ENCODE_PIC_PARAMS avcPicParams = m_basicFeature->m_picParam;
218         ENCODE_CHK_NULL_RETURN(avcPicParams);
219         PCODEC_AVC_ENCODE_SLICE_PARAMS avcSliceParams = m_basicFeature->m_sliceParams;
220         ENCODE_CHK_NULL_RETURN(avcSliceParams);
221 
222         auto     pictureType   = CodecHal_Clip3(0, 2, avcPicParams->CodingType - 1);
223         uint16_t picWidthInMb  = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_dsWidth);
224         uint16_t picHeightInMb = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_dsHeight);
225         auto     fastpass_qp   = CodecHal_Clip3(10, 51, avcPicParams->QpY + avcSliceParams->slice_qp_delta);
226         auto     codingType    = avcPicParams->CodingType;
227         // Only do this lambda offset for lower resolution and high QP range.
228         uint16_t gopP = (avcSeqParams->GopRefDist) ? ((avcSeqParams->GopPicSize - 1) / avcSeqParams->GopRefDist) : 0;
229         uint16_t gopB = avcSeqParams->GopPicSize - 1 - gopP;
230         uint16_t numB = ((gopP > 0) ? (gopB / gopP) : 0);
231         if ((numB != 0) && (picWidthInMb * 16 < 1920) && (picHeightInMb * 16 < 1080) && (fastpass_qp >= 32))
232         {
233             uint8_t index0 = avcPicParams->RefPicFlag ? 0 : 1;
234             static const std::array<
235                 std::array<
236                     uint8_t,
237                     3>,
238                 2>
239                 table = {{
240                     {0, 1, 1},
241                     {0, 1, 2},
242                 }};
243             fastpass_qp += table[index0][pictureType];
244             fastpass_qp = CodecHal_Clip3(0, 51, fastpass_qp);
245 
246             for (auto i = 0; i < 8; i++)
247             {
248                 params.vdencCmd3Par0[i] = m_CMD3Settings.AvcVdencCMD3ConstSettings_0[i][fastpass_qp];
249             }
250 
251             if (codingType == I_TYPE || codingType == P_TYPE)
252                 params.vdencCmd3Par19 = m_CMD3Settings.AvcVdencCMD3ConstSettings_3[pictureType][fastpass_qp];
253 
254             uint8_t isIPGOP          = avcSeqParams->GopRefDist == 1 ? 1 : 0;
255             uint8_t codingTypeMinus1 = avcPicParams->CodingType - 1;
256             uint8_t refPic           = avcPicParams->RefPicFlag;
257 
258             params.vdencCmd3Par31 = m_CMD3Settings.par31Table[isIPGOP][codingTypeMinus1][refPic][fastpass_qp];
259             params.vdencCmd3Par32 = m_CMD3Settings.par32Table[isIPGOP][codingTypeMinus1][refPic][fastpass_qp];
260         }
261     }
262 
263     return MOS_STATUS_SUCCESS;
264 }
265 
266 }  // namespace encode