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