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