1 // Copyright (c) 2018-2020 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20
21 #include "math.h"
22 #include "mfx_common.h"
23
24 #if defined (MFX_ENABLE_VPP)
25 #include "mfx_enc_common.h"
26 #include "mfx_session.h"
27
28 #include "mfx_vpp_hw.h"
29
30 #include "mfx_vpp_sw.h"
31 #include "mfx_vpp_utils.h"
32
33 // internal filters
34 #include "mfx_denoise_vpp.h"
35 #include "mfx_color_space_conversion_vpp.h"
36 #include "mfx_resize_vpp.h"
37 #include "mfx_shift_vpp.h"
38 #include "mfx_deinterlace_vpp.h"
39 #include "mfx_video_analysis_vpp.h"
40 #include "mfx_frame_rate_conversion_vpp.h"
41 #include "mfx_procamp_vpp.h"
42 #include "mfx_detail_enhancement_vpp.h"
43
44
45 //-----------------------------------------------------------------------------
46 // independent functions
47 //-----------------------------------------------------------------------------
48
49 // all check must be done before call
GetExternalFramesCount(VideoCORE * core,mfxVideoParam * pParam,mfxU32 * pListID,mfxU32 len,mfxU16 framesCountMin[2],mfxU16 framesCountSuggested[2])50 mfxStatus GetExternalFramesCount(VideoCORE* core,
51 mfxVideoParam* pParam,
52 mfxU32* pListID,
53 mfxU32 len,
54 mfxU16 framesCountMin[2],
55 mfxU16 framesCountSuggested[2])
56 {
57 mfxU32 filterIndex;
58 mfxU16 inputFramesCount[MAX_NUM_VPP_FILTERS] = {0};
59 mfxU16 outputFramesCount[MAX_NUM_VPP_FILTERS] = {0};
60
61 for( filterIndex = 0; filterIndex < len; filterIndex++ )
62 {
63 switch( pListID[filterIndex] )
64 {
65
66 case (mfxU32)MFX_EXTBUFF_VPP_RSHIFT_IN:
67 case (mfxU32)MFX_EXTBUFF_VPP_RSHIFT_OUT:
68 case (mfxU32)MFX_EXTBUFF_VPP_LSHIFT_IN:
69 case (mfxU32)MFX_EXTBUFF_VPP_LSHIFT_OUT:
70 {
71 inputFramesCount[filterIndex] = MFXVideoVPPShift::GetInFramesCountExt();
72 outputFramesCount[filterIndex] = MFXVideoVPPShift::GetOutFramesCountExt();
73 break;
74 }
75
76 case (mfxU32)MFX_EXTBUFF_VPP_DENOISE:
77 {
78 inputFramesCount[filterIndex] = MFXVideoVPPDenoise::GetInFramesCountExt();
79 outputFramesCount[filterIndex] = MFXVideoVPPDenoise::GetOutFramesCountExt();
80 break;
81 }
82
83 #ifdef MFX_ENABLE_MCTF
84 case (mfxU32)MFX_EXTBUFF_VPP_MCTF:
85 {
86 mfxU16 MctfTemporalMode = CMC::DEFAULT_REFS;
87 #ifdef MFX_ENABLE_MCTF_EXT
88 mfxExtVppMctf* mctf_ctrl = reinterpret_cast<mfxExtVppMctf *>(GetExtendedBuffer(pParam->ExtParam, pParam->NumExtParam, MFX_EXTBUFF_VPP_MCTF));
89 MctfTemporalMode = mctf_ctrl ? mctf_ctrl->TemporalMode : CMC::DEFAULT_REFS;
90 // should process UNKNOWN mode here or its an error?
91 if (MCTF_TEMPORAL_MODE_UNKNOWN == MctfTemporalMode)
92 MctfTemporalMode = CMC::DEFAULT_REFS;
93 #endif
94 switch (MctfTemporalMode)
95 {
96 case MCTF_TEMPORAL_MODE_SPATIAL:
97 // this is for spatial filtering mode only; 1 input is enough
98 inputFramesCount[filterIndex] = 1;
99 outputFramesCount[filterIndex] = 1;
100 break;
101 case MCTF_TEMPORAL_MODE_1REF:
102 // preasumably, this is for filtering mode with 1 backward refernce; 1 input is enough
103 inputFramesCount[filterIndex] = 1;
104 outputFramesCount[filterIndex] = 1;
105 break;
106 case MCTF_TEMPORAL_MODE_2REF:
107 // this is bi-directional MCTF with 2 referencies; thus 2 inputs are needed
108 inputFramesCount[filterIndex] = 2;
109 outputFramesCount[filterIndex] = 2;
110 break;
111 case MCTF_TEMPORAL_MODE_4REF:
112 // this is bi-directional MCTF with 4 references(its not a mistake! thus 3 inputs are needed
113 inputFramesCount[filterIndex] = 3;
114 outputFramesCount[filterIndex] = 3;
115 break;
116 default:
117 return MFX_ERR_INVALID_VIDEO_PARAM;
118
119 }
120 break;
121 }
122 #endif
123 case (mfxU32)MFX_EXTBUFF_VPP_RESIZE:
124 {
125 inputFramesCount[filterIndex] = MFXVideoVPPResize::GetInFramesCountExt();
126 outputFramesCount[filterIndex] = MFXVideoVPPResize::GetOutFramesCountExt();
127 break;
128 }
129
130 case (mfxU32)MFX_EXTBUFF_VPP_ROTATION:
131 {
132 inputFramesCount[filterIndex] = 1;
133 outputFramesCount[filterIndex] = 1;
134 break;
135 }
136
137 case (mfxU32)MFX_EXTBUFF_VPP_SCALING:
138 {
139 break;
140 }
141
142 #if (MFX_VERSION >= 1025)
143 case (mfxU32)MFX_EXTBUFF_VPP_COLOR_CONVERSION:
144 {
145 break;
146 }
147 #endif
148
149 case (mfxU32)MFX_EXTBUFF_VPP_MIRRORING:
150 {
151 break;
152 }
153
154 case (mfxU32)MFX_EXTBUFF_VPP_DEINTERLACING:
155 {
156 break;
157 }
158
159 case (mfxU32)MFX_EXTBUFF_VPP_ITC:
160 case (mfxU32)MFX_EXTBUFF_VPP_DI:
161 {
162 inputFramesCount[filterIndex] = MFXVideoVPPDeinterlace::GetInFramesCountExt();
163 outputFramesCount[filterIndex] = MFXVideoVPPDeinterlace::GetOutFramesCountExt();
164 break;
165 }
166
167 case (mfxU32)MFX_EXTBUFF_VPP_DI_30i60p:
168 {
169 inputFramesCount[filterIndex] = MFXVideoVPPDeinterlace::GetInFramesCountExt();
170 outputFramesCount[filterIndex] = MFXVideoVPPDeinterlace::GetOutFramesCountExt() << 1;
171 break;
172 }
173
174 case (mfxU32)MFX_EXTBUFF_VPP_DI_WEAVE:
175 {
176 inputFramesCount[filterIndex] = MFXVideoVPPDeinterlace::GetInFramesCountExt() << 1;
177 outputFramesCount[filterIndex] = MFXVideoVPPDeinterlace::GetOutFramesCountExt();
178 break;
179 }
180
181 case (mfxU32)MFX_EXTBUFF_VPP_CSC:
182 case (mfxU32)MFX_EXTBUFF_VPP_CSC_OUT_RGB4:
183 case (mfxU32)MFX_EXTBUFF_VPP_CSC_OUT_A2RGB10:
184 case (mfxU32)MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO:
185 {
186 inputFramesCount[filterIndex] = MFXVideoVPPColorSpaceConversion::GetInFramesCountExt();
187 outputFramesCount[filterIndex] = MFXVideoVPPColorSpaceConversion::GetOutFramesCountExt();
188 break;
189 }
190
191 case (mfxU32)MFX_EXTBUFF_VPP_SCENE_ANALYSIS:
192 {
193 inputFramesCount[filterIndex] = MFXVideoVPPVideoAnalysis::GetInFramesCountExt();
194
195 outputFramesCount[filterIndex] = MFXVideoVPPVideoAnalysis::GetOutFramesCountExt();
196 break;
197 }
198
199 case (mfxU32)MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION:
200 {
201 // call Get[In/Out]FramesCountExt not correct for external application
202 // result must be based on in/out frame rates
203 mfxFrameInfo info;
204
205 info = pParam->vpp.In;
206 mfxF64 inFrameRate = CalculateUMCFramerate(info.FrameRateExtN, info.FrameRateExtD);
207 if (fabs(inFrameRate-0) < 0.01)
208 {
209 return MFX_ERR_INVALID_VIDEO_PARAM;
210 }
211
212 info = pParam->vpp.Out;
213 mfxF64 outFrameRate = CalculateUMCFramerate(info.FrameRateExtN, info.FrameRateExtD);
214
215 outputFramesCount[ filterIndex ] = (mfxU16)(ceil(outFrameRate / inFrameRate));
216 outputFramesCount[ filterIndex ] = std::max<mfxU16>(outputFramesCount[ filterIndex ], 1);//robustness
217
218 // numInFrames = inFrameRate / inFrameRate = 1;
219 inputFramesCount[ filterIndex ] = 1;
220
221 // after analysis for correct FRC processing we require following equations
222 inputFramesCount[ filterIndex ] = std::max<mfxU16>( inputFramesCount[ filterIndex ], MFXVideoVPPFrameRateConversion::GetInFramesCountExt() );
223 outputFramesCount[ filterIndex ] = std::max<mfxU16>( outputFramesCount[ filterIndex ], MFXVideoVPPFrameRateConversion::GetOutFramesCountExt() );
224
225 break;
226 }
227
228 case (mfxU32)MFX_EXTBUFF_VPP_PROCAMP:
229 {
230 inputFramesCount[filterIndex] = MFXVideoVPPProcAmp::GetInFramesCountExt();
231 outputFramesCount[filterIndex] = MFXVideoVPPProcAmp::GetOutFramesCountExt();
232 break;
233 }
234
235 case (mfxU32)MFX_EXTBUFF_VPP_DETAIL:
236 {
237 inputFramesCount[filterIndex] = MFXVideoVPPDetailEnhancement::GetInFramesCountExt();
238 outputFramesCount[filterIndex] = MFXVideoVPPDetailEnhancement::GetOutFramesCountExt();
239 break;
240 }
241
242
243
244 case (mfxU32)MFX_EXTBUFF_VPP_COMPOSITE:
245 {
246 for (mfxU32 i = 0; i < pParam->NumExtParam; i++)
247 {
248 if (pParam->ExtParam[i]->BufferId == MFX_EXTBUFF_VPP_COMPOSITE)
249 {
250 mfxExtVPPComposite* extComp = (mfxExtVPPComposite*) pParam->ExtParam[i];
251 if (extComp->NumInputStream > MAX_NUM_OF_VPP_COMPOSITE_STREAMS)
252 {
253 return MFX_ERR_INVALID_VIDEO_PARAM;
254 }
255 else
256 {
257 if ((core->GetVAType() == MFX_HW_D3D9) && (extComp->NumInputStream > MAX_STREAMS_PER_TILE))
258 return MFX_ERR_INVALID_VIDEO_PARAM;
259 inputFramesCount[filterIndex] = extComp->NumInputStream;
260 }
261
262 for(mfxU32 j = 0; j < extComp->NumInputStream; j++)
263 {
264 if (pParam->vpp.Out.Width < (extComp->InputStream[j].DstX + extComp->InputStream[j].DstW))
265 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
266 if (pParam->vpp.Out.Height < (extComp->InputStream[j].DstY + extComp->InputStream[j].DstH))
267 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
268 }
269 }
270 } /*for (mfxU32 i = 0; i < pParam->NumExtParam; i++)*/
271
272 /* for output always one */
273 outputFramesCount[filterIndex] = 1;
274 break;
275 }
276
277 case (mfxU32)MFX_EXTBUFF_VPP_FIELD_PROCESSING:
278 {
279 inputFramesCount[filterIndex] = 1;
280 outputFramesCount[filterIndex] = 1;
281 break;
282 }
283
284 case (mfxU32)MFX_EXTBUFF_VPP_FIELD_WEAVING:
285 {
286 inputFramesCount[filterIndex] = 2;
287 outputFramesCount[filterIndex] = 1;
288 break;
289 }
290
291 case (mfxU32)MFX_EXTBUFF_VPP_FIELD_SPLITTING:
292 {
293 inputFramesCount[filterIndex] = 1;
294 outputFramesCount[filterIndex] = 2;
295 break;
296 }
297
298 default:
299 {
300 return MFX_ERR_INVALID_VIDEO_PARAM;
301 }
302
303 }// CASE
304 }//end of
305
306 framesCountSuggested[VPP_IN] = vppMax_16u(inputFramesCount, len);
307 framesCountSuggested[VPP_OUT] = vppMax_16u(outputFramesCount, len);
308
309
310 // so, SW min frames must be equal MAX(filter0, filter1, ..., filterN-1)
311 framesCountMin[VPP_IN] = framesCountSuggested[VPP_IN];
312 framesCountMin[VPP_OUT] = framesCountSuggested[VPP_OUT];
313
314 //robustness
315 if( VPP_MAX_REQUIRED_FRAMES_COUNT < framesCountMin[VPP_IN] )
316 {
317 framesCountMin[VPP_IN] = VPP_MAX_REQUIRED_FRAMES_COUNT;
318 }
319
320 if( VPP_MAX_REQUIRED_FRAMES_COUNT < framesCountMin[VPP_OUT] )
321 {
322 framesCountMin[VPP_OUT] = VPP_MAX_REQUIRED_FRAMES_COUNT;
323 }
324
325 return MFX_ERR_NONE;
326
327 } // mfxStatus GetExternalFramesCount(...)
328
329 // all check must be done before call
IsCompositionMode(mfxVideoParam * pParam)330 bool IsCompositionMode(mfxVideoParam* pParam)
331 {
332 if (pParam->ExtParam && pParam->NumExtParam > 0)
333 {
334 for (mfxU32 i = 0; i < pParam->NumExtParam; ++i)
335 {
336 mfxExtBuffer *pExtBuffer = pParam->ExtParam[i];
337 if (pExtBuffer->BufferId == (mfxU32)MFX_EXTBUFF_VPP_COMPOSITE)
338 return true;
339 }
340 }
341
342 return false;
343 }
344
ExtendedQuery(VideoCORE * core,mfxU32 filterName,mfxExtBuffer * pHint)345 mfxStatus ExtendedQuery(VideoCORE * core, mfxU32 filterName, mfxExtBuffer* pHint)
346 {
347 mfxStatus sts = MFX_ERR_NONE;
348
349 if( MFX_EXTBUFF_VPP_DENOISE == filterName )
350 {
351 sts = MFXVideoVPPDenoise::Query( pHint );
352 }
353 #ifdef MFX_ENABLE_MCTF
354 else if (MFX_EXTBUFF_VPP_MCTF == filterName)
355 {
356 sts = CMC::CheckAndFixParams((mfxExtVppMctf*)pHint);
357 }
358 #endif
359 else if( MFX_EXTBUFF_VPP_DETAIL == filterName )
360 {
361 sts = MFXVideoVPPDetailEnhancement::Query( pHint );
362 }
363 else if( MFX_EXTBUFF_VPP_PROCAMP == filterName )
364 {
365 sts = MFXVideoVPPProcAmp::Query( pHint );
366 }
367 else if( MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION == filterName )
368 {
369 sts = MFXVideoVPPFrameRateConversion::Query( pHint );
370 }
371 else if( MFX_EXTBUFF_VPP_SCENE_ANALYSIS == filterName )
372 {
373 sts = MFX_ERR_UNSUPPORTED;
374 }
375 else if( MFX_EXTBUFF_VPP_COMPOSITE == filterName )
376 {
377 if ((NULL != core) && (MFX_PLATFORM_SOFTWARE == core->GetPlatformType()))
378 {
379 sts = MFX_ERR_UNSUPPORTED;
380 }
381 else
382 {
383 sts = MFX_ERR_NONE;
384 }
385 }
386 else if( MFX_EXTBUFF_VPP_FIELD_PROCESSING == filterName )
387 {
388 if ((NULL != core) && (MFX_PLATFORM_SOFTWARE == core->GetPlatformType()))
389 {
390 sts = MFX_ERR_UNSUPPORTED;
391 }
392 else
393 {
394 sts = MFX_ERR_NONE;
395 }
396 }
397 else if (MFX_EXTBUFF_VPP_SCALING == filterName)
398 {
399 sts = CheckScalingParam(pHint);
400 }
401 else // ignore
402 {
403 sts = MFX_ERR_NONE;
404 }
405
406 return sts;
407
408 } // mmfxStatus ExtendedQuery(VideoCORE * core, mfxU32 filterName, mfxExtBuffer* pHint)
409
410 #endif // MFX_ENABLE_VPP
411 /* EOF */
412