1 /*
2 * Copyright (c) 2020-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_hevc_downsampling_packet.cpp
24 //! \brief Defines the interface for hevc decode down sampling sub packet
25 //!
26 #include "decode_hevc_downsampling_packet.h"
27 #include "decode_hevc_basic_feature.h"
28
29 #ifdef _DECODE_PROCESSING_SUPPORTED
30
31 namespace decode
32 {
33
HevcDownSamplingPkt(DecodePipeline * pipeline,CodechalHwInterfaceNext * hwInterface)34 HevcDownSamplingPkt::HevcDownSamplingPkt(DecodePipeline *pipeline, CodechalHwInterfaceNext *hwInterface)
35 : DecodeDownSamplingPkt(pipeline, hwInterface)
36 {}
37
Init()38 MOS_STATUS HevcDownSamplingPkt::Init()
39 {
40 DECODE_CHK_STATUS(DecodeDownSamplingPkt::Init());
41
42 #if (_DEBUG || _RELEASE_INTERNAL)
43 m_dbgOvrdWidthInMinCb =
44 ReadUserFeature(m_pipeline->GetUserSetting(), "Scalability Split Width In MinCb", MediaUserSetting::Group::Sequence).Get<bool>();
45 #endif
46
47 return MOS_STATUS_SUCCESS;
48 }
49
SetSfcMode(MEDIA_SFC_INTERFACE_MODE & mode)50 MOS_STATUS HevcDownSamplingPkt::SetSfcMode(MEDIA_SFC_INTERFACE_MODE &mode)
51 {
52 mode.veboxSfcEnabled = 0;
53 mode.vdboxSfcEnabled = 1;
54 return MOS_STATUS_SUCCESS;
55 }
56
InitSfcParams(VDBOX_SFC_PARAMS & sfcParams)57 MOS_STATUS HevcDownSamplingPkt::InitSfcParams(VDBOX_SFC_PARAMS &sfcParams)
58 {
59 DECODE_FUNC_CALL();
60
61 DECODE_CHK_STATUS(DecodeDownSamplingPkt::InitSfcParams(sfcParams));
62
63 sfcParams.input.width = m_basicFeature->m_width;
64 sfcParams.input.height = m_basicFeature->m_height;
65
66 HevcBasicFeature *hevcBasicFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
67 DECODE_CHK_NULL(hevcBasicFeature);
68 sfcParams.videoParams.hevc.lcuSize = hevcBasicFeature->m_ctbSize;
69
70 SCALABILITY_PARAMS &scalabilityParams = sfcParams.videoParams.scalabilityParams;
71 if (m_pipeline->GetPipeNum() <= 1)
72 {
73 scalabilityParams.numPipe = 1;
74 scalabilityParams.curPipe = 0;
75 scalabilityParams.engineMode = MhwSfcInterface::sfcScalabModeSingle;
76 }
77 else
78 {
79 DECODE_CHK_STATUS(InitSfcScalabParams(scalabilityParams));
80 }
81
82 return MOS_STATUS_SUCCESS;
83 }
84
InitSfcScalabParams(SCALABILITY_PARAMS & scalabilityParams)85 MOS_STATUS HevcDownSamplingPkt::InitSfcScalabParams(SCALABILITY_PARAMS &scalabilityParams)
86 {
87 DECODE_FUNC_CALL();
88
89 HevcPipeline *hevcPipeline = dynamic_cast<HevcPipeline *>(m_pipeline);
90 DECODE_CHK_NULL(hevcPipeline);
91 HevcBasicFeature *hevcBasicFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
92 DECODE_CHK_NULL(hevcBasicFeature);
93
94 CodecRectangle &inputSurfaceRegion = m_downSampling->m_inputSurfaceRegion;
95 CodecRectangle &outputSurfaceRegion = m_downSampling->m_outputSurfaceRegion;
96
97 auto curPipe = hevcPipeline->GetCurrentPipe();
98 auto numPipe = hevcPipeline->GetPipeNum();
99 auto curPass = hevcPipeline->GetCurrentPass();
100
101 scalabilityParams.numPipe = numPipe;
102 scalabilityParams.curPipe = curPipe;
103
104 if (curPipe == 0)
105 {
106 scalabilityParams.engineMode = MhwSfcInterface::sfcScalabModeLeftCol;
107 }
108 else if (curPipe == numPipe - 1)
109 {
110 scalabilityParams.engineMode = MhwSfcInterface::sfcScalabModeRightCol;
111 }
112 else
113 {
114 scalabilityParams.engineMode = MhwSfcInterface::sfcScalabModeMiddleCol;
115 }
116
117 uint32_t tileColIndex = 0;
118 uint32_t tileColCount = 0;
119
120 DECODE_CHK_STATUS(InitSfcScalabSrcParams(
121 *hevcPipeline, *hevcBasicFeature, scalabilityParams, tileColIndex, tileColCount));
122
123 DECODE_CHK_STATUS(InitSfcScalabDstParams(
124 *hevcPipeline, *hevcBasicFeature, scalabilityParams, tileColIndex, tileColCount));
125
126 return MOS_STATUS_SUCCESS;
127 }
128
InitSfcScalabSrcParams(HevcPipeline & hevcPipeline,HevcBasicFeature & hevcBasicFeature,SCALABILITY_PARAMS & scalabilityParams,uint32_t & tileColIndex,uint32_t & tileColCount)129 MOS_STATUS HevcDownSamplingPkt::InitSfcScalabSrcParams(
130 HevcPipeline &hevcPipeline, HevcBasicFeature &hevcBasicFeature,
131 SCALABILITY_PARAMS &scalabilityParams, uint32_t &tileColIndex, uint32_t &tileColCount)
132 {
133 DECODE_FUNC_CALL();
134
135 CodecRectangle &inputSurfaceRegion = m_downSampling->m_inputSurfaceRegion;
136 CodecRectangle &outputSurfaceRegion = m_downSampling->m_outputSurfaceRegion;
137
138 auto curPipe = hevcPipeline.GetCurrentPipe();
139 auto numPipe = hevcPipeline.GetPipeNum();
140 auto curPass = hevcPipeline.GetCurrentPass();
141
142 if (hevcPipeline.GetDecodeMode() == HevcPipeline::realTileDecodeMode)
143 {
144 scalabilityParams.tileType = MhwSfcInterface::sfcScalabRealTile;
145
146 DECODE_CHK_NULL(hevcBasicFeature.m_hevcPicParams);
147 PCODEC_HEVC_PIC_PARAMS hevcPicParams = hevcBasicFeature.m_hevcPicParams;
148 tileColIndex = curPipe + curPass * numPipe;
149 tileColCount = hevcPicParams->num_tile_columns_minus1 + 1;
150
151 if (hevcPicParams->uniform_spacing_flag)
152 {
153 scalabilityParams.srcStartX = tileColIndex * hevcBasicFeature.m_widthInCtb / tileColCount *
154 hevcBasicFeature.m_ctbSize;
155 scalabilityParams.srcEndX = (tileColIndex + 1) * hevcBasicFeature.m_widthInCtb / tileColCount *
156 hevcBasicFeature.m_ctbSize - 1;
157 }
158 else
159 {
160 scalabilityParams.srcStartX = 0;
161 for (uint32_t i = 0; i < tileColIndex; i++)
162 {
163 scalabilityParams.srcStartX +=
164 (hevcPicParams->column_width_minus1[i] + 1) * hevcBasicFeature.m_ctbSize;
165 }
166 if (tileColIndex == hevcPicParams->num_tile_columns_minus1)
167 {
168 scalabilityParams.srcEndX = inputSurfaceRegion.m_x + inputSurfaceRegion.m_width - 1;
169 }
170 else
171 {
172 scalabilityParams.srcEndX = scalabilityParams.srcStartX +
173 (hevcPicParams->column_width_minus1[tileColIndex] + 1) * hevcBasicFeature.m_ctbSize - 1;
174 }
175 }
176 }
177 else if (hevcPipeline.GetDecodeMode() == HevcPipeline::virtualTileDecodeMode)
178 {
179 scalabilityParams.tileType = MhwSfcInterface::sfcScalabVirtualTile;
180
181 tileColIndex = curPipe;
182 tileColCount = numPipe;
183
184 scalabilityParams.srcStartX = (tileColIndex * hevcBasicFeature.m_widthInCtb) / tileColCount *
185 hevcBasicFeature.m_ctbSize;
186 if (tileColIndex == tileColCount - 1)
187 {
188 scalabilityParams.srcEndX = inputSurfaceRegion.m_x + inputSurfaceRegion.m_width - 1;
189 }
190 else
191 {
192 scalabilityParams.srcEndX = (tileColIndex + 1) * hevcBasicFeature.m_widthInCtb / tileColCount *
193 hevcBasicFeature.m_ctbSize - 1;
194 }
195 #if (_DEBUG || _RELEASE_INTERNAL)
196 if (m_dbgOvrdWidthInMinCb > 0 && numPipe == 2)
197 {
198 if (curPipe == 1)
199 {
200 scalabilityParams.srcStartX = m_dbgOvrdWidthInMinCb * hevcBasicFeature.m_minCtbSize;
201 scalabilityParams.srcEndX = inputSurfaceRegion.m_x + inputSurfaceRegion.m_width - 1;
202 }
203 else
204 {
205 scalabilityParams.srcStartX = 0;
206 scalabilityParams.srcEndX = m_dbgOvrdWidthInMinCb * hevcBasicFeature.m_minCtbSize - 1;
207 }
208 }
209 #endif
210 }
211 else
212 {
213 DECODE_ASSERTMESSAGE("Invalid decode mode, expect real tile mode and virtual tile mode.");
214 return MOS_STATUS_INVALID_PARAMETER;
215 }
216
217 // Clamp srcStartX, srcEndX into source region
218 if (scalabilityParams.srcStartX < inputSurfaceRegion.m_x)
219 {
220 scalabilityParams.srcStartX = inputSurfaceRegion.m_x;
221 }
222 if (scalabilityParams.srcEndX > inputSurfaceRegion.m_x + inputSurfaceRegion.m_width - 1)
223 {
224 scalabilityParams.srcEndX = inputSurfaceRegion.m_x + inputSurfaceRegion.m_width - 1;
225 }
226
227 return MOS_STATUS_SUCCESS;
228 }
229
InitSfcScalabDstParams(HevcPipeline & hevcPipeline,HevcBasicFeature & hevcBasicFeature,SCALABILITY_PARAMS & scalabilityParams,const uint32_t & tileColIndex,const uint32_t & tileColCount)230 MOS_STATUS HevcDownSamplingPkt::InitSfcScalabDstParams(
231 HevcPipeline &hevcPipeline, HevcBasicFeature &hevcBasicFeature,
232 SCALABILITY_PARAMS &scalabilityParams, const uint32_t &tileColIndex, const uint32_t &tileColCount)
233 {
234 DECODE_FUNC_CALL();
235
236 CodecRectangle &inputSurfaceRegion = m_downSampling->m_inputSurfaceRegion;
237 CodecRectangle &outputSurfaceRegion = m_downSampling->m_outputSurfaceRegion;
238
239 if (tileColIndex == 0)
240 {
241 m_firstValidTileIndex = 0;
242 m_lastValidTileIndex = tileColCount - 1;
243 m_dstXLandingCount = 0;
244 }
245
246 // start ildb offset correction
247 uint32_t srcEndXCorr = scalabilityParams.srcEndX - m_ildbXOffset;
248
249 uint32_t tileOffsetX;
250 uint32_t tileEndX;
251 if ((inputSurfaceRegion.m_x + inputSurfaceRegion.m_width - 1) <= srcEndXCorr)
252 {
253 tileOffsetX = 0;
254 tileEndX = inputSurfaceRegion.m_x + inputSurfaceRegion.m_width;
255 }
256 else
257 {
258 tileOffsetX = (hevcBasicFeature.m_hevcPicParams->chroma_format_idc == HCP_CHROMA_FORMAT_YUV444) ?
259 m_tileOffsetX444 : m_tileOffsetXBasic;
260 tileEndX = srcEndXCorr;
261 }
262
263 uint32_t dstEndX = 0;
264 if ((srcEndXCorr - inputSurfaceRegion.m_x) >= (tileOffsetX + 1))
265 {
266 constexpr int32_t phaseShiftMin = -(1 << (4 + 19));
267 constexpr int32_t phaseShiftMax = (1 << (4 + 19)) - 1;
268 int32_t xPhaseShift = MOS_F_ROUND((double(inputSurfaceRegion.m_width) / outputSurfaceRegion.m_width - 1.0) / 2.0 * 524288.0F);
269 uint32_t xPhaseShiftClamped = MOS_CLAMP_MIN_MAX(xPhaseShift, phaseShiftMin, phaseShiftMax);
270 uint64_t oneBySf = uint64_t(double(uint64_t(inputSurfaceRegion.m_width) * 524288 / outputSurfaceRegion.m_width));
271
272 while (true)
273 {
274 if (m_dstXLandingCount == 0)
275 {
276 m_firstValidTileIndex = tileColIndex;
277 }
278
279 double tempDestCntx = (((double)m_dstXLandingCount * (double)oneBySf) + xPhaseShiftClamped);
280 if (tempDestCntx < 0)
281 {
282 tempDestCntx = 0;
283 }
284 double xLandingPoint = double((tempDestCntx + (double(1 << (m_oneBySfFractionPrecision - m_betaPrecision - 1)))) / 524288
285 + inputSurfaceRegion.m_x);
286
287 if (xLandingPoint >= double(tileEndX - tileOffsetX))
288 {
289 dstEndX = m_dstXLandingCount - 1;
290 break;
291 }
292 else
293 {
294 m_dstXLandingCount++;
295 }
296 }
297 }
298
299 if (tileOffsetX == 0)
300 {
301 m_lastValidTileIndex = tileColIndex;
302 }
303
304 // Last column end at destination region right border.
305 if (tileColIndex == m_lastValidTileIndex)
306 {
307 dstEndX = outputSurfaceRegion.m_x + outputSurfaceRegion.m_width - 1;
308 }
309
310 if (tileColIndex <= m_firstValidTileIndex)
311 {
312 scalabilityParams.dstStartX = 0;
313 scalabilityParams.dstEndX = dstEndX;
314 }
315 else if (tileColIndex <= m_lastValidTileIndex)
316 {
317 scalabilityParams.dstStartX = m_lastDstEndX + 1;
318 scalabilityParams.dstEndX = dstEndX;
319 }
320 else
321 {
322 scalabilityParams.dstStartX = 0;
323 scalabilityParams.dstEndX = 0;
324 }
325
326 m_lastDstEndX = dstEndX;
327
328 return MOS_STATUS_SUCCESS;
329 }
330
331 }
332
333 #endif // !_DECODE_PROCESSING_SUPPORTED
334