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_vdbox_sfc_render.cpp
24 //! \brief    Common interface for sfc
25 //! \details  Common interface for sfc
26 //!
27 #include "vp_feature_manager.h"
28 #include "media_sfc_interface.h"
29 #include "media_vdbox_sfc_render.h"
30 #include "mos_os.h"
31 #include "vp_render_sfc_base.h"
32 #include "vp_render_ief.h"
33 #include "vp_mem_compression.h"
34 
35 using namespace vp;
36 
MediaVdboxSfcRender()37 MediaVdboxSfcRender::MediaVdboxSfcRender()
38 {
39 }
40 
~MediaVdboxSfcRender()41 MediaVdboxSfcRender::~MediaVdboxSfcRender()
42 {
43     Destroy();
44 }
45 
Destroy()46 void MediaVdboxSfcRender::Destroy()
47 {
48     MOS_Delete(m_sfcRender);
49     MOS_Delete(m_cscFilter);
50     MOS_Delete(m_scalingFilter);
51     MOS_Delete(m_rotMirFilter);
52     MOS_Delete(m_allocator);
53     if (m_isMmcAllocated)
54     {
55         MOS_Delete(m_mmc);
56     }
57 }
58 
59 //!
60 //! \brief    MediaSfcInterface initialize
61 //! \details  Initialize the BltState, create BLT context.
62 //! \return   MOS_STATUS
63 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
64 //!
Initialize(VP_MHWINTERFACE & vpMhwinterface,MediaMemComp * mmc)65 MOS_STATUS MediaVdboxSfcRender::Initialize(VP_MHWINTERFACE &vpMhwinterface, MediaMemComp *mmc)
66 {
67     VP_PUBLIC_CHK_NULL_RETURN(vpMhwinterface.m_vpPlatformInterface);
68     VP_PUBLIC_CHK_NULL_RETURN(vpMhwinterface.m_osInterface);
69 
70     m_vpMhwInterface    = vpMhwinterface;
71     m_osInterface       = m_vpMhwInterface.m_osInterface;
72 
73     if (mmc)
74     {
75         m_mmc = mmc;
76         m_isMmcAllocated = false;
77     }
78     else
79     {
80         m_mmc = MOS_New(VPMediaMemComp, m_osInterface, m_vpMhwInterface);
81         VP_PUBLIC_CHK_NULL_RETURN(m_mmc);
82         m_isMmcAllocated = true;
83     }
84 
85     m_allocator         = MOS_New(VpAllocator, m_osInterface, m_mmc);
86     VP_PUBLIC_CHK_NULL_RETURN(m_allocator);
87     m_cscFilter         = MOS_New(VpCscFilter, &m_vpMhwInterface);
88     VP_PUBLIC_CHK_NULL_RETURN(m_cscFilter);
89     m_scalingFilter     = MOS_New(VpScalingFilter, &m_vpMhwInterface);
90     VP_PUBLIC_CHK_NULL_RETURN(m_scalingFilter);
91     m_rotMirFilter      = MOS_New(VpRotMirFilter, &m_vpMhwInterface);
92     VP_PUBLIC_CHK_NULL_RETURN(m_rotMirFilter);
93     VP_PUBLIC_CHK_STATUS_RETURN(m_vpMhwInterface.m_vpPlatformInterface->CreateSfcRender(m_sfcRender, m_vpMhwInterface, m_allocator));
94     VP_PUBLIC_CHK_NULL_RETURN(m_sfcRender);
95     return MOS_STATUS_SUCCESS;
96 }
97 
SetCSCParams(VDBOX_SFC_PARAMS & sfcParam,VP_EXECUTE_CAPS & vpExecuteCaps)98 MOS_STATUS MediaVdboxSfcRender::SetCSCParams(VDBOX_SFC_PARAMS &sfcParam, VP_EXECUTE_CAPS &vpExecuteCaps)
99 {
100     VP_PUBLIC_CHK_NULL_RETURN(m_sfcRender);
101     VP_PUBLIC_CHK_NULL_RETURN(m_cscFilter);
102     FeatureParamCsc cscParams       = {};
103     cscParams.type                  = FeatureTypeCscOnSfc;
104     cscParams.formatInput           = sfcParam.input.format;
105     cscParams.formatOutput          = sfcParam.output.surface->Format;
106     cscParams.input.colorSpace      = sfcParam.input.colorSpace;
107     cscParams.output.colorSpace     = sfcParam.output.colorSpace;
108     cscParams.input.chromaSiting    = sfcParam.input.chromaSiting;
109     cscParams.output.chromaSiting   = sfcParam.output.chromaSiting;
110 
111     m_cscFilter->Init();
112     m_cscFilter->SetExecuteEngineCaps(cscParams, vpExecuteCaps);
113     m_cscFilter->CalculateEngineParams();
114 
115     return m_sfcRender->SetCSCParams(m_cscFilter->GetSfcParams());
116 }
117 
SetScalingParams(VDBOX_SFC_PARAMS & sfcParam,VP_EXECUTE_CAPS & vpExecuteCaps)118 MOS_STATUS MediaVdboxSfcRender::SetScalingParams(VDBOX_SFC_PARAMS &sfcParam, VP_EXECUTE_CAPS &vpExecuteCaps)
119 {
120     VP_PUBLIC_CHK_NULL_RETURN(m_sfcRender);
121     VP_PUBLIC_CHK_NULL_RETURN(m_scalingFilter);
122 
123     RECT                rcSrcInput          = {0, 0, (int32_t)sfcParam.input.width,             (int32_t)sfcParam.input.height              };
124     RECT                rcEffectiveSrcInput = {0, 0, (int32_t)sfcParam.input.effectiveWidth,    (int32_t)sfcParam.input.effectiveHeight     };
125     RECT                rcOutput            = {0, 0, (int32_t)sfcParam.output.surface->dwWidth, (int32_t)sfcParam.output.surface->dwHeight  };
126     FeatureParamScaling scalingParams       = {};
127     scalingParams.type                      = FeatureTypeScalingOnSfc;
128     scalingParams.formatInput               = sfcParam.input.format;
129     scalingParams.formatOutput              = sfcParam.output.surface->Format;
130     scalingParams.scalingMode               = GetScalingMode(sfcParam.scalingMode);
131     scalingParams.scalingPreference         = VPHAL_SCALING_PREFER_SFC;              //!< DDI indicate Scaling preference
132     scalingParams.bDirectionalScalar        = false;                                 //!< Vebox Directional Scalar
133     scalingParams.input.rcSrc               = rcEffectiveSrcInput;                   //!< rcEffectiveSrcInput exclude right/bottom padding area of SFC input.
134     scalingParams.input.rcDst               = sfcParam.output.rcDst;
135     scalingParams.input.rcMaxSrc            = rcSrcInput;
136     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.
137     scalingParams.input.dwHeight            = sfcParam.input.height;
138     scalingParams.output.rcSrc              = rcOutput;
139     scalingParams.output.rcDst              = rcOutput;
140     scalingParams.output.rcMaxSrc           = rcOutput;
141     scalingParams.output.dwWidth            = sfcParam.output.surface->dwWidth;
142     scalingParams.output.dwHeight           = sfcParam.output.surface->dwHeight;
143     scalingParams.pColorFillParams          = nullptr;
144     scalingParams.pCompAlpha                = nullptr;
145     scalingParams.csc.colorSpaceOutput      = sfcParam.output.colorSpace;
146     scalingParams.interlacedScalingType     = sfcParam.videoParams.fieldParams.isFieldToInterleaved ? ISCALING_FIELD_TO_INTERLEAVED : ISCALING_NONE;
147     if (sfcParam.videoParams.fieldParams.isFieldToInterleaved)
148     {
149         scalingParams.input.sampleType      = sfcParam.videoParams.fieldParams.isBottomField ? SAMPLE_SINGLE_BOTTOM_FIELD : SAMPLE_SINGLE_TOP_FIELD;
150         scalingParams.output.sampleType     = sfcParam.videoParams.fieldParams.isBottomFirst ? SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD : SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD;
151     }
152     else
153     {
154         scalingParams.input.sampleType      = SAMPLE_PROGRESSIVE;
155         scalingParams.output.sampleType     = SAMPLE_PROGRESSIVE;
156     }
157 
158     m_scalingFilter->Init(sfcParam.videoParams.codecStandard, sfcParam.videoParams.jpeg.jpegChromaType);
159     m_scalingFilter->SetExecuteEngineCaps(scalingParams, vpExecuteCaps);
160     m_scalingFilter->CalculateEngineParams();
161 
162     return m_sfcRender->SetScalingParams(m_scalingFilter->GetSfcParams());
163 }
164 
SetSfcMmcParams(VDBOX_SFC_PARAMS & sfcParam)165 MOS_STATUS MediaVdboxSfcRender::SetSfcMmcParams(VDBOX_SFC_PARAMS &sfcParam)
166 {
167     VP_PUBLIC_CHK_STATUS_RETURN(m_mmc->SetSurfaceMmcState(sfcParam.output.surface));
168     VP_PUBLIC_CHK_STATUS_RETURN(m_mmc->SetSurfaceMmcMode(sfcParam.output.surface));
169     VP_PUBLIC_CHK_STATUS_RETURN(m_mmc->SetSurfaceMmcFormat(sfcParam.output.surface));
170     return m_sfcRender->SetMmcParams(sfcParam.output.surface, true, m_mmc->IsMmcEnabled());
171 }
172 
SetRotMirParams(VDBOX_SFC_PARAMS & sfcParam,VP_EXECUTE_CAPS & vpExecuteCaps)173 MOS_STATUS MediaVdboxSfcRender::SetRotMirParams(VDBOX_SFC_PARAMS &sfcParam, VP_EXECUTE_CAPS &vpExecuteCaps)
174 {
175     VP_PUBLIC_CHK_NULL_RETURN(m_sfcRender);
176     VP_PUBLIC_CHK_NULL_RETURN(m_rotMirFilter);
177     FeatureParamRotMir rotMirParams     = {};
178     rotMirParams.type                   = FeatureTypeRotMirOnSfc;
179     rotMirParams.formatInput            = sfcParam.input.format;
180     rotMirParams.formatOutput           = sfcParam.output.surface->Format;
181     rotMirParams.rotation               = sfcParam.input.mirrorEnabled ? VPHAL_MIRROR_HORIZONTAL : VPHAL_ROTATION_IDENTITY;
182     rotMirParams.surfInfo.tileOutput    = sfcParam.output.surface->TileType;
183 
184     m_rotMirFilter->Init();
185     m_rotMirFilter->SetExecuteEngineCaps(rotMirParams, vpExecuteCaps);
186     m_rotMirFilter->CalculateEngineParams();
187 
188     return m_sfcRender->SetRotMirParams(m_rotMirFilter->GetSfcParams());
189 }
190 
SetHistogramParams(VDBOX_SFC_PARAMS & sfcParam)191 MOS_STATUS MediaVdboxSfcRender::SetHistogramParams(VDBOX_SFC_PARAMS& sfcParam)
192 {
193     return m_sfcRender->SetHistogramBuf(sfcParam.output.histogramBuf);
194 }
195 
AddSfcStates(MOS_COMMAND_BUFFER * cmdBuffer,VDBOX_SFC_PARAMS & sfcParam)196 MOS_STATUS MediaVdboxSfcRender::AddSfcStates(MOS_COMMAND_BUFFER *cmdBuffer, VDBOX_SFC_PARAMS &sfcParam)
197 {
198     VP_PUBLIC_CHK_NULL_RETURN(m_sfcRender);
199     VP_PUBLIC_CHK_NULL_RETURN(sfcParam.output.surface);
200     VP_PUBLIC_CHK_NULL_RETURN(cmdBuffer);
201 
202     VP_EXECUTE_CAPS vpExecuteCaps   = {};
203     vpExecuteCaps.bSFC              = 1;
204     vpExecuteCaps.bSfcCsc           = 1;
205     vpExecuteCaps.bSfcScaling       = 1;
206     vpExecuteCaps.bSfcRotMir        = 1;
207 
208     VP_PUBLIC_CHK_STATUS_RETURN(m_sfcRender->Init(sfcParam.videoParams));
209     VP_PUBLIC_CHK_STATUS_RETURN(SetCSCParams(sfcParam, vpExecuteCaps));
210     VP_PUBLIC_CHK_STATUS_RETURN(SetScalingParams(sfcParam, vpExecuteCaps));
211     VP_PUBLIC_CHK_STATUS_RETURN(SetRotMirParams(sfcParam, vpExecuteCaps));
212     VP_PUBLIC_CHK_STATUS_RETURN(SetHistogramParams(sfcParam));
213     VP_PUBLIC_CHK_STATUS_RETURN(SetSfcMmcParams(sfcParam));
214 
215     RECT        rcOutput        = {0, 0, (int32_t)sfcParam.output.surface->dwWidth, (int32_t)sfcParam.output.surface->dwHeight};
216     // The value of plane offset are different between vp and codec. updatePlaneOffset need be set to true when create vp surface
217     // with mos surface from codec hal.
218     VP_SURFACE  *renderTarget   = m_allocator->AllocateVpSurface(*sfcParam.output.surface,
219                                                             sfcParam.output.colorSpace,
220                                                             sfcParam.output.chromaSiting,
221                                                             rcOutput,
222                                                             rcOutput,
223                                                             SURF_OUT_RENDERTARGET,
224                                                             true);
225 
226     //---------------------------------
227     // Send CMD: SFC pipe commands
228     //---------------------------------
229 
230     VP_RENDER_CHK_STATUS_RETURN(m_sfcRender->SetupSfcState(renderTarget));
231     VP_RENDER_CHK_STATUS_RETURN(m_sfcRender->SendSfcCmd(
232                             CODECHAL_JPEG != sfcParam.videoParams.codecStandard,
233                             cmdBuffer));
234 
235     m_allocator->DestroyVpSurface(renderTarget);
236     m_allocator->CleanRecycler();
237 
238     return MOS_STATUS_SUCCESS;
239 }
240 
GetScalingMode(CODECHAL_SCALING_MODE scalingMode)241 VPHAL_SCALING_MODE MediaVdboxSfcRender::GetScalingMode(CODECHAL_SCALING_MODE scalingMode)
242 {
243     // Default mode is VPHAL_SCALING_AVS
244     VPHAL_SCALING_MODE sfcScalingMode = VPHAL_SCALING_AVS;
245 
246     switch(scalingMode)
247     {
248     case CODECHAL_SCALING_BILINEAR:
249         sfcScalingMode = VPHAL_SCALING_BILINEAR;
250         break;
251     case CODECHAL_SCALING_NEAREST:
252     case CODECHAL_SCALING_AVS:
253     case CODECHAL_SCALING_ADV_QUALITY:
254     default:
255         sfcScalingMode = VPHAL_SCALING_AVS;
256         break;
257     }
258 
259     return sfcScalingMode;
260 }
261 
IsVdboxSfcFormatSupported(CODECHAL_STANDARD codecStandard,MOS_FORMAT inputFormat,MOS_FORMAT outputFormat,MOS_TILE_TYPE tileType)262 bool MediaVdboxSfcRender::IsVdboxSfcFormatSupported(
263     CODECHAL_STANDARD           codecStandard,
264     MOS_FORMAT                  inputFormat,
265     MOS_FORMAT                  outputFormat,
266     MOS_TILE_TYPE               tileType)
267 {
268     if (nullptr == m_sfcRender)
269     {
270         return false;
271     }
272 
273     return (m_sfcRender->IsVdboxSfcInputFormatSupported(codecStandard, inputFormat) &&
274             m_sfcRender->IsVdboxSfcOutputFormatSupported(codecStandard, outputFormat, tileType));
275 }
276