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