1 /*
2 * Copyright (c) 2020-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     meida_sfc_render.cpp
24 //! \brief    Common interface for sfc
25 //! \details  Common interface for sfc
26 //!
27 #include "media_sfc_interface.h"
28 #include "media_sfc_render.h"
29 #include "vp_feature_manager.h"
30 #include "mhw_vebox.h"
31 #include "vp_common.h"
32 #include "vp_platform_interface.h"
33 #include "vp_pipeline.h"
34 #include "media_vdbox_sfc_render.h"
35 #include "media_interfaces_vphal.h"
36 #include "mos_os.h"
37 #include "renderhal.h"
38 #include "media_mem_compression.h"
39 #include "media_interfaces_mhw_next.h"
40 #include "renderhal_platform_interface.h"
41 
42 using namespace vp;
43 
44 typedef MediaFactory<uint32_t, VphalDevice> VphalFactory;
45 
MediaSfcRender(PMOS_INTERFACE osInterface,MEDIA_SFC_INTERFACE_MODE mode,MediaMemComp * mmc)46 MediaSfcRender::MediaSfcRender(PMOS_INTERFACE osInterface, MEDIA_SFC_INTERFACE_MODE mode, MediaMemComp *mmc) :
47     m_osInterface(osInterface), m_mode(mode), m_mmc(mmc)
48 {
49 }
50 
~MediaSfcRender()51 MediaSfcRender::~MediaSfcRender()
52 {
53     Destroy();
54 }
55 
Destroy()56 void MediaSfcRender::Destroy()
57 {
58     MOS_STATUS status = MOS_STATUS_SUCCESS;
59     MOS_Delete(m_vdboxSfcRender);
60     MOS_Delete(m_vpPipeline);
61     MOS_Delete(m_vpPlatformInterface);
62     MOS_Delete(m_vpMhwinterface);
63 
64     if (m_renderHal)
65     {
66         if (m_renderHal->pfnDestroy)
67         {
68             status = m_renderHal->pfnDestroy(m_renderHal);
69             if (MOS_STATUS_SUCCESS != status)
70             {
71                 VP_PUBLIC_ASSERTMESSAGE("Failed to destroy RenderHal, eStatus:%d.\n", status);
72             }
73         }
74         MOS_FreeMemory(m_renderHal);
75     }
76     if (m_cpInterface)
77     {
78         if (m_osInterface)
79         {
80             m_osInterface->pfnDeleteMhwCpInterface(m_cpInterface);
81             m_cpInterface = nullptr;
82         }
83         else
84         {
85             VP_PUBLIC_ASSERTMESSAGE("Failed to destroy cpInterface.");
86         }
87     }
88 
89     if (m_veboxItf)
90     {
91         status = m_veboxItf->DestroyHeap();
92         if (MOS_FAILED(status))
93         {
94             VP_PUBLIC_ASSERTMESSAGE("Failed to destroy veboxItf heap, eStatus:%d.\n", status);
95         }
96     }
97 
98     MOS_Delete(m_statusTable);
99 }
100 
Render(VEBOX_SFC_PARAMS & sfcParam)101 MOS_STATUS MediaSfcRender::Render(VEBOX_SFC_PARAMS &sfcParam)
102 {
103     if (!m_initialized || !m_mode.veboxSfcEnabled)
104     {
105         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_UNINITIALIZED);
106     }
107 
108     VP_PUBLIC_CHK_STATUS_RETURN(IsParameterSupported(sfcParam));
109 
110     VP_PARAMS params = {};
111     params.type = PIPELINE_PARAM_TYPE_MEDIA_SFC_INTERFACE;
112     params.sfcParams = &sfcParam;
113     VP_PUBLIC_CHK_STATUS_RETURN(m_vpPipeline->Prepare(&params));
114     VP_PUBLIC_CHK_STATUS_RETURN(m_vpPipeline->Execute());
115     return MOS_STATUS_SUCCESS;
116 }
117 
Render(MOS_COMMAND_BUFFER * cmdBuffer,VDBOX_SFC_PARAMS & param)118 MOS_STATUS MediaSfcRender::Render(MOS_COMMAND_BUFFER *cmdBuffer, VDBOX_SFC_PARAMS &param)
119 {
120     if (!m_initialized || !m_mode.vdboxSfcEnabled)
121     {
122         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_UNINITIALIZED);
123     }
124 
125     VP_PUBLIC_CHK_NULL_RETURN(m_vdboxSfcRender);
126     VP_PUBLIC_CHK_NULL_RETURN(cmdBuffer);
127     VP_PUBLIC_CHK_STATUS_RETURN(IsParameterSupported(param));
128 
129     VP_PUBLIC_CHK_STATUS_RETURN(m_vdboxSfcRender->AddSfcStates(cmdBuffer, param));
130     return MOS_STATUS_SUCCESS;
131 }
132 
133 //!
134 //! \brief    MediaSfcInterface initialize
135 //! \details  Initialize the BltState, create BLT context.
136 //! \return   MOS_STATUS
137 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
138 //!
Initialize()139 MOS_STATUS MediaSfcRender::Initialize()
140 {
141     if (m_initialized)
142     {
143         return MOS_STATUS_SUCCESS;
144     }
145 
146     VphalDevice         *vphalDevice = nullptr;
147     PLATFORM            platform = {};
148     MOS_STATUS          status = MOS_STATUS_SUCCESS;
149     MEDIA_FEATURE_TABLE *skuTable = nullptr;
150     MEDIA_WA_TABLE      *waTable = nullptr;
151 
152     VP_PUBLIC_CHK_NULL_RETURN(m_osInterface);
153     VP_PUBLIC_CHK_NULL_RETURN(m_osInterface->pfnGetPlatform);
154     VP_PUBLIC_CHK_NULL_RETURN(m_osInterface->pfnGetSkuTable);
155     VP_PUBLIC_CHK_NULL_RETURN(m_osInterface->pfnGetWaTable);
156 
157     skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
158     waTable = m_osInterface->pfnGetWaTable(m_osInterface);
159 
160     VP_PUBLIC_CHK_NULL_RETURN(skuTable);
161     VP_PUBLIC_CHK_NULL_RETURN(waTable);
162 
163     // Check whether SFC supported.
164     if (!MEDIA_IS_SKU(skuTable, FtrSFCPipe))
165     {
166         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
167     }
168 
169     // Clean the garbage data if any.
170     Destroy();
171 
172     m_statusTable = MOS_New(VPHAL_STATUS_TABLE);
173     VP_PUBLIC_CHK_NULL_RETURN(m_statusTable);
174 
175     // Create platform interface and vp pipeline by vphalDevice.
176     m_osInterface->pfnGetPlatform(m_osInterface, &platform);
177     vphalDevice = VphalFactory::Create(platform.eProductFamily);
178     VP_PUBLIC_CHK_NULL_RETURN(vphalDevice);
179 
180     if (m_mode.veboxSfcEnabled)
181     {
182         if (vphalDevice->Initialize(m_osInterface, false, &status) != MOS_STATUS_SUCCESS)
183         {
184             vphalDevice->Destroy();
185             MOS_Delete(vphalDevice);
186             return status;
187         }
188         if (nullptr == vphalDevice->m_vpPipeline || nullptr == vphalDevice->m_vpPlatformInterface)
189         {
190             vphalDevice->Destroy();
191             MOS_Delete(vphalDevice);
192             return status;
193         }
194     }
195     else
196     {
197         if (vphalDevice->CreateVpPlatformInterface(m_osInterface, &status) != MOS_STATUS_SUCCESS)
198         {
199             vphalDevice->Destroy();
200             MOS_Delete(vphalDevice);
201             return status;
202         }
203         if (nullptr == vphalDevice->m_vpPlatformInterface)
204         {
205             vphalDevice->Destroy();
206             MOS_Delete(vphalDevice);
207             return status;
208         }
209     }
210 
211     m_vpPipeline = vphalDevice->m_vpPipeline;
212     m_vpPlatformInterface = vphalDevice->m_vpPlatformInterface;
213     MOS_Delete(vphalDevice);
214 
215     // Create mhw interfaces.
216     MhwInterfacesNext::CreateParams paramsNext  = {};
217     paramsNext.Flags.m_sfc                      = MEDIA_IS_SKU(skuTable, FtrSFCPipe);
218     paramsNext.Flags.m_vebox                    = MEDIA_IS_SKU(skuTable, FtrVERing);
219     MhwInterfacesNext *mhwInterfacesNext        = MhwInterfacesNext::CreateFactory(paramsNext, m_osInterface);
220 
221     VP_PUBLIC_CHK_NULL_RETURN(mhwInterfacesNext);
222     m_sfcItf         = mhwInterfacesNext->m_sfcItf;
223     m_veboxItf       = mhwInterfacesNext->m_veboxItf;
224 
225     // mi interface and cp interface will always be created during MhwInterfaces::CreateFactory.
226     // Delete them here since they will also be created by RenderHal_InitInterface.
227     m_osInterface->pfnDeleteMhwCpInterface(mhwInterfacesNext->m_cpInterface);
228     MOS_Delete(mhwInterfacesNext);
229 
230     VP_PUBLIC_CHK_NULL_RETURN(m_veboxItf);
231     const MHW_VEBOX_HEAP *veboxHeap = nullptr;
232     m_veboxItf->GetVeboxHeapInfo(&veboxHeap);
233     uint32_t uiNumInstances = m_veboxItf->GetVeboxNumInstances();
234 
235     if (uiNumInstances > 0 &&
236         veboxHeap == nullptr)
237     {
238         // Allocate VEBOX Heap
239         VP_PUBLIC_CHK_STATUS_RETURN(m_veboxItf->CreateHeap());
240     }
241 
242     // Initialize render hal.
243     m_renderHal = (PRENDERHAL_INTERFACE)MOS_AllocAndZeroMemory(sizeof(RENDERHAL_INTERFACE));
244     VP_PUBLIC_CHK_NULL_RETURN(m_renderHal);
245     VP_PUBLIC_CHK_STATUS_RETURN(RenderHal_InitInterface(
246         m_renderHal,
247         &m_cpInterface,
248         m_osInterface));
249     RENDERHAL_SETTINGS  RenderHalSettings = {};
250     RenderHalSettings.iMediaStates = 32; // Init MEdia state values
251     VP_PUBLIC_CHK_STATUS_RETURN(m_renderHal->pfnInitialize(m_renderHal, &RenderHalSettings));
252     m_miItf = m_renderHal->pRenderHalPltInterface->GetMhwMiItf();
253 
254     // Initialize vpPipeline.
255     m_vpMhwinterface = MOS_New(VP_MHWINTERFACE);
256     VP_PUBLIC_CHK_NULL_RETURN(m_vpMhwinterface);
257     MOS_ZeroMemory(m_vpMhwinterface, sizeof(VP_MHWINTERFACE));
258     m_osInterface->pfnGetPlatform(m_osInterface, &m_vpMhwinterface->m_platform);
259     m_vpMhwinterface->m_waTable                = waTable;
260     m_vpMhwinterface->m_skuTable               = skuTable;
261     m_vpMhwinterface->m_osInterface            = m_osInterface;
262     m_vpMhwinterface->m_renderHal              = m_renderHal;
263     m_vpMhwinterface->m_cpInterface            = m_cpInterface;
264     m_vpMhwinterface->m_statusTable            = m_statusTable;
265     m_vpMhwinterface->m_vpPlatformInterface    = m_vpPlatformInterface;
266     m_vpMhwinterface->m_settings               = nullptr;
267     m_vpMhwinterface->m_reporting              = nullptr;
268     m_vpPlatformInterface->SetMhwSfcItf(m_sfcItf);
269     m_vpPlatformInterface->SetMhwVeboxItf(m_veboxItf);
270     m_vpPlatformInterface->SetMhwMiItf(m_miItf);
271     m_vpMhwinterface->m_vpPlatformInterface = m_vpPlatformInterface;
272     m_vpMhwinterface->m_bIsMediaSfcInterfaceInUse = true;
273 
274     if (m_mode.veboxSfcEnabled)
275     {
276         VP_PUBLIC_CHK_STATUS_RETURN(m_vpPipeline->Init(m_vpMhwinterface));
277     }
278     else
279     {
280         MOS_Delete(m_vpPipeline);
281     }
282 
283     if (m_mode.vdboxSfcEnabled)
284     {
285         m_vdboxSfcRender = MOS_New(MediaVdboxSfcRender);
286         VP_PUBLIC_CHK_NULL_RETURN(m_vdboxSfcRender);
287         VP_PUBLIC_CHK_STATUS_RETURN(m_vdboxSfcRender->Initialize(*m_vpMhwinterface, m_mmc));
288     }
289 
290     m_initialized = true;
291 
292     return MOS_STATUS_SUCCESS;
293 }
294 
InitScalingParams(FeatureParamScaling & scalingParams,VDBOX_SFC_PARAMS & sfcParam)295 MOS_STATUS MediaSfcRender::InitScalingParams(FeatureParamScaling &scalingParams, VDBOX_SFC_PARAMS &sfcParam)
296 {
297     if (!m_mode.vdboxSfcEnabled)
298     {
299         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_UNINITIALIZED);
300     }
301 
302     VP_PUBLIC_CHK_NULL_RETURN(sfcParam.output.surface);
303 
304     RECT                rcSrcInput          = {0, 0, (int32_t)sfcParam.input.width,             (int32_t)sfcParam.input.height              };
305     RECT                rcEffectiveSrcInput = {0, 0, (int32_t)sfcParam.input.effectiveWidth,    (int32_t)sfcParam.input.effectiveHeight     };
306     RECT                rcOutput            = {0, 0, (int32_t)sfcParam.output.surface->dwWidth, (int32_t)sfcParam.output.surface->dwHeight  };
307 
308     scalingParams.type                      = FeatureTypeScalingOnSfc;
309     scalingParams.formatInput               = sfcParam.input.format;
310     scalingParams.formatOutput              = sfcParam.output.surface->Format;
311     scalingParams.scalingMode               = VPHAL_SCALING_AVS;
312     scalingParams.scalingPreference         = VPHAL_SCALING_PREFER_SFC;              //!< DDI indicate Scaling preference
313     scalingParams.bDirectionalScalar        = false;                                 //!< Vebox Directional Scalar
314     scalingParams.input.rcSrc               = rcEffectiveSrcInput;                   //!< rcEffectiveSrcInput exclude right/bottom padding area of SFC input.
315     scalingParams.input.rcDst               = sfcParam.output.rcDst;
316     scalingParams.input.rcMaxSrc            = rcSrcInput;
317     scalingParams.input.dwWidth             = sfcParam.input.width;                  //!< No input crop support for VD mode. Input Frame Height/Width must have same width/height of decoded frames.
318     scalingParams.input.dwHeight            = sfcParam.input.height;
319     scalingParams.output.rcSrc              = rcOutput;
320     scalingParams.output.rcDst              = rcOutput;
321     scalingParams.output.rcMaxSrc           = rcOutput;
322     scalingParams.output.dwWidth            = sfcParam.output.surface->dwWidth;
323     scalingParams.output.dwHeight           = sfcParam.output.surface->dwHeight;
324     scalingParams.pColorFillParams          = nullptr;
325     scalingParams.pCompAlpha                = nullptr;
326     scalingParams.csc.colorSpaceOutput      = sfcParam.output.colorSpace;
327     return MOS_STATUS_SUCCESS;
328 }
329 
InitScalingParams(FeatureParamScaling & scalingParams,VEBOX_SFC_PARAMS & sfcParam)330 MOS_STATUS MediaSfcRender::InitScalingParams(FeatureParamScaling &scalingParams, VEBOX_SFC_PARAMS &sfcParam)
331 {
332     if (!m_mode.veboxSfcEnabled)
333     {
334         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_UNINITIALIZED);
335     }
336 
337     VP_PUBLIC_CHK_NULL_RETURN(sfcParam.input.surface);
338     VP_PUBLIC_CHK_NULL_RETURN(sfcParam.output.surface);
339 
340     scalingParams.scalingMode            = VPHAL_SCALING_AVS;
341     scalingParams.scalingPreference      = VPHAL_SCALING_PREFER_SFC;
342     scalingParams.bDirectionalScalar     = false;
343     scalingParams.formatInput            = sfcParam.input.surface->Format;
344     scalingParams.input.rcSrc            = sfcParam.input.rcSrc;
345     scalingParams.input.rcMaxSrc         = sfcParam.input.rcSrc;
346     scalingParams.input.dwWidth          = sfcParam.input.surface->dwWidth;
347     scalingParams.input.dwHeight         = sfcParam.input.surface->dwHeight;
348     scalingParams.formatOutput           = sfcParam.output.surface->Format;
349     scalingParams.csc.colorSpaceOutput   = sfcParam.output.colorSpace;
350     scalingParams.pColorFillParams       = nullptr;
351     scalingParams.pCompAlpha             = nullptr;
352 
353     RECT recOutput = {0, 0, (int32_t)sfcParam.output.surface->dwWidth, (int32_t)sfcParam.output.surface->dwHeight};
354 
355     if (sfcParam.input.rotation == (MEDIA_ROTATION)VPHAL_ROTATION_IDENTITY    ||
356         sfcParam.input.rotation == (MEDIA_ROTATION)VPHAL_ROTATION_180         ||
357         sfcParam.input.rotation == (MEDIA_ROTATION)VPHAL_MIRROR_HORIZONTAL    ||
358         sfcParam.input.rotation == (MEDIA_ROTATION)VPHAL_MIRROR_VERTICAL)
359     {
360         scalingParams.output.dwWidth    = sfcParam.output.surface->dwWidth;
361         scalingParams.output.dwHeight   = sfcParam.output.surface->dwHeight;
362         scalingParams.input.rcDst       = sfcParam.output.rcDst;
363         scalingParams.output.rcSrc      = recOutput;
364         scalingParams.output.rcDst      = recOutput;
365         scalingParams.output.rcMaxSrc   = recOutput;
366     }
367     else
368     {
369         scalingParams.output.dwWidth     = sfcParam.output.surface->dwHeight;
370         scalingParams.output.dwHeight    = sfcParam.output.surface->dwWidth;
371         RECT_ROTATE(scalingParams.input.rcDst, sfcParam.output.rcDst);
372         RECT_ROTATE(scalingParams.output.rcSrc, recOutput);
373         RECT_ROTATE(scalingParams.output.rcDst, recOutput);
374         RECT_ROTATE(scalingParams.output.rcMaxSrc, recOutput);
375     }
376     return MOS_STATUS_SUCCESS;
377 }
378 
IsParameterSupported(VDBOX_SFC_PARAMS & sfcParam)379 MOS_STATUS MediaSfcRender::IsParameterSupported(
380     VDBOX_SFC_PARAMS                    &sfcParam)
381 {
382     if (!m_mode.vdboxSfcEnabled)
383     {
384         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_UNINITIALIZED);
385     }
386 
387     VP_PUBLIC_CHK_NULL_RETURN(sfcParam.output.surface);
388     VP_PUBLIC_CHK_NULL_RETURN(m_vdboxSfcRender);
389     VP_PUBLIC_CHK_NULL_RETURN(m_sfcItf);
390 
391     VpScalingFilter scalingFilter(m_vpMhwinterface);
392     FeatureParamScaling scalingParams = {};
393 
394     VP_PUBLIC_CHK_STATUS_RETURN(InitScalingParams(scalingParams, sfcParam));
395 
396     VP_EXECUTE_CAPS vpExecuteCaps   = {};
397     vpExecuteCaps.bSFC              = 1;
398     vpExecuteCaps.bSfcCsc           = 1;
399     vpExecuteCaps.bSfcScaling       = 1;
400     vpExecuteCaps.bSfcRotMir        = 1;
401 
402     VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.Init(sfcParam.videoParams.codecStandard, sfcParam.videoParams.jpeg.jpegChromaType));
403     VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.SetExecuteEngineCaps(scalingParams, vpExecuteCaps));
404     VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.CalculateEngineParams());
405 
406     SFC_SCALING_PARAMS *params = scalingFilter.GetSfcParams();
407     VP_PUBLIC_CHK_NULL_RETURN(params);
408 
409     // Check original input size (for JPEG)
410     uint32_t minWidth = 0, minHeight = 0, maxWidth = 0, maxHeight = 0;
411     VP_PUBLIC_CHK_STATUS_RETURN(m_sfcItf->GetMinWidthHeightInfo(minWidth, minHeight));
412     VP_PUBLIC_CHK_STATUS_RETURN(m_sfcItf->GetMaxWidthHeightInfo(maxWidth, maxHeight));
413     if (!MOS_WITHIN_RANGE(sfcParam.input.width, minWidth, maxWidth) ||
414         !MOS_WITHIN_RANGE(sfcParam.input.height, minHeight, maxHeight))
415     {
416         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
417     }
418 
419     // Check input size
420     if (!MOS_WITHIN_RANGE(params->dwInputFrameWidth, minWidth, maxWidth) ||
421         !MOS_WITHIN_RANGE(params->dwInputFrameHeight, minHeight, maxHeight))
422     {
423         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
424     }
425 
426     // Check output size
427     if (!MOS_WITHIN_RANGE(params->dwOutputFrameWidth, minWidth, maxWidth) ||
428         !MOS_WITHIN_RANGE(params->dwOutputFrameHeight, minHeight, maxHeight))
429     {
430         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
431     }
432 
433     // Check output region rectangles
434     if ((scalingParams.input.rcDst.bottom - scalingParams.input.rcDst.top > (int32_t)scalingParams.output.dwHeight) ||
435         (scalingParams.input.rcDst.right - scalingParams.input.rcDst.left > (int32_t)scalingParams.output.dwWidth))
436     {
437         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
438     }
439 
440     float minScalingRatio = 0, maxScalingRatio = 0;
441     VP_PUBLIC_CHK_STATUS_RETURN(m_sfcItf->GetScalingRatioLimit(minScalingRatio, maxScalingRatio));
442 
443     // Check scaling ratio
444     if (!MOS_WITHIN_RANGE(params->fAVSXScalingRatio, minScalingRatio, maxScalingRatio) ||
445         !MOS_WITHIN_RANGE(params->fAVSYScalingRatio, minScalingRatio, maxScalingRatio))
446     {
447         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
448     }
449 
450     // Check input and output format (limited only to current decode processing usage)
451     if (!m_vdboxSfcRender->IsVdboxSfcFormatSupported(sfcParam.videoParams.codecStandard, sfcParam.input.format, sfcParam.output.surface->Format, sfcParam.output.surface->TileType))
452     {
453         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
454     }
455 
456     return MOS_STATUS_SUCCESS;
457 }
458 
IsParameterSupported(VEBOX_SFC_PARAMS & sfcParam)459 MOS_STATUS MediaSfcRender::IsParameterSupported(
460     VEBOX_SFC_PARAMS                    &sfcParam)
461 {
462     if (!m_mode.veboxSfcEnabled)
463     {
464         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_UNINITIALIZED);
465     }
466 
467     VP_PUBLIC_CHK_NULL_RETURN(sfcParam.input.surface);
468     VP_PUBLIC_CHK_NULL_RETURN(sfcParam.output.surface);
469     VP_PUBLIC_CHK_NULL_RETURN(m_sfcItf);
470 
471     VpScalingFilter scalingFilter(m_vpMhwinterface);
472     FeatureParamScaling scalingParams = {};
473 
474     VP_PUBLIC_CHK_STATUS_RETURN(InitScalingParams(scalingParams, sfcParam));
475 
476     VP_EXECUTE_CAPS vpExecuteCaps   = {};
477     vpExecuteCaps.bSFC              = 1;
478     vpExecuteCaps.bSfcCsc           = 1;
479     vpExecuteCaps.bSfcScaling       = 1;
480     vpExecuteCaps.bSfcRotMir        = 1;
481 
482     VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.Init());
483     VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.SetExecuteEngineCaps(scalingParams, vpExecuteCaps));
484     VP_PUBLIC_CHK_STATUS_RETURN(scalingFilter.CalculateEngineParams());
485 
486     SFC_SCALING_PARAMS *params = scalingFilter.GetSfcParams();
487     VP_PUBLIC_CHK_NULL_RETURN(params);
488 
489     // Check original input size
490     uint32_t minInputWidth = 0, minInputHeight = 0, minOutputWidth = 0, minOutputHeight = 0, maxWidth = 0, maxHeight = 0;
491     VP_PUBLIC_CHK_STATUS_RETURN(m_sfcItf->GetInputMinWidthHeightInfo(minInputWidth, minInputHeight));
492     VP_PUBLIC_CHK_STATUS_RETURN(m_sfcItf->GetOutputMinWidthHeightInfo(minOutputWidth, minOutputHeight));
493     VP_PUBLIC_CHK_STATUS_RETURN(m_sfcItf->GetMaxWidthHeightInfo(maxWidth, maxHeight));
494 
495     // Check input size
496     if (!MOS_WITHIN_RANGE(params->dwInputFrameWidth, minInputWidth, maxWidth) ||
497         !MOS_WITHIN_RANGE(params->dwInputFrameHeight, minInputHeight, maxHeight))
498     {
499         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
500     }
501 
502     // Check output size
503     if (!MOS_WITHIN_RANGE(params->dwOutputFrameWidth, minOutputWidth, maxWidth) ||
504         !MOS_WITHIN_RANGE(params->dwOutputFrameHeight, minOutputHeight, maxHeight))
505     {
506         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
507     }
508 
509     // Check input region rectangles
510     if ((scalingParams.input.rcSrc.bottom - scalingParams.input.rcSrc.top > (int32_t)scalingParams.input.dwHeight) ||
511         (scalingParams.input.rcSrc.right - scalingParams.input.rcSrc.left > (int32_t)scalingParams.input.dwWidth))
512     {
513         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
514     }
515 
516     // Check output region rectangles
517     if ((scalingParams.input.rcDst.bottom - scalingParams.input.rcDst.top > (int32_t)scalingParams.output.dwHeight) ||
518         (scalingParams.input.rcDst.right - scalingParams.input.rcDst.left > (int32_t)scalingParams.output.dwWidth))
519     {
520         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
521     }
522 
523     float minScalingRatio = 0, maxScalingRatio = 0;
524     VP_PUBLIC_CHK_STATUS_RETURN(m_sfcItf->GetScalingRatioLimit(minScalingRatio, maxScalingRatio));
525     // Check scaling ratio
526     if (!MOS_WITHIN_RANGE(params->fAVSXScalingRatio, minScalingRatio, maxScalingRatio) ||
527         !MOS_WITHIN_RANGE(params->fAVSYScalingRatio, minScalingRatio, maxScalingRatio))
528     {
529         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
530     }
531 
532     // Check input and output format
533     if (!m_vpPipeline->IsVeboxSfcFormatSupported(sfcParam.input.surface->Format, sfcParam.output.surface->Format))
534     {
535         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
536     }
537 
538     return MOS_STATUS_SUCCESS;
539 }
540