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