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