1 // Copyright (c) 2017-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 #ifndef __MFXUTILS_H__
22 #define __MFXUTILS_H__
23 
24 #include "mfx_config.h"
25 
26 #include "mfxstructures.h"
27 #include "mfxplugin.h"
28 
29 #include "umc_structures.h"
30 #include "mfx_trace.h"
31 #include "mfx_timing.h"
32 
33 #include <cassert>
34 #include <cstddef>
35 
36 #if defined(MFX_VA_LINUX)
37 #include <va/va.h>
38 #endif
39 
40 #include "mfx_utils_defs.h"
41 
42 
43 
44 static const mfxU32 MFX_TIME_STAMP_FREQUENCY = 90000; // will go to mfxdefs.h
45 static const mfxU64 MFX_TIME_STAMP_INVALID = (mfxU64)-1; // will go to mfxdefs.h
46 #define MFX_CHECK_UMC_STS(err)  { if (err != static_cast<int>(UMC::UMC_OK)) {return ConvertStatusUmc2Mfx(err);} }
47 
48 inline
ConvertStatusUmc2Mfx(UMC::Status umcStatus)49 mfxStatus ConvertStatusUmc2Mfx(UMC::Status umcStatus)
50 {
51     switch (umcStatus)
52     {
53     case UMC::UMC_OK: return MFX_ERR_NONE;
54     case UMC::UMC_ERR_NULL_PTR: return MFX_ERR_NULL_PTR;
55     case UMC::UMC_ERR_UNSUPPORTED: return MFX_ERR_UNSUPPORTED;
56     case UMC::UMC_ERR_ALLOC: return MFX_ERR_MEMORY_ALLOC;
57     case UMC::UMC_ERR_LOCK: return MFX_ERR_LOCK_MEMORY;
58     case UMC::UMC_ERR_NOT_ENOUGH_BUFFER: return MFX_ERR_NOT_ENOUGH_BUFFER;
59     case UMC::UMC_ERR_NOT_ENOUGH_DATA: return MFX_ERR_MORE_DATA;
60     case UMC::UMC_ERR_SYNC: return MFX_ERR_MORE_DATA; // need to skip bad frames
61     default: return MFX_ERR_ABORTED; // need general error code here
62     }
63 }
64 
65 inline
GetUmcTimeStamp(mfxU64 ts)66 mfxF64 GetUmcTimeStamp(mfxU64 ts)
67 {
68     return ts == MFX_TIME_STAMP_INVALID ? -1.0 : ts / (mfxF64)MFX_TIME_STAMP_FREQUENCY;
69 }
70 
71 inline
GetMfxTimeStamp(mfxF64 ts)72 mfxU64 GetMfxTimeStamp(mfxF64 ts)
73 {
74     return ts < 0.0 ? MFX_TIME_STAMP_INVALID : (mfxU64)(ts * MFX_TIME_STAMP_FREQUENCY + .5);
75 }
76 
77 inline
LumaIsNull(const mfxFrameSurface1 * surf)78 bool LumaIsNull(const mfxFrameSurface1 * surf)
79 {
80 #if (MFX_VERSION >= 1027)
81     if (surf->Info.FourCC == MFX_FOURCC_Y410)
82     {
83         return !surf->Data.Y410;
84     }
85     else
86 #endif
87     {
88         return !surf->Data.Y;
89     }
90 }
91 
92 namespace mfx
93 {
94 
95 template <class F>
96 struct TupleArgs;
97 
98 template <typename TRes, typename... TArgs>
99 struct TupleArgs<TRes(TArgs...)>
100 {
101     using type = std::tuple<TArgs...>;
102 };
103 template <typename TRes, typename... TArgs>
104 struct TupleArgs<TRes(*)(TArgs...)>
105 {
106     using type = std::tuple<TArgs...>;
107 };
108 
109 template<class T, T... args>
110 struct integer_sequence
111 {
112     using value_type = T;
113     static size_t size() { return (sizeof...(args)); }
114 };
115 
116 template<size_t... args>
117 using index_sequence = mfx::integer_sequence<size_t, args...>;
118 
119 template<size_t N, size_t ...S>
120 struct make_index_sequence_impl
121     : make_index_sequence_impl<N - 1, N - 1, S...>
122 {};
123 
124 template<size_t ...S>
125 struct make_index_sequence_impl<0, S...>
126 {
127     using type = index_sequence<S...>;
128 };
129 
130 template <class F>
131 struct result_of;
132 
133 template <typename TRes, typename... TArgs>
134 struct result_of<TRes(TArgs...)> : std::result_of<TRes(TArgs...)> {};
135 
136 template <typename TRes, typename... TArgs>
137 struct result_of<TRes(*const&)(TArgs...)>
138 {
139     using type = TRes;
140 };
141 
142 template<size_t S>
143 using make_index_sequence = typename make_index_sequence_impl<S>::type;
144 
145 template<typename TFunc, typename TTuple, size_t ...S >
146 inline typename mfx::result_of<TFunc>::type
147     apply_impl(TFunc&& fn, TTuple&& t, mfx::index_sequence<S...>)
148 {
149     return fn(std::get<S>(t) ...);
150 }
151 
152 template<typename TFunc, typename TTuple>
153 inline typename mfx::result_of<TFunc>::type
154     apply(TFunc&& fn, TTuple&& t)
155 {
156     return apply_impl(
157         std::forward<TFunc>(fn)
158         , std::forward<TTuple>(t)
159         , typename mfx::make_index_sequence<std::tuple_size<typename std::remove_reference<TTuple>::type>::value>());
160 }
161 
162 template<class T>
163 class IterStepWrapper
164     : public std::iterator_traits<T>
165 {
166 public:
167     using iterator_category = std::forward_iterator_tag;
168     using iterator_type = IterStepWrapper;
169     using reference = typename std::iterator_traits<T>::reference;
170     using pointer = typename std::iterator_traits<T>::pointer;
171 
172     IterStepWrapper(T ptr, ptrdiff_t step = 1)
173         : m_ptr(ptr)
174         , m_step(step)
175     {}
176     iterator_type& operator++()
177     {
178         std::advance(m_ptr, m_step);
179         return *this;
180     }
181     iterator_type operator++(int)
182     {
183         auto i = *this;
184         ++(*this);
185         return i;
186     }
187     reference operator*() { return *m_ptr; }
188     pointer operator->() { return m_ptr; }
189     bool operator==(const iterator_type& other)
190     {
191         return
192             m_ptr == other.m_ptr
193             || abs(std::distance(m_ptr, other.m_ptr)) < std::max(abs(m_step), abs(other.m_step));
194     }
195     bool operator!=(const iterator_type& other)
196     {
197         return !((*this) == other);
198     }
199 private:
200     T m_ptr;
201     ptrdiff_t m_step;
202 };
203 
204 template <class T>
205 inline IterStepWrapper<T> MakeStepIter(T ptr, ptrdiff_t step = 1)
206 {
207     return IterStepWrapper<T>(ptr, step);
208 }
209 
210 namespace options //MSDK API options verification utilities
211 {
212     //Each Check... function return true if verification failed, false otherwise
213     template <class T>
214     inline bool Check(const T&)
215     {
216         return true;
217     }
218 
219     template <class T, T val, T... other>
220     inline bool Check(const T & opt)
221     {
222         if (opt == val)
223             return false;
224         return Check<T, other...>(opt);
225     }
226 
227     template <class T, T val>
228     inline bool CheckGE(T opt)
229     {
230         return !(opt >= val);
231     }
232 
233     template <class T, class... U>
234     inline bool Check(T & opt, T next, U... other)
235     {
236         if (opt == next)
237             return false;
238         return Check(opt, other...);
239     }
240 
241     template <class T>
242     inline bool CheckOrZero(T& opt)
243     {
244         opt = T(0);
245         return true;
246     }
247 
248     template <class T, T val, T... other>
249     inline bool CheckOrZero(T & opt)
250     {
251         if (opt == val)
252             return false;
253         return CheckOrZero<T, other...>(opt);
254     }
255 
256     template <class T, class... U>
257     inline bool CheckOrZero(T & opt, T next, U... other)
258     {
259         if (opt == next)
260             return false;
261         return CheckOrZero(opt, (T)other...);
262     }
263 
264     template <class T, class U>
265     inline bool CheckMaxOrZero(T & opt, U max)
266     {
267         if (opt <= max)
268             return false;
269         opt = 0;
270         return true;
271     }
272 
273     template <class T, class U>
274     inline bool CheckMinOrZero(T & opt, U min)
275     {
276         if (opt >= min)
277             return false;
278         opt = 0;
279         return true;
280     }
281 
282     template <class T, class U>
283     inline bool CheckMaxOrClip(T & opt, U max)
284     {
285         if (opt <= max)
286             return false;
287         opt = T(max);
288         return true;
289     }
290 
291     template <class T, class U>
292     inline bool CheckMinOrClip(T & opt, U min)
293     {
294         if (opt >= min)
295             return false;
296         opt = T(min);
297         return true;
298     }
299 
300     template <class T>
301     inline bool CheckRangeOrSetDefault(T & opt, T min, T max, T dflt)
302     {
303         if (opt >= min && opt <= max)
304             return false;
305         opt = dflt;
306         return true;
307     }
308 
309     inline bool CheckTriState(mfxU16 opt)
310     {
311         return Check<mfxU16
312             , MFX_CODINGOPTION_UNKNOWN
313             , MFX_CODINGOPTION_ON
314             , MFX_CODINGOPTION_OFF>(opt);
315     }
316 
317     inline bool CheckTriStateOrZero(mfxU16& opt)
318     {
319         return CheckOrZero<mfxU16
320             , MFX_CODINGOPTION_UNKNOWN
321             , MFX_CODINGOPTION_ON
322             , MFX_CODINGOPTION_OFF>(opt);
323     }
324 
325     template<class TVal, class TArg, typename std::enable_if<!std::is_constructible<TVal, TArg>::value, int>::type = 0>
326     inline TVal GetOrCall(TArg val) { return val(); }
327 
328     template<class TVal, class TArg, typename = typename std::enable_if<std::is_constructible<TVal, TArg>::value>::type>
329     inline TVal GetOrCall(TArg val) { return TVal(val); }
330 
331     template<typename T, typename TF>
332     inline bool SetDefault(T& opt, TF get_dflt)
333     {
334         if (opt)
335             return false;
336         opt = GetOrCall<T>(get_dflt);
337         return true;
338     }
339 
340     template<typename T, typename TF>
341     inline bool SetIf(T& opt, bool bSet, TF get)
342     {
343         if (!bSet)
344             return false;
345         opt = GetOrCall<T>(get);
346         return true;
347     }
348 
349     template<class T, class TF, class... TA>
350     inline bool SetIf(T& opt, bool bSet, TF&& get, TA&&... arg)
351     {
352         if (!bSet)
353             return false;
354         opt = get(std::forward<TA>(arg)...);
355         return true;
356     }
357 
358     template <class T>
359     inline bool InheritOption(T optInit, T & optReset)
360     {
361         if (optReset == 0)
362         {
363             optReset = optInit;
364             return true;
365         }
366         return false;
367     }
368 
369     template<class TSrcIt, class TDstIt>
370     TDstIt InheritOptions(TSrcIt initFirst, TSrcIt initLast, TDstIt resetFirst)
371     {
372         while (initFirst != initLast)
373         {
374             InheritOption(*initFirst++, *resetFirst++);
375         }
376         return resetFirst;
377     }
378 
379     inline mfxU16 Bool2CO(bool bOptON)
380     {
381         return mfxU16(MFX_CODINGOPTION_OFF - !!bOptON * MFX_CODINGOPTION_ON);
382     }
383 
384     template<class T>
385     inline bool AlignDown(T& value, mfxU32 alignment)
386     {
387         assert((alignment & (alignment - 1)) == 0); // should be 2^n
388         if (!(value & (alignment - 1))) return false;
389         value = value & ~(alignment - 1);
390         return true;
391     }
392 
393     template<class T>
394     inline bool AlignUp(T& value, mfxU32 alignment)
395     {
396         assert((alignment & (alignment - 1)) == 0); // should be 2^n
397         if (!(value & (alignment - 1))) return false;
398         value = (value + alignment - 1) & ~(alignment - 1);
399         return true;
400     }
401 
402     namespace frametype
403     {
404         inline bool IsIdr(mfxU32 type)
405         {
406             return !!(type & MFX_FRAMETYPE_IDR);
407         }
408         inline bool IsI(mfxU32 type)
409         {
410             return !!(type & MFX_FRAMETYPE_I);
411         }
412         inline bool IsB(mfxU32 type)
413         {
414             return !!(type & MFX_FRAMETYPE_B);
415         }
416         inline bool IsP(mfxU32 type)
417         {
418             return !!(type & MFX_FRAMETYPE_P);
419         }
420         inline bool IsRef(mfxU32 type)
421         {
422             return !!(type & MFX_FRAMETYPE_REF);
423         }
424     }
425 }
426 }
427 
428 #if defined(MFX_VA_LINUX)
429 inline mfxStatus CheckAndDestroyVAbuffer(VADisplay display, VABufferID & buffer_id)
430 {
431     if (buffer_id != VA_INVALID_ID)
432     {
433         VAStatus vaSts = vaDestroyBuffer(display, buffer_id);
434         MFX_CHECK_WITH_ASSERT(VA_STATUS_SUCCESS == vaSts, MFX_ERR_DEVICE_FAILED);
435 
436         buffer_id = VA_INVALID_ID;
437     }
438 
439     return MFX_ERR_NONE;
440 }
441 #endif
442 
443 #define MFX_DECL_OPERATOR_NOT_EQ(Name)                      \
444 static inline bool operator!=(Name const& l, Name const& r) \
445 {                                                           \
446     return !(l == r);                                       \
447 }
448 
449 static inline bool operator==(mfxPluginUID const& l, mfxPluginUID const& r)
450 {
451     return MFX_EQ_ARRAY(Data, 16);
452 }
453 
454 MFX_DECL_OPERATOR_NOT_EQ(mfxPluginUID)
455 
456 
457 
458 #endif // __MFXUTILS_H__
459