qsv: Update SDK version to v2022.2.4
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / qsv / libmfx / dispatcher / vpl / mfx_dispatcher_vpl_config.cpp
1 /*############################################################################
2   # Copyright (C) Intel Corporation
3   #
4   # SPDX-License-Identifier: MIT
5   ############################################################################*/
6
7 #include "vpl/mfx_dispatcher_vpl.h"
8
9 #include <assert.h>
10
11 #include <regex>
12
13 // implementation of config context (mfxConfig)
14 // each loader instance can have one or more configs
15 //   associated with it - used for filtering implementations
16 //   based on what they support (codec types, etc.)
17 ConfigCtxVPL::ConfigCtxVPL()
18         : m_propVar(),
19           m_propRange32U(),
20           m_implName(),
21           m_implLicense(),
22           m_implKeywords(),
23           m_deviceIdStr(),
24           m_implFunctionName(),
25           m_extDevLUID8U(),
26           m_extDevNameStr(),
27           m_extBuf() {
28     // initially set Type = unset (invalid)
29     // if valid property string and value are passed in,
30     //   this will be updated
31     // otherwise loader will ignore this cfg during EnumImplementations
32     for (mfxU32 idx = 0; idx < NUM_TOTAL_FILTER_PROPS; idx++) {
33         m_propVar[idx].Version.Version = MFX_VARIANT_VERSION;
34         m_propVar[idx].Type            = MFX_VARIANT_TYPE_UNSET;
35         m_propVar[idx].Data.U64        = 0;
36     }
37
38     m_parentLoader = nullptr;
39     return;
40 }
41
42 ConfigCtxVPL::~ConfigCtxVPL() {
43     return;
44 }
45
46 struct PropVariant {
47     const char *Name;
48     mfxVariantType Type;
49 };
50
51 enum PropIdx {
52     // settable config properties for mfxImplDescription
53     ePropMain_Impl = 0,
54     ePropMain_AccelerationMode,
55     ePropMain_ApiVersion,
56     ePropMain_ApiVersion_Major,
57     ePropMain_ApiVersion_Minor,
58     ePropMain_ImplName,
59     ePropMain_License,
60     ePropMain_Keywords,
61     ePropMain_VendorID,
62     ePropMain_VendorImplID,
63     ePropMain_PoolAllocationPolicy,
64
65     // settable config properties for mfxDeviceDescription
66     ePropDevice_DeviceID,
67     ePropDevice_DeviceIDStr,
68     ePropDevice_MediaAdapterType,
69
70     // settable config properties for mfxDecoderDescription
71     ePropDec_CodecID,
72     ePropDec_MaxcodecLevel,
73     ePropDec_Profile,
74     ePropDec_MemHandleType,
75     ePropDec_Width,
76     ePropDec_Height,
77     ePropDec_ColorFormats,
78
79     // settable config properties for mfxEncoderDescription
80     ePropEnc_CodecID,
81     ePropEnc_MaxcodecLevel,
82     ePropEnc_BiDirectionalPrediction,
83     ePropEnc_ReportedStats,
84     ePropEnc_Profile,
85     ePropEnc_MemHandleType,
86     ePropEnc_Width,
87     ePropEnc_Height,
88     ePropEnc_ColorFormats,
89
90     // settable config properties for mfxVPPDescription
91     ePropVPP_FilterFourCC,
92     ePropVPP_MaxDelayInFrames,
93     ePropVPP_MemHandleType,
94     ePropVPP_Width,
95     ePropVPP_Height,
96     ePropVPP_InFormat,
97     ePropVPP_OutFormat,
98
99     // settable config properties for mfxExtendedDeviceId
100     ePropExtDev_VendorID,
101     ePropExtDev_DeviceID,
102     ePropExtDev_PCIDomain,
103     ePropExtDev_PCIBus,
104     ePropExtDev_PCIDevice,
105     ePropExtDev_PCIFunction,
106     ePropExtDev_DeviceLUID,
107     ePropExtDev_LUIDDeviceNodeMask,
108     ePropExtDev_DRMRenderNodeNum,
109     ePropExtDev_DRMPrimaryNodeNum,
110     ePropExtDev_DeviceName,
111
112     // special properties not part of description struct
113     ePropSpecial_HandleType,
114     ePropSpecial_Handle,
115     ePropSpecial_NumThread,
116     ePropSpecial_DeviceCopy,
117     ePropSpecial_ExtBuffer,
118     ePropSpecial_DXGIAdapterIndex,
119
120     // functions which must report as implemented
121     ePropFunc_FunctionName,
122
123     // number of entries (always last)
124     eProp_TotalProps
125 };
126
127 // leave table formatting alone
128 // clang-format off
129
130 // order must align exactly with PropIdx list
131 // to avoid mismatches, this should be automated (e.g. pre-processor step)
132 static const PropVariant PropIdxTab[] = {
133     { "ePropMain_Impl",                     MFX_VARIANT_TYPE_U32 },
134     { "ePropMain_AccelerationMode",         MFX_VARIANT_TYPE_U32 },
135     { "ePropMain_ApiVersion",               MFX_VARIANT_TYPE_U32 },
136     { "ePropMain_ApiVersion_Major",         MFX_VARIANT_TYPE_U16 },
137     { "ePropMain_ApiVersion_Minor",         MFX_VARIANT_TYPE_U16 },
138     { "ePropMain_ImplName",                 MFX_VARIANT_TYPE_PTR },
139     { "ePropMain_License",                  MFX_VARIANT_TYPE_PTR },
140     { "ePropMain_Keywords",                 MFX_VARIANT_TYPE_PTR },
141     { "ePropMain_VendorID",                 MFX_VARIANT_TYPE_U32 },
142     { "ePropMain_VendorImplID",             MFX_VARIANT_TYPE_U32 },
143     { "ePropMain_PoolAllocationPolicy",     MFX_VARIANT_TYPE_U32 },
144
145     { "ePropDevice_DeviceID",               MFX_VARIANT_TYPE_U16 },
146     { "ePropDevice_DeviceIDStr",            MFX_VARIANT_TYPE_PTR },
147     { "ePropDevice_MediaAdapterType",       MFX_VARIANT_TYPE_U16 },
148
149     { "ePropDec_CodecID",                   MFX_VARIANT_TYPE_U32 },
150     { "ePropDec_MaxcodecLevel",             MFX_VARIANT_TYPE_U16 },
151     { "ePropDec_Profile",                   MFX_VARIANT_TYPE_U32 },
152     { "ePropDec_MemHandleType",             MFX_VARIANT_TYPE_U32 },
153     { "ePropDec_Width",                     MFX_VARIANT_TYPE_PTR },
154     { "ePropDec_Height",                    MFX_VARIANT_TYPE_PTR },
155     { "ePropDec_ColorFormats",              MFX_VARIANT_TYPE_U32 },
156
157     { "ePropEnc_CodecID",                   MFX_VARIANT_TYPE_U32 },
158     { "ePropEnc_MaxcodecLevel",             MFX_VARIANT_TYPE_U16 },
159     { "ePropEnc_BiDirectionalPrediction",   MFX_VARIANT_TYPE_U16 },
160     { "ePropEnc_ReportedStats",             MFX_VARIANT_TYPE_U16 },
161     { "ePropEnc_Profile",                   MFX_VARIANT_TYPE_U32 },
162     { "ePropEnc_MemHandleType",             MFX_VARIANT_TYPE_U32 },
163     { "ePropEnc_Width",                     MFX_VARIANT_TYPE_PTR },
164     { "ePropEnc_Height",                    MFX_VARIANT_TYPE_PTR },
165     { "ePropEnc_ColorFormats",              MFX_VARIANT_TYPE_U32 },
166
167     { "ePropVPP_FilterFourCC",              MFX_VARIANT_TYPE_U32 },
168     { "ePropVPP_MaxDelayInFrames",          MFX_VARIANT_TYPE_U16 },
169     { "ePropVPP_MemHandleType",             MFX_VARIANT_TYPE_U32 },
170     { "ePropVPP_Width",                     MFX_VARIANT_TYPE_PTR },
171     { "ePropVPP_Height",                    MFX_VARIANT_TYPE_PTR },
172     { "ePropVPP_InFormat",                  MFX_VARIANT_TYPE_U32 },
173     { "ePropVPP_OutFormat",                 MFX_VARIANT_TYPE_U32 },
174
175     { "ePropExtDev_VendorID",               MFX_VARIANT_TYPE_U16 },
176     { "ePropExtDev_DeviceID",               MFX_VARIANT_TYPE_U16 },
177     { "ePropExtDev_PCIDomain",              MFX_VARIANT_TYPE_U32 },
178     { "ePropExtDev_PCIBus",                 MFX_VARIANT_TYPE_U32 },
179     { "ePropExtDev_PCIDevice",              MFX_VARIANT_TYPE_U32 },
180     { "ePropExtDev_PCIFunction",            MFX_VARIANT_TYPE_U32 },
181     { "ePropExtDev_DeviceLUID",             MFX_VARIANT_TYPE_PTR },
182     { "ePropExtDev_LUIDDeviceNodeMask",     MFX_VARIANT_TYPE_U32 },
183     { "ePropExtDev_DRMRenderNodeNum",       MFX_VARIANT_TYPE_U32 },
184     { "ePropExtDev_DRMPrimaryNodeNum",      MFX_VARIANT_TYPE_U32 },
185     { "ePropExtDev_DeviceName",             MFX_VARIANT_TYPE_PTR },
186
187     { "ePropSpecial_HandleType",            MFX_VARIANT_TYPE_U32 },
188     { "ePropSpecial_Handle",                MFX_VARIANT_TYPE_PTR },
189     { "ePropSpecial_NumThread",             MFX_VARIANT_TYPE_U32 },
190     { "ePropSpecial_DeviceCopy",            MFX_VARIANT_TYPE_U16 },
191     { "ePropSpecial_ExtBuffer",             MFX_VARIANT_TYPE_PTR },
192     { "ePropSpecial_DXGIAdapterIndex",      MFX_VARIANT_TYPE_U32 },
193
194     { "ePropFunc_FunctionName",             MFX_VARIANT_TYPE_PTR },
195 };
196
197 // end table formatting
198 // clang-format on
199
200 // sanity check - property table and indexes must have same number of entries
201 static_assert((sizeof(PropIdxTab) / sizeof(PropVariant)) == eProp_TotalProps,
202               "PropIdx and PropIdxTab are misaligned");
203
204 static_assert(NUM_TOTAL_FILTER_PROPS == eProp_TotalProps,
205               "NUM_TOTAL_FILTER_PROPS and eProp_TotalProps are misaligned");
206
207 mfxStatus ConfigCtxVPL::ValidateAndSetProp(mfxI32 idx, mfxVariant value) {
208     if (idx < 0 || idx >= eProp_TotalProps)
209         return MFX_ERR_NOT_FOUND;
210
211     if (value.Type != PropIdxTab[idx].Type)
212         return MFX_ERR_UNSUPPORTED;
213
214     m_propVar[idx].Version.Version = MFX_VARIANT_VERSION;
215     m_propVar[idx].Type            = value.Type;
216
217     if (value.Type == MFX_VARIANT_TYPE_PTR) {
218         if (value.Data.Ptr == nullptr) {
219             // unset property to avoid possibly dereferencing null if app ignores error code
220             m_propVar[idx].Type = MFX_VARIANT_TYPE_UNSET;
221             return MFX_ERR_NULL_PTR;
222         }
223
224         // local ptr for copying from array
225         mfxU8 *pU8 = (mfxU8 *)(value.Data.Ptr);
226
227         mfxExtBuffer *extBuf = nullptr;
228
229         // save copy of data passed by pointer, into object of the appropriate type
230         switch (idx) {
231             case ePropDec_Width:
232                 m_propRange32U[PROP_RANGE_DEC_W] = *((mfxRange32U *)(value.Data.Ptr));
233                 m_propVar[idx].Data.Ptr          = &(m_propRange32U[PROP_RANGE_DEC_W]);
234                 break;
235             case ePropDec_Height:
236                 m_propRange32U[PROP_RANGE_DEC_H] = *((mfxRange32U *)(value.Data.Ptr));
237                 m_propVar[idx].Data.Ptr          = &(m_propRange32U[PROP_RANGE_DEC_H]);
238                 break;
239             case ePropEnc_Width:
240                 m_propRange32U[PROP_RANGE_ENC_W] = *((mfxRange32U *)(value.Data.Ptr));
241                 m_propVar[idx].Data.Ptr          = &(m_propRange32U[PROP_RANGE_ENC_W]);
242                 break;
243             case ePropEnc_Height:
244                 m_propRange32U[PROP_RANGE_ENC_H] = *((mfxRange32U *)(value.Data.Ptr));
245                 m_propVar[idx].Data.Ptr          = &(m_propRange32U[PROP_RANGE_ENC_H]);
246                 break;
247             case ePropVPP_Width:
248                 m_propRange32U[PROP_RANGE_VPP_W] = *((mfxRange32U *)(value.Data.Ptr));
249                 m_propVar[idx].Data.Ptr          = &(m_propRange32U[PROP_RANGE_VPP_W]);
250                 break;
251             case ePropVPP_Height:
252                 m_propRange32U[PROP_RANGE_VPP_H] = *((mfxRange32U *)(value.Data.Ptr));
253                 m_propVar[idx].Data.Ptr          = &(m_propRange32U[PROP_RANGE_VPP_H]);
254                 break;
255             case ePropSpecial_Handle:
256                 m_propVar[idx].Data.Ptr = (mfxHDL)(value.Data.Ptr);
257                 break;
258             case ePropMain_ImplName:
259                 m_implName              = (char *)(value.Data.Ptr);
260                 m_propVar[idx].Data.Ptr = &(m_implName);
261                 break;
262             case ePropMain_License:
263                 m_implLicense           = (char *)(value.Data.Ptr);
264                 m_propVar[idx].Data.Ptr = &(m_implLicense);
265                 break;
266             case ePropMain_Keywords:
267                 m_implKeywords          = (char *)(value.Data.Ptr);
268                 m_propVar[idx].Data.Ptr = &(m_implKeywords);
269                 break;
270             case ePropDevice_DeviceIDStr:
271                 m_deviceIdStr           = (char *)(value.Data.Ptr);
272                 m_propVar[idx].Data.Ptr = &(m_deviceIdStr);
273                 break;
274             case ePropFunc_FunctionName:
275                 // no need to save Data.Ptr - parsed in main loop
276                 m_implFunctionName = (char *)(value.Data.Ptr);
277                 break;
278             case ePropExtDev_DeviceLUID:
279                 for (mfxU32 j = 0; j < 8; j++)
280                     m_extDevLUID8U[j] = pU8[j];
281                 m_propVar[idx].Data.Ptr = &(m_extDevLUID8U[0]);
282                 break;
283             case ePropExtDev_DeviceName:
284                 m_extDevNameStr         = (char *)(value.Data.Ptr);
285                 m_propVar[idx].Data.Ptr = &(m_extDevNameStr);
286                 break;
287             case ePropSpecial_ExtBuffer:
288                 // Don't assume anything about the lifetime of input mfxExtBuffer in Data.Ptr
289                 // Instead, we copy the full extBuf into a vector owned by ConfixCtxVPL and will pass this to MFXInitialize()
290                 // if app calls MFXSetConfigFilterProperty('ExtBuffer') again with a different extBuf, the old copy will be overwritten
291                 SetExtBuf((mfxExtBuffer *)(value.Data.Ptr));
292
293                 if (GetExtBuf(&extBuf))
294                     m_propVar[idx].Data.Ptr = extBuf;
295                 break;
296             default:
297                 break;
298         }
299     }
300     else {
301         m_propVar[idx].Data = value.Data;
302     }
303
304     return MFX_ERR_NONE;
305 }
306
307 mfxStatus ConfigCtxVPL::SetFilterPropertyDec(std::list<std::string> &propParsedString,
308                                              mfxVariant value) {
309     std::string nextProp;
310
311     nextProp = GetNextProp(propParsedString);
312
313     // no settable top-level members
314     if (nextProp != "decoder")
315         return MFX_ERR_NOT_FOUND;
316
317     // parse 'decoder'
318     nextProp = GetNextProp(propParsedString);
319     if (nextProp == "CodecID") {
320         return ValidateAndSetProp(ePropDec_CodecID, value);
321     }
322     else if (nextProp == "MaxcodecLevel") {
323         return ValidateAndSetProp(ePropDec_MaxcodecLevel, value);
324     }
325     else if (nextProp != "decprofile") {
326         return MFX_ERR_NOT_FOUND;
327     }
328
329     // parse 'decprofile'
330     nextProp = GetNextProp(propParsedString);
331     if (nextProp == "Profile") {
332         return ValidateAndSetProp(ePropDec_Profile, value);
333     }
334     else if (nextProp != "decmemdesc") {
335         return MFX_ERR_NOT_FOUND;
336     }
337
338     // parse 'decmemdesc'
339     nextProp = GetNextProp(propParsedString);
340     if (nextProp == "MemHandleType") {
341         return ValidateAndSetProp(ePropDec_MemHandleType, value);
342     }
343     else if (nextProp == "Width") {
344         return ValidateAndSetProp(ePropDec_Width, value);
345     }
346     else if (nextProp == "Height") {
347         return ValidateAndSetProp(ePropDec_Height, value);
348     }
349     else if (nextProp == "ColorFormat" || nextProp == "ColorFormats") {
350         return ValidateAndSetProp(ePropDec_ColorFormats, value);
351     }
352
353     // end of mfxDecoderDescription options
354     return MFX_ERR_NOT_FOUND;
355 }
356
357 mfxStatus ConfigCtxVPL::SetFilterPropertyEnc(std::list<std::string> &propParsedString,
358                                              mfxVariant value) {
359     std::string nextProp;
360
361     nextProp = GetNextProp(propParsedString);
362
363     // no settable top-level members
364     if (nextProp != "encoder")
365         return MFX_ERR_NOT_FOUND;
366
367     // parse 'encoder'
368     nextProp = GetNextProp(propParsedString);
369     if (nextProp == "CodecID") {
370         return ValidateAndSetProp(ePropEnc_CodecID, value);
371     }
372     else if (nextProp == "MaxcodecLevel") {
373         return ValidateAndSetProp(ePropEnc_MaxcodecLevel, value);
374     }
375     else if (nextProp == "BiDirectionalPrediction") {
376         return ValidateAndSetProp(ePropEnc_BiDirectionalPrediction, value);
377     }
378 #ifdef ONEVPL_EXPERIMENTAL
379     else if (nextProp == "ReportedStats") {
380         return ValidateAndSetProp(ePropEnc_ReportedStats, value);
381     }
382 #endif
383     else if (nextProp != "encprofile") {
384         return MFX_ERR_NOT_FOUND;
385     }
386
387     // parse 'encprofile'
388     nextProp = GetNextProp(propParsedString);
389     if (nextProp == "Profile") {
390         return ValidateAndSetProp(ePropEnc_Profile, value);
391     }
392     else if (nextProp != "encmemdesc") {
393         return MFX_ERR_NOT_FOUND;
394     }
395
396     // parse 'encmemdesc'
397     nextProp = GetNextProp(propParsedString);
398     if (nextProp == "MemHandleType") {
399         return ValidateAndSetProp(ePropEnc_MemHandleType, value);
400     }
401     else if (nextProp == "Width") {
402         return ValidateAndSetProp(ePropEnc_Width, value);
403     }
404     else if (nextProp == "Height") {
405         return ValidateAndSetProp(ePropEnc_Height, value);
406     }
407     else if (nextProp == "ColorFormat" || nextProp == "ColorFormats") {
408         return ValidateAndSetProp(ePropEnc_ColorFormats, value);
409     }
410
411     // end of mfxEncoderDescription options
412     return MFX_ERR_NOT_FOUND;
413 }
414
415 mfxStatus ConfigCtxVPL::SetFilterPropertyVPP(std::list<std::string> &propParsedString,
416                                              mfxVariant value) {
417     std::string nextProp;
418
419     nextProp = GetNextProp(propParsedString);
420
421     // no settable top-level members
422     if (nextProp != "filter")
423         return MFX_ERR_NOT_FOUND;
424
425     // parse 'filter'
426     nextProp = GetNextProp(propParsedString);
427     if (nextProp == "FilterFourCC") {
428         return ValidateAndSetProp(ePropVPP_FilterFourCC, value);
429     }
430     else if (nextProp == "MaxDelayInFrames") {
431         return ValidateAndSetProp(ePropVPP_MaxDelayInFrames, value);
432     }
433     else if (nextProp != "memdesc") {
434         return MFX_ERR_NOT_FOUND;
435     }
436
437     // parse 'memdesc'
438     nextProp = GetNextProp(propParsedString);
439     if (nextProp == "MemHandleType") {
440         return ValidateAndSetProp(ePropVPP_MemHandleType, value);
441     }
442     else if (nextProp == "Width") {
443         return ValidateAndSetProp(ePropVPP_Width, value);
444     }
445     else if (nextProp == "Height") {
446         return ValidateAndSetProp(ePropVPP_Height, value);
447     }
448     else if (nextProp != "format") {
449         return MFX_ERR_NOT_FOUND;
450     }
451
452     // parse 'format'
453     nextProp = GetNextProp(propParsedString);
454     if (nextProp == "InFormat") {
455         return ValidateAndSetProp(ePropVPP_InFormat, value);
456     }
457     else if (nextProp == "OutFormat" || nextProp == "OutFormats") {
458         return ValidateAndSetProp(ePropVPP_OutFormat, value);
459     }
460
461     // end of mfxVPPDescription options
462     return MFX_ERR_NOT_FOUND;
463 }
464
465 // return codes (from spec):
466 //   MFX_ERR_NOT_FOUND - name contains unknown parameter name
467 //   MFX_ERR_UNSUPPORTED - value data type != parameter with provided name
468 mfxStatus ConfigCtxVPL::SetFilterProperty(const mfxU8 *name, mfxVariant value) {
469     if (!name)
470         return MFX_ERR_NULL_PTR;
471
472     std::list<std::string> propParsedString;
473
474     // parse property string into individual properties,
475     //   separated by '.'
476     std::stringstream prop((char *)name);
477     std::string s;
478     propParsedString.clear();
479     while (getline(prop, s, '.')) {
480         propParsedString.push_back(s);
481     }
482
483     // get first property descriptor
484     std::string nextProp = GetNextProp(propParsedString);
485
486     // check for special-case properties, not part of mfxImplDescription
487     if (nextProp == "mfxHandleType") {
488         return ValidateAndSetProp(ePropSpecial_HandleType, value);
489     }
490     else if (nextProp == "mfxHDL") {
491         return ValidateAndSetProp(ePropSpecial_Handle, value);
492     }
493     else if (nextProp == "NumThread") {
494         return ValidateAndSetProp(ePropSpecial_NumThread, value);
495     }
496 #ifdef ONEVPL_EXPERIMENTAL
497     else if (nextProp == "DeviceCopy") {
498         return ValidateAndSetProp(ePropSpecial_DeviceCopy, value);
499     }
500 #endif
501     else if (nextProp == "ExtBuffer") {
502         return ValidateAndSetProp(ePropSpecial_ExtBuffer, value);
503     }
504     else if (nextProp == "DXGIAdapterIndex") {
505 #if defined(_WIN32) || defined(_WIN64)
506         // this property is only valid on Windows
507         return ValidateAndSetProp(ePropSpecial_DXGIAdapterIndex, value);
508 #else
509         return MFX_ERR_NOT_FOUND;
510 #endif
511     }
512
513     // to require that a specific function is implemented, use the property name
514     //   "mfxImplementedFunctions.FunctionsName"
515     if (nextProp == "mfxImplementedFunctions") {
516         nextProp = GetNextProp(propParsedString);
517         if (nextProp == "FunctionsName") {
518             return ValidateAndSetProp(ePropFunc_FunctionName, value);
519         }
520         return MFX_ERR_NOT_FOUND;
521     }
522
523 #ifdef ONEVPL_EXPERIMENTAL
524     // extended device ID properties must begin with mfxExtendedDeviceId
525     if (nextProp == "mfxExtendedDeviceId") {
526         nextProp = GetNextProp(propParsedString);
527         if (nextProp == "VendorID") {
528             return ValidateAndSetProp(ePropExtDev_VendorID, value);
529         }
530         else if (nextProp == "DeviceID") {
531             return ValidateAndSetProp(ePropExtDev_DeviceID, value);
532         }
533         else if (nextProp == "PCIDomain") {
534             return ValidateAndSetProp(ePropExtDev_PCIDomain, value);
535         }
536         else if (nextProp == "PCIBus") {
537             return ValidateAndSetProp(ePropExtDev_PCIBus, value);
538         }
539         else if (nextProp == "PCIDevice") {
540             return ValidateAndSetProp(ePropExtDev_PCIDevice, value);
541         }
542         else if (nextProp == "PCIFunction") {
543             return ValidateAndSetProp(ePropExtDev_PCIFunction, value);
544         }
545         else if (nextProp == "DeviceLUID") {
546             return ValidateAndSetProp(ePropExtDev_DeviceLUID, value);
547         }
548         else if (nextProp == "LUIDDeviceNodeMask") {
549             return ValidateAndSetProp(ePropExtDev_LUIDDeviceNodeMask, value);
550         }
551         else if (nextProp == "DRMRenderNodeNum") {
552             return ValidateAndSetProp(ePropExtDev_DRMRenderNodeNum, value);
553         }
554         else if (nextProp == "DRMPrimaryNodeNum") {
555             return ValidateAndSetProp(ePropExtDev_DRMPrimaryNodeNum, value);
556         }
557         else if (nextProp == "DeviceName") {
558             return ValidateAndSetProp(ePropExtDev_DeviceName, value);
559         }
560         return MFX_ERR_NOT_FOUND;
561     }
562 #endif
563
564     // standard properties must begin with "mfxImplDescription"
565     if (nextProp != "mfxImplDescription") {
566         return MFX_ERR_NOT_FOUND;
567     }
568
569     // get next property descriptor
570     nextProp = GetNextProp(propParsedString);
571
572     // property is a top-level member of mfxImplDescription
573     if (nextProp == "Impl") {
574         return ValidateAndSetProp(ePropMain_Impl, value);
575     }
576     else if (nextProp == "AccelerationMode") {
577         return ValidateAndSetProp(ePropMain_AccelerationMode, value);
578     }
579     else if (nextProp == "mfxSurfacePoolMode") {
580         return ValidateAndSetProp(ePropMain_PoolAllocationPolicy, value);
581     }
582     else if (nextProp == "ApiVersion") {
583         // ApiVersion may be passed as single U32 (Version) or two U16's (Major, Minor)
584         nextProp = GetNextProp(propParsedString);
585         if (nextProp == "Version")
586             return ValidateAndSetProp(ePropMain_ApiVersion, value);
587         else if (nextProp == "Major")
588             return ValidateAndSetProp(ePropMain_ApiVersion_Major, value);
589         else if (nextProp == "Minor")
590             return ValidateAndSetProp(ePropMain_ApiVersion_Minor, value);
591         else
592             return MFX_ERR_NOT_FOUND;
593     }
594     else if (nextProp == "VendorID") {
595         return ValidateAndSetProp(ePropMain_VendorID, value);
596     }
597     else if (nextProp == "ImplName") {
598         return ValidateAndSetProp(ePropMain_ImplName, value);
599     }
600     else if (nextProp == "License") {
601         return ValidateAndSetProp(ePropMain_License, value);
602     }
603     else if (nextProp == "Keywords") {
604         return ValidateAndSetProp(ePropMain_Keywords, value);
605     }
606     else if (nextProp == "VendorImplID") {
607         return ValidateAndSetProp(ePropMain_VendorImplID, value);
608     }
609
610     // property is a member of mfxDeviceDescription
611     if (nextProp == "mfxDeviceDescription") {
612         nextProp = GetNextProp(propParsedString);
613         // old version of table in spec had extra "device", just skip if present
614         if (nextProp == "device")
615             nextProp = GetNextProp(propParsedString);
616
617         // special case - deviceID may be passed as U16 (default) or string (since API 2.4)
618         // for compatibility, both are supported (value.Type distinguishes between them)
619         if (nextProp == "DeviceID") {
620             if (value.Type == MFX_VARIANT_TYPE_PTR)
621                 return ValidateAndSetProp(ePropDevice_DeviceIDStr, value);
622             else
623                 return ValidateAndSetProp(ePropDevice_DeviceID, value);
624         }
625
626         if (nextProp == "MediaAdapterType") {
627             return ValidateAndSetProp(ePropDevice_MediaAdapterType, value);
628         }
629
630         return MFX_ERR_NOT_FOUND;
631     }
632
633     // property is a member of mfxDecoderDescription
634     if (nextProp == "mfxDecoderDescription") {
635         return SetFilterPropertyDec(propParsedString, value);
636     }
637
638     if (nextProp == "mfxEncoderDescription") {
639         return SetFilterPropertyEnc(propParsedString, value);
640     }
641
642     if (nextProp == "mfxVPPDescription") {
643         return SetFilterPropertyVPP(propParsedString, value);
644     }
645
646     return MFX_ERR_NOT_FOUND;
647 }
648
649 #define CHECK_IDX(idxA, idxB, numB) \
650     if ((idxB) == (numB)) {         \
651         (idxA)++;                   \
652         (idxB) = 0;                 \
653         continue;                   \
654     }
655
656 mfxStatus ConfigCtxVPL::GetFlatDescriptionsDec(const mfxImplDescription *libImplDesc,
657                                                std::list<DecConfig> &decConfigList) {
658     mfxU32 codecIdx   = 0;
659     mfxU32 profileIdx = 0;
660     mfxU32 memIdx     = 0;
661     mfxU32 outFmtIdx  = 0;
662
663     DecCodec *decCodec     = nullptr;
664     DecProfile *decProfile = nullptr;
665     DecMemDesc *decMemDesc = nullptr;
666
667     while (codecIdx < libImplDesc->Dec.NumCodecs) {
668         DecConfig dc = {};
669
670         decCodec         = &(libImplDesc->Dec.Codecs[codecIdx]);
671         dc.CodecID       = decCodec->CodecID;
672         dc.MaxcodecLevel = decCodec->MaxcodecLevel;
673         CHECK_IDX(codecIdx, profileIdx, decCodec->NumProfiles);
674
675         decProfile = &(decCodec->Profiles[profileIdx]);
676         dc.Profile = decProfile->Profile;
677         CHECK_IDX(profileIdx, memIdx, decProfile->NumMemTypes);
678
679         decMemDesc       = &(decProfile->MemDesc[memIdx]);
680         dc.MemHandleType = decMemDesc->MemHandleType;
681         dc.Width         = decMemDesc->Width;
682         dc.Height        = decMemDesc->Height;
683         CHECK_IDX(memIdx, outFmtIdx, decMemDesc->NumColorFormats);
684
685         dc.ColorFormat = decMemDesc->ColorFormats[outFmtIdx];
686         outFmtIdx++;
687
688         // we have a valid, unique description - add to list
689         decConfigList.push_back(dc);
690     }
691
692     if (decConfigList.empty())
693         return MFX_ERR_INVALID_VIDEO_PARAM;
694
695     return MFX_ERR_NONE;
696 }
697
698 mfxStatus ConfigCtxVPL::GetFlatDescriptionsEnc(const mfxImplDescription *libImplDesc,
699                                                std::list<EncConfig> &encConfigList) {
700     mfxU32 codecIdx   = 0;
701     mfxU32 profileIdx = 0;
702     mfxU32 memIdx     = 0;
703     mfxU32 inFmtIdx   = 0;
704
705     EncCodec *encCodec     = nullptr;
706     EncProfile *encProfile = nullptr;
707     EncMemDesc *encMemDesc = nullptr;
708
709 #ifdef ONEVPL_EXPERIMENTAL
710     // ReportedStats was added with API 2.7 under ONEVPL_EXPERIMENTAL.
711     // When it is promoted to production API, MFX_ENCODERDESCRIPTION_VERSION should be bumped up
712     //   and we should check mfxEncoderDescription.Version instead to know whether ReportedStats
713     //   is a valid field (taken from reserved[] space).
714     // Until then, best we can do is to check the overall API version for this impl.
715     mfxVersion reqApiVersionReportedStats = {};
716     reqApiVersionReportedStats.Major      = 2;
717     reqApiVersionReportedStats.Minor      = 7;
718 #endif
719
720     while (codecIdx < libImplDesc->Enc.NumCodecs) {
721         EncConfig ec = {};
722
723         encCodec                   = &(libImplDesc->Enc.Codecs[codecIdx]);
724         ec.CodecID                 = encCodec->CodecID;
725         ec.MaxcodecLevel           = encCodec->MaxcodecLevel;
726         ec.BiDirectionalPrediction = encCodec->BiDirectionalPrediction;
727
728 #ifdef ONEVPL_EXPERIMENTAL
729         // see comment above about checking mfxEncoderDescription version once this is moved out
730         //   of experimental API
731         if (libImplDesc->ApiVersion.Version >= reqApiVersionReportedStats.Version)
732             ec.ReportedStats = encCodec->ReportedStats;
733 #endif
734
735         CHECK_IDX(codecIdx, profileIdx, encCodec->NumProfiles);
736
737         encProfile = &(encCodec->Profiles[profileIdx]);
738         ec.Profile = encProfile->Profile;
739         CHECK_IDX(profileIdx, memIdx, encProfile->NumMemTypes);
740
741         encMemDesc       = &(encProfile->MemDesc[memIdx]);
742         ec.MemHandleType = encMemDesc->MemHandleType;
743         ec.Width         = encMemDesc->Width;
744         ec.Height        = encMemDesc->Height;
745         CHECK_IDX(memIdx, inFmtIdx, encMemDesc->NumColorFormats);
746
747         ec.ColorFormat = encMemDesc->ColorFormats[inFmtIdx];
748         inFmtIdx++;
749
750         // we have a valid, unique description - add to list
751         encConfigList.push_back(ec);
752     }
753
754     if (encConfigList.empty())
755         return MFX_ERR_INVALID_VIDEO_PARAM;
756
757     return MFX_ERR_NONE;
758 }
759
760 mfxStatus ConfigCtxVPL::GetFlatDescriptionsVPP(const mfxImplDescription *libImplDesc,
761                                                std::list<VPPConfig> &vppConfigList) {
762     mfxU32 filterIdx = 0;
763     mfxU32 memIdx    = 0;
764     mfxU32 inFmtIdx  = 0;
765     mfxU32 outFmtIdx = 0;
766
767     VPPFilter *vppFilter   = nullptr;
768     VPPMemDesc *vppMemDesc = nullptr;
769     VPPFormat *vppFormat   = nullptr;
770
771     while (filterIdx < libImplDesc->VPP.NumFilters) {
772         VPPConfig vc = {};
773
774         vppFilter           = &(libImplDesc->VPP.Filters[filterIdx]);
775         vc.FilterFourCC     = vppFilter->FilterFourCC;
776         vc.MaxDelayInFrames = vppFilter->MaxDelayInFrames;
777         CHECK_IDX(filterIdx, memIdx, vppFilter->NumMemTypes);
778
779         vppMemDesc       = &(vppFilter->MemDesc[memIdx]);
780         vc.MemHandleType = vppMemDesc->MemHandleType;
781         vc.Width         = vppMemDesc->Width;
782         vc.Height        = vppMemDesc->Height;
783         CHECK_IDX(memIdx, inFmtIdx, vppMemDesc->NumInFormats);
784
785         vppFormat   = &(vppMemDesc->Formats[inFmtIdx]);
786         vc.InFormat = vppFormat->InFormat;
787         CHECK_IDX(inFmtIdx, outFmtIdx, vppFormat->NumOutFormat);
788
789         vc.OutFormat = vppFormat->OutFormats[outFmtIdx];
790         outFmtIdx++;
791
792         // we have a valid, unique description - add to list
793         vppConfigList.push_back(vc);
794     }
795
796     if (vppConfigList.empty())
797         return MFX_ERR_INVALID_VIDEO_PARAM;
798
799     return MFX_ERR_NONE;
800 }
801
802 #define CHECK_PROP(idx, type, val)                             \
803     if ((cfgPropsAll[(idx)].Type != MFX_VARIANT_TYPE_UNSET) && \
804         (cfgPropsAll[(idx)].Data.type != val))                 \
805         isCompatible = false;
806
807 mfxStatus ConfigCtxVPL::CheckPropsGeneral(const mfxVariant cfgPropsAll[],
808                                           const mfxImplDescription *libImplDesc) {
809     bool isCompatible = true;
810
811     // check if this implementation includes
812     //   all of the required top-level properties
813     CHECK_PROP(ePropMain_Impl, U32, libImplDesc->Impl);
814     CHECK_PROP(ePropMain_VendorID, U32, libImplDesc->VendorID);
815     CHECK_PROP(ePropMain_VendorImplID, U32, libImplDesc->VendorImplID);
816
817     // check API version in calling function since major and minor may be passed
818     //   in separate cfg objects
819
820     if (libImplDesc->AccelerationModeDescription.NumAccelerationModes > 0) {
821         if (cfgPropsAll[ePropMain_AccelerationMode].Type != MFX_VARIANT_TYPE_UNSET) {
822             // check all supported modes if list is filled out
823             mfxU16 numModes = libImplDesc->AccelerationModeDescription.NumAccelerationModes;
824             mfxAccelerationMode modeRequested =
825                 (mfxAccelerationMode)(cfgPropsAll[ePropMain_AccelerationMode].Data.U32);
826             auto *modeTab = libImplDesc->AccelerationModeDescription.Mode;
827
828             auto *m = std::find(modeTab, modeTab + numModes, modeRequested);
829             if (m == modeTab + numModes)
830                 isCompatible = false;
831         }
832     }
833     else {
834         // check default mode
835         CHECK_PROP(ePropMain_AccelerationMode, U32, libImplDesc->AccelerationMode);
836     }
837
838     if (cfgPropsAll[ePropMain_PoolAllocationPolicy].Type != MFX_VARIANT_TYPE_UNSET) {
839         // mfxPoolAllocationPolicy added with struct version 1.2
840         mfxU16 numPolicies = 0;
841         if (libImplDesc->Version.Version >= MFX_STRUCT_VERSION(1, 2))
842             numPolicies = libImplDesc->PoolPolicies.NumPoolPolicies;
843
844         // check all supported policies if list is filled out
845         // if structure is not present (old version) numPolicies will be 0, so skipped
846         if (isCompatible == true && numPolicies > 0) {
847             mfxPoolAllocationPolicy policyRequested =
848                 (mfxPoolAllocationPolicy)(cfgPropsAll[ePropMain_PoolAllocationPolicy].Data.U32);
849             auto *policyTab = libImplDesc->PoolPolicies.Policy;
850
851             auto *m = std::find(policyTab, policyTab + numPolicies, policyRequested);
852             if (m == policyTab + numPolicies)
853                 isCompatible = false;
854         }
855         else {
856             isCompatible = false;
857         }
858     }
859
860     // check string: ImplName (string match)
861     if (cfgPropsAll[ePropMain_ImplName].Type != MFX_VARIANT_TYPE_UNSET) {
862         std::string filtName = *(std::string *)(cfgPropsAll[ePropMain_ImplName].Data.Ptr);
863         std::string implName = libImplDesc->ImplName;
864         if (filtName != implName)
865             isCompatible = false;
866     }
867
868     // check string: License (tokenized)
869     if (cfgPropsAll[ePropMain_License].Type != MFX_VARIANT_TYPE_UNSET) {
870         std::string license = *(std::string *)(cfgPropsAll[ePropMain_License].Data.Ptr);
871         if (CheckPropString(libImplDesc->License, license) != MFX_ERR_NONE)
872             isCompatible = false;
873     }
874
875     // check string: Keywords (tokenized)
876     if (cfgPropsAll[ePropMain_Keywords].Type != MFX_VARIANT_TYPE_UNSET) {
877         std::string keywords = *(std::string *)(cfgPropsAll[ePropMain_Keywords].Data.Ptr);
878         if (CheckPropString(libImplDesc->Keywords, keywords) != MFX_ERR_NONE)
879             isCompatible = false;
880     }
881
882     // check DeviceID - stored as char*, but passed in for filtering as U16
883     // convert both to unsigned ints and compare
884     if (cfgPropsAll[ePropDevice_DeviceID].Type != MFX_VARIANT_TYPE_UNSET) {
885         unsigned int implDeviceID = 0;
886         try {
887             implDeviceID = std::stoi(libImplDesc->Dev.DeviceID, 0, 16);
888         }
889         catch (...) {
890             return MFX_ERR_UNSUPPORTED;
891         }
892
893         unsigned int filtDeviceID = (unsigned int)(cfgPropsAll[ePropDevice_DeviceID].Data.U16);
894         if (implDeviceID != filtDeviceID)
895             isCompatible = false;
896     }
897
898     if (cfgPropsAll[ePropDevice_DeviceIDStr].Type != MFX_VARIANT_TYPE_UNSET) {
899         // since API 2.4 - pass DeviceID as string (do string match)
900         std::string filtDeviceID = *(std::string *)(cfgPropsAll[ePropDevice_DeviceIDStr].Data.Ptr);
901         std::string implDeviceID = libImplDesc->Dev.DeviceID;
902         if (filtDeviceID != implDeviceID)
903             isCompatible = false;
904     }
905
906     // mfxDeviceDescription.MediaAdapterType introduced in API 2.5, structure version 1.1
907     // do not check this for MSDK libs (allow it to pass)
908     if (libImplDesc->ApiVersion.Major >= 2) {
909         if (cfgPropsAll[ePropDevice_MediaAdapterType].Type != MFX_VARIANT_TYPE_UNSET) {
910             if (libImplDesc->Dev.Version.Version < MFX_STRUCT_VERSION(1, 1))
911                 isCompatible = false;
912
913             CHECK_PROP(ePropDevice_MediaAdapterType, U16, libImplDesc->Dev.MediaAdapterType);
914         }
915     }
916
917     if (isCompatible == true)
918         return MFX_ERR_NONE;
919
920     return MFX_ERR_UNSUPPORTED;
921 }
922
923 mfxStatus ConfigCtxVPL::CheckPropsDec(const mfxVariant cfgPropsAll[],
924                                       std::list<DecConfig> decConfigList) {
925     auto it = decConfigList.begin();
926     while (it != decConfigList.end()) {
927         DecConfig dc      = (DecConfig)(*it);
928         bool isCompatible = true;
929
930         // check if this decode description includes
931         //   all of the required decoder properties
932         CHECK_PROP(ePropDec_CodecID, U32, dc.CodecID);
933         CHECK_PROP(ePropDec_MaxcodecLevel, U16, dc.MaxcodecLevel);
934         CHECK_PROP(ePropDec_Profile, U32, dc.Profile);
935         CHECK_PROP(ePropDec_MemHandleType, U32, dc.MemHandleType);
936         CHECK_PROP(ePropDec_ColorFormats, U32, dc.ColorFormat);
937
938         // special handling for properties passed via pointer
939         if (cfgPropsAll[ePropDec_Width].Type != MFX_VARIANT_TYPE_UNSET) {
940             mfxRange32U width = {};
941             if (cfgPropsAll[ePropDec_Width].Data.Ptr)
942                 width = *((mfxRange32U *)(cfgPropsAll[ePropDec_Width].Data.Ptr));
943
944             if ((width.Max > dc.Width.Max) || (width.Min < dc.Width.Min) ||
945                 (width.Step < dc.Width.Step))
946                 isCompatible = false;
947         }
948
949         if (cfgPropsAll[ePropDec_Height].Type != MFX_VARIANT_TYPE_UNSET) {
950             mfxRange32U height = {};
951             if (cfgPropsAll[ePropDec_Height].Data.Ptr)
952                 height = *((mfxRange32U *)(cfgPropsAll[ePropDec_Height].Data.Ptr));
953
954             if ((height.Max > dc.Height.Max) || (height.Min < dc.Height.Min) ||
955                 (height.Step < dc.Height.Step))
956                 isCompatible = false;
957         }
958
959         if (isCompatible == true)
960             return MFX_ERR_NONE;
961
962         it++;
963     }
964
965     return MFX_ERR_UNSUPPORTED;
966 }
967
968 mfxStatus ConfigCtxVPL::CheckPropsEnc(const mfxVariant cfgPropsAll[],
969                                       std::list<EncConfig> encConfigList) {
970     auto it = encConfigList.begin();
971     while (it != encConfigList.end()) {
972         EncConfig ec      = (EncConfig)(*it);
973         bool isCompatible = true;
974
975         // check if this encode description includes
976         //   all of the required encoder properties
977         CHECK_PROP(ePropEnc_CodecID, U32, ec.CodecID);
978         CHECK_PROP(ePropEnc_MaxcodecLevel, U16, ec.MaxcodecLevel);
979         CHECK_PROP(ePropEnc_BiDirectionalPrediction, U16, ec.BiDirectionalPrediction);
980         CHECK_PROP(ePropEnc_Profile, U32, ec.Profile);
981         CHECK_PROP(ePropEnc_MemHandleType, U32, ec.MemHandleType);
982         CHECK_PROP(ePropEnc_ColorFormats, U32, ec.ColorFormat);
983
984         // special handling for properties passed via pointer
985         if (cfgPropsAll[ePropEnc_Width].Type != MFX_VARIANT_TYPE_UNSET) {
986             mfxRange32U width = {};
987             if (cfgPropsAll[ePropEnc_Width].Data.Ptr)
988                 width = *((mfxRange32U *)(cfgPropsAll[ePropEnc_Width].Data.Ptr));
989
990             if ((width.Max > ec.Width.Max) || (width.Min < ec.Width.Min) ||
991                 (width.Step < ec.Width.Step))
992                 isCompatible = false;
993         }
994
995         if (cfgPropsAll[ePropEnc_Height].Type != MFX_VARIANT_TYPE_UNSET) {
996             mfxRange32U height = {};
997             if (cfgPropsAll[ePropEnc_Height].Data.Ptr)
998                 height = *((mfxRange32U *)(cfgPropsAll[ePropEnc_Height].Data.Ptr));
999
1000             if ((height.Max > ec.Height.Max) || (height.Min < ec.Height.Min) ||
1001                 (height.Step < ec.Height.Step))
1002                 isCompatible = false;
1003         }
1004
1005         if (cfgPropsAll[ePropEnc_ReportedStats].Type != MFX_VARIANT_TYPE_UNSET) {
1006             mfxU16 requestedStats = cfgPropsAll[ePropEnc_ReportedStats].Data.U16;
1007
1008             // ReportedStats is a logical OR of one or more flags: MFX_ENCODESTATS_LEVEL_xxx
1009             if ((requestedStats & ec.ReportedStats) != requestedStats)
1010                 isCompatible = false;
1011         }
1012
1013         if (isCompatible == true)
1014             return MFX_ERR_NONE;
1015
1016         it++;
1017     }
1018
1019     return MFX_ERR_UNSUPPORTED;
1020 }
1021
1022 mfxStatus ConfigCtxVPL::CheckPropsVPP(const mfxVariant cfgPropsAll[],
1023                                       std::list<VPPConfig> vppConfigList) {
1024     auto it = vppConfigList.begin();
1025     while (it != vppConfigList.end()) {
1026         VPPConfig vc      = (VPPConfig)(*it);
1027         bool isCompatible = true;
1028
1029         // check if this filter description includes
1030         //   all of the required VPP properties
1031         CHECK_PROP(ePropVPP_FilterFourCC, U32, vc.FilterFourCC);
1032         CHECK_PROP(ePropVPP_MaxDelayInFrames, U16, vc.MaxDelayInFrames);
1033         CHECK_PROP(ePropVPP_MemHandleType, U32, vc.MemHandleType);
1034         CHECK_PROP(ePropVPP_InFormat, U32, vc.InFormat);
1035         CHECK_PROP(ePropVPP_OutFormat, U32, vc.OutFormat);
1036
1037         // special handling for properties passed via pointer
1038         if (cfgPropsAll[ePropVPP_Width].Type != MFX_VARIANT_TYPE_UNSET) {
1039             mfxRange32U width = {};
1040             if (cfgPropsAll[ePropVPP_Width].Data.Ptr)
1041                 width = *((mfxRange32U *)(cfgPropsAll[ePropVPP_Width].Data.Ptr));
1042
1043             if ((width.Max > vc.Width.Max) || (width.Min < vc.Width.Min) ||
1044                 (width.Step < vc.Width.Step))
1045                 isCompatible = false;
1046         }
1047
1048         if (cfgPropsAll[ePropVPP_Height].Type != MFX_VARIANT_TYPE_UNSET) {
1049             mfxRange32U height = {};
1050             if (cfgPropsAll[ePropVPP_Height].Data.Ptr)
1051                 height = *((mfxRange32U *)(cfgPropsAll[ePropVPP_Height].Data.Ptr));
1052
1053             if ((height.Max > vc.Height.Max) || (height.Min < vc.Height.Min) ||
1054                 (height.Step < vc.Height.Step))
1055                 isCompatible = false;
1056         }
1057
1058         if (isCompatible == true)
1059             return MFX_ERR_NONE;
1060
1061         it++;
1062     }
1063
1064     return MFX_ERR_UNSUPPORTED;
1065 }
1066
1067 #ifdef ONEVPL_EXPERIMENTAL
1068 mfxStatus ConfigCtxVPL::CheckPropsExtDevID(const mfxVariant cfgPropsAll[],
1069                                            const mfxExtendedDeviceId *libImplExtDevID) {
1070     bool isCompatible = true;
1071
1072     // check if this implementation includes
1073     //   all of the required extended device ID properties
1074     CHECK_PROP(ePropExtDev_VendorID, U16, libImplExtDevID->VendorID);
1075     CHECK_PROP(ePropExtDev_DeviceID, U16, libImplExtDevID->DeviceID);
1076
1077     CHECK_PROP(ePropExtDev_PCIDomain, U32, libImplExtDevID->PCIDomain);
1078     CHECK_PROP(ePropExtDev_PCIBus, U32, libImplExtDevID->PCIBus);
1079     CHECK_PROP(ePropExtDev_PCIDevice, U32, libImplExtDevID->PCIDevice);
1080     CHECK_PROP(ePropExtDev_PCIFunction, U32, libImplExtDevID->PCIFunction);
1081
1082     // check DeviceLUID, require LUIDValid == true
1083     if (cfgPropsAll[ePropExtDev_DeviceLUID].Type != MFX_VARIANT_TYPE_UNSET) {
1084         // LUID filter is passed as ptr to 8-byte array, which was saved in local copy
1085         mfxU8 *pU8 = (mfxU8 *)(cfgPropsAll[ePropExtDev_DeviceLUID].Data.Ptr);
1086         if (libImplExtDevID->LUIDValid) {
1087             for (mfxU32 j = 0; j < 8; j++) {
1088                 if (pU8[j] != libImplExtDevID->DeviceLUID[j])
1089                     isCompatible = false;
1090             }
1091         }
1092         else {
1093             isCompatible = false;
1094         }
1095     }
1096
1097     // check LUIDDeviceNodeMask, require LUIDValid == true
1098     if (cfgPropsAll[ePropExtDev_LUIDDeviceNodeMask].Type != MFX_VARIANT_TYPE_UNSET) {
1099         if (libImplExtDevID->LUIDValid) {
1100             CHECK_PROP(ePropExtDev_LUIDDeviceNodeMask, U32, libImplExtDevID->LUIDDeviceNodeMask);
1101         }
1102         else {
1103             isCompatible = false;
1104         }
1105     }
1106
1107     // check DRMRenderNodeNum
1108     if (cfgPropsAll[ePropExtDev_DRMRenderNodeNum].Type != MFX_VARIANT_TYPE_UNSET) {
1109         if (libImplExtDevID->DRMRenderNodeNum != 0) {
1110             CHECK_PROP(ePropExtDev_DRMRenderNodeNum, U32, libImplExtDevID->DRMRenderNodeNum);
1111         }
1112         else {
1113             isCompatible = false;
1114         }
1115     }
1116
1117     // check DRMPrimaryNodeNum
1118     if (cfgPropsAll[ePropExtDev_DRMPrimaryNodeNum].Type != MFX_VARIANT_TYPE_UNSET) {
1119         if (libImplExtDevID->DRMRenderNodeNum != 0x7FFFFFFF) {
1120             CHECK_PROP(ePropExtDev_DRMPrimaryNodeNum, U32, libImplExtDevID->DRMPrimaryNodeNum);
1121         }
1122         else {
1123             isCompatible = false;
1124         }
1125     }
1126
1127     // check string: DeviceName (string match)
1128     if (cfgPropsAll[ePropExtDev_DeviceName].Type != MFX_VARIANT_TYPE_UNSET) {
1129         std::string filtName = *(std::string *)(cfgPropsAll[ePropExtDev_DeviceName].Data.Ptr);
1130         std::string implName = libImplExtDevID->DeviceName;
1131         if (filtName != implName)
1132             isCompatible = false;
1133     }
1134
1135     if (isCompatible == true)
1136         return MFX_ERR_NONE;
1137
1138     return MFX_ERR_UNSUPPORTED;
1139 }
1140 #endif
1141
1142 // implString = string from implDesc - one or more comma-separated tokens
1143 // filtString = string user is looking for - one or more comma-separated tokens
1144 // we parse filtString into tokens, then check if all of them are present in implString
1145 mfxStatus ConfigCtxVPL::CheckPropString(const mfxChar *implString, const std::string filtString) {
1146     std::list<std::string> tokenString;
1147     std::string s;
1148
1149     // parse implString string into tokens, separated by ','
1150     std::stringstream implSS((char *)implString);
1151     while (getline(implSS, s, ',')) {
1152         tokenString.push_back(s);
1153     }
1154
1155     // parse filtString string into tokens, separated by ','
1156     // check that each token is present in implString, otherwise return error
1157     std::stringstream filtSS(filtString);
1158     while (getline(filtSS, s, ',')) {
1159         if (std::find(tokenString.begin(), tokenString.end(), s) == tokenString.end())
1160             return MFX_ERR_UNSUPPORTED;
1161     }
1162
1163     return MFX_ERR_NONE;
1164 }
1165
1166 mfxStatus ConfigCtxVPL::ValidateConfig(const mfxImplDescription *libImplDesc,
1167                                        const mfxImplementedFunctions *libImplFuncs,
1168 #ifdef ONEVPL_EXPERIMENTAL
1169                                        const mfxExtendedDeviceId *libImplExtDevID,
1170 #endif
1171                                        std::list<ConfigCtxVPL *> configCtxList,
1172                                        LibType libType,
1173                                        SpecialConfig *specialConfig) {
1174     mfxU32 idx;
1175     bool decRequested    = false;
1176     bool encRequested    = false;
1177     bool vppRequested    = false;
1178     bool extDevRequested = false;
1179
1180     bool bImplValid = true;
1181
1182     if (!libImplDesc)
1183         return MFX_ERR_NULL_PTR;
1184
1185     std::list<DecConfig> decConfigList;
1186     std::list<EncConfig> encConfigList;
1187     std::list<VPPConfig> vppConfigList;
1188
1189     // generate "flat" descriptions of each combination
1190     //   (e.g. multiple profiles from the same codec)
1191     GetFlatDescriptionsDec(libImplDesc, decConfigList);
1192     GetFlatDescriptionsEnc(libImplDesc, encConfigList);
1193     GetFlatDescriptionsVPP(libImplDesc, vppConfigList);
1194
1195     // list of functions required to be implemented
1196     std::list<std::string> implFunctionList;
1197     implFunctionList.clear();
1198
1199     // check requested API version
1200     mfxVersion reqVersion = {};
1201     bool bVerSetMajor     = false;
1202     bool bVerSetMinor     = false;
1203
1204     // clear list of extension buffers
1205     specialConfig->bIsSet_ExtBuffer = false;
1206     specialConfig->ExtBuffers.clear();
1207
1208     // iterate through all filters and populate cfgPropsAll
1209     auto it = configCtxList.begin();
1210
1211     while (it != configCtxList.end()) {
1212         ConfigCtxVPL *config = (*it);
1213         it++;
1214
1215         // initially all properties are unset
1216         mfxVariant cfgPropsAll[eProp_TotalProps] = {};
1217         for (idx = 0; idx < eProp_TotalProps; idx++) {
1218             cfgPropsAll[idx].Type = MFX_VARIANT_TYPE_UNSET;
1219         }
1220
1221         for (idx = 0; idx < eProp_TotalProps; idx++) {
1222             // ignore unset properties
1223             if (config->m_propVar[idx].Type == MFX_VARIANT_TYPE_UNSET)
1224                 continue;
1225
1226             // if property is required function, add to list which will be checked below
1227             if (idx == ePropFunc_FunctionName) {
1228                 implFunctionList.push_back(config->m_implFunctionName);
1229                 continue;
1230             }
1231
1232             cfgPropsAll[idx].Type = config->m_propVar[idx].Type;
1233             cfgPropsAll[idx].Data = config->m_propVar[idx].Data;
1234
1235             if (idx >= ePropDec_CodecID && idx <= ePropDec_ColorFormats)
1236                 decRequested = true;
1237             else if (idx >= ePropEnc_CodecID && idx <= ePropEnc_ColorFormats)
1238                 encRequested = true;
1239             else if (idx >= ePropVPP_FilterFourCC && idx <= ePropVPP_OutFormat)
1240                 vppRequested = true;
1241             else if (idx >= ePropExtDev_VendorID && idx <= ePropExtDev_DeviceName)
1242                 extDevRequested = true;
1243         }
1244
1245         // if already marked invalid, no need to check props again
1246         // however we still need to iterate over all of the config objects
1247         //   to get any non-filtering properties (returned in SpecialConfig)
1248         if (bImplValid == true) {
1249             if (CheckPropsGeneral(cfgPropsAll, libImplDesc))
1250                 bImplValid = false;
1251
1252 #ifdef ONEVPL_EXPERIMENTAL
1253             if (extDevRequested) {
1254                 // fail if extDevID is not available (null) or if prop is not supported
1255                 if (!libImplExtDevID || CheckPropsExtDevID(cfgPropsAll, libImplExtDevID))
1256                     bImplValid = false;
1257             }
1258 #else
1259             if (extDevRequested)
1260                 bImplValid = false;
1261 #endif
1262
1263             // MSDK RT compatibility mode (1.x) does not provide Dec/Enc/VPP caps
1264             // ignore these filters if set (do not use them to _exclude_ the library)
1265             if (libType != LibTypeMSDK) {
1266                 if (decRequested && CheckPropsDec(cfgPropsAll, decConfigList))
1267                     bImplValid = false;
1268
1269                 if (encRequested && CheckPropsEnc(cfgPropsAll, encConfigList))
1270                     bImplValid = false;
1271
1272                 if (vppRequested && CheckPropsVPP(cfgPropsAll, vppConfigList))
1273                     bImplValid = false;
1274             }
1275         }
1276
1277         // update any special (including non-filtering) properties, for use by caller
1278         // if multiple cfg objects set the same non-filtering property, the last (most recent) one is used
1279         if (cfgPropsAll[ePropSpecial_HandleType].Type != MFX_VARIANT_TYPE_UNSET) {
1280             specialConfig->deviceHandleType =
1281                 (mfxHandleType)cfgPropsAll[ePropSpecial_HandleType].Data.U32;
1282             specialConfig->bIsSet_deviceHandleType = true;
1283         }
1284
1285         if (cfgPropsAll[ePropSpecial_Handle].Type != MFX_VARIANT_TYPE_UNSET) {
1286             specialConfig->deviceHandle        = (mfxHDL)cfgPropsAll[ePropSpecial_Handle].Data.Ptr;
1287             specialConfig->bIsSet_deviceHandle = true;
1288         }
1289
1290         if (cfgPropsAll[ePropSpecial_NumThread].Type != MFX_VARIANT_TYPE_UNSET) {
1291             specialConfig->NumThread        = cfgPropsAll[ePropSpecial_NumThread].Data.U32;
1292             specialConfig->bIsSet_NumThread = true;
1293         }
1294
1295         if (cfgPropsAll[ePropSpecial_DeviceCopy].Type != MFX_VARIANT_TYPE_UNSET) {
1296             specialConfig->DeviceCopy        = cfgPropsAll[ePropSpecial_DeviceCopy].Data.U16;
1297             specialConfig->bIsSet_DeviceCopy = true;
1298         }
1299
1300         if (cfgPropsAll[ePropSpecial_DXGIAdapterIndex].Type != MFX_VARIANT_TYPE_UNSET) {
1301             specialConfig->dxgiAdapterIdx =
1302                 (mfxU32)cfgPropsAll[ePropSpecial_DXGIAdapterIndex].Data.U32;
1303             specialConfig->bIsSet_dxgiAdapterIdx = true;
1304         }
1305
1306         if (cfgPropsAll[ePropMain_AccelerationMode].Type != MFX_VARIANT_TYPE_UNSET) {
1307             specialConfig->accelerationMode =
1308                 (mfxAccelerationMode)cfgPropsAll[ePropMain_AccelerationMode].Data.U32;
1309             specialConfig->bIsSet_accelerationMode = true;
1310         }
1311
1312         if (cfgPropsAll[ePropSpecial_ExtBuffer].Type != MFX_VARIANT_TYPE_UNSET) {
1313             specialConfig->ExtBuffers.push_back(
1314                 (mfxExtBuffer *)cfgPropsAll[ePropSpecial_ExtBuffer].Data.Ptr);
1315             specialConfig->bIsSet_ExtBuffer = true;
1316         }
1317
1318         // special handling for API version which may be passed either as single U32 (Version)
1319         //   or two U16 (Major, Minor) which could come in separate cfg objects
1320         if (cfgPropsAll[ePropMain_ApiVersion].Type != MFX_VARIANT_TYPE_UNSET) {
1321             reqVersion.Version = (mfxU32)cfgPropsAll[ePropMain_ApiVersion].Data.U32;
1322             bVerSetMajor       = true;
1323             bVerSetMinor       = true;
1324         }
1325         else {
1326             if (cfgPropsAll[ePropMain_ApiVersion_Major].Type != MFX_VARIANT_TYPE_UNSET) {
1327                 reqVersion.Major = (mfxU32)cfgPropsAll[ePropMain_ApiVersion_Major].Data.U16;
1328                 bVerSetMajor     = true;
1329             }
1330
1331             if (cfgPropsAll[ePropMain_ApiVersion_Minor].Type != MFX_VARIANT_TYPE_UNSET) {
1332                 reqVersion.Minor = (mfxU32)cfgPropsAll[ePropMain_ApiVersion_Minor].Data.U16;
1333                 bVerSetMinor     = true;
1334             }
1335         }
1336     }
1337
1338     if (bVerSetMajor && bVerSetMinor) {
1339         // require both Major and Minor to be set if filtering this way
1340         if (libImplDesc->ApiVersion.Version < reqVersion.Version)
1341             bImplValid = false;
1342
1343         specialConfig->ApiVersion.Version = reqVersion.Version;
1344         specialConfig->bIsSet_ApiVersion  = true;
1345     }
1346
1347     if (bImplValid == false)
1348         return MFX_ERR_UNSUPPORTED;
1349
1350     // check whether required functions are implemented
1351     if (!implFunctionList.empty()) {
1352         if (!libImplFuncs) {
1353             // library did not provide list of implemented functions
1354             return MFX_ERR_UNSUPPORTED;
1355         }
1356
1357         auto fn = implFunctionList.begin();
1358         while (fn != implFunctionList.end()) {
1359             std::string fnName = (*fn++);
1360             mfxU32 fnIdx;
1361
1362             // search for fnName in list of implemented functions
1363             for (fnIdx = 0; fnIdx < libImplFuncs->NumFunctions; fnIdx++) {
1364                 if (fnName == libImplFuncs->FunctionsName[fnIdx])
1365                     break;
1366             }
1367
1368             if (fnIdx == libImplFuncs->NumFunctions)
1369                 return MFX_ERR_UNSUPPORTED;
1370         }
1371     }
1372
1373     return MFX_ERR_NONE;
1374 }
1375
1376 bool ConfigCtxVPL::CheckLowLatencyConfig(std::list<ConfigCtxVPL *> configCtxList,
1377                                          SpecialConfig *specialConfig) {
1378     mfxU32 idx;
1379     bool bLowLatency = true;
1380
1381     // initially all properties are unset
1382     mfxVariant cfgPropsAll[eProp_TotalProps] = {};
1383     for (idx = 0; idx < eProp_TotalProps; idx++)
1384         cfgPropsAll[idx].Type = MFX_VARIANT_TYPE_UNSET;
1385
1386     // iterate through all filters and populate cfgPropsAll
1387     // for purposes of low-latency enabling, we check the last (most recent) value of each filter
1388     //   property, in the case that multiple mfxConfig objects were created
1389     // preferred usage is just to create one mfxConfig and set all of the required props in it
1390     // Exception: there can be more than one ExtBuffer attached via multiple mfxConfig objects (API >= 2.7)
1391
1392     // clear list of extension buffers
1393     specialConfig->bIsSet_ExtBuffer = false;
1394     specialConfig->ExtBuffers.clear();
1395
1396     auto it = configCtxList.begin();
1397     while (it != configCtxList.end()) {
1398         ConfigCtxVPL *config = (*it);
1399         it++;
1400
1401         for (idx = 0; idx < eProp_TotalProps; idx++) {
1402             // ignore unset properties
1403             if (config->m_propVar[idx].Type == MFX_VARIANT_TYPE_UNSET)
1404                 continue;
1405
1406             cfgPropsAll[idx].Type = config->m_propVar[idx].Type;
1407             cfgPropsAll[idx].Data = config->m_propVar[idx].Data;
1408
1409             if (idx == ePropSpecial_ExtBuffer) {
1410                 specialConfig->ExtBuffers.push_back(
1411                     (mfxExtBuffer *)cfgPropsAll[ePropSpecial_ExtBuffer].Data.Ptr);
1412                 specialConfig->bIsSet_ExtBuffer = true;
1413             }
1414         }
1415     }
1416
1417     for (mfxU32 idx = 0; idx < eProp_TotalProps; idx++) {
1418         switch (idx) {
1419             case ePropMain_Impl:
1420                 if (cfgPropsAll[idx].Type == MFX_VARIANT_TYPE_U32) {
1421                     if (cfgPropsAll[idx].Data.U32 == MFX_IMPL_TYPE_HARDWARE)
1422                         continue;
1423                 }
1424                 bLowLatency = false;
1425                 break;
1426
1427             case ePropMain_ImplName:
1428                 if (cfgPropsAll[idx].Type == MFX_VARIANT_TYPE_PTR && cfgPropsAll[idx].Data.Ptr) {
1429                     std::string s = *(std::string *)(cfgPropsAll[idx].Data.Ptr);
1430                     if (s == "mfx-gen")
1431                         continue;
1432                 }
1433                 bLowLatency = false;
1434                 break;
1435
1436             case ePropMain_VendorID:
1437                 if (cfgPropsAll[idx].Type == MFX_VARIANT_TYPE_U32) {
1438                     if (cfgPropsAll[idx].Data.U32 == 0x8086)
1439                         continue;
1440                 }
1441                 bLowLatency = false;
1442                 break;
1443
1444             // application must set AccelerationMode for lowlatency - will be passed to RT in MFXInitialize()
1445             case ePropMain_AccelerationMode:
1446                 if (cfgPropsAll[idx].Type == MFX_VARIANT_TYPE_U32) {
1447                     specialConfig->accelerationMode =
1448                         (mfxAccelerationMode)cfgPropsAll[ePropMain_AccelerationMode].Data.U32;
1449                     specialConfig->bIsSet_accelerationMode = true;
1450                     continue;
1451                 }
1452                 bLowLatency = false;
1453                 break;
1454
1455             // application may set ApiVersion with lowlatency, but not required
1456             case ePropMain_ApiVersion:
1457                 if (cfgPropsAll[ePropMain_ApiVersion].Type != MFX_VARIANT_TYPE_UNSET) {
1458                     specialConfig->ApiVersion.Version =
1459                         (mfxU32)cfgPropsAll[ePropMain_ApiVersion].Data.U32;
1460                     specialConfig->bIsSet_ApiVersion = true;
1461                 }
1462                 break;
1463
1464             // following are non-filtering properties - they may be set here or not (don't affect low latency)
1465             case ePropSpecial_HandleType:
1466                 if (cfgPropsAll[ePropSpecial_HandleType].Type != MFX_VARIANT_TYPE_UNSET) {
1467                     specialConfig->deviceHandleType =
1468                         (mfxHandleType)cfgPropsAll[ePropSpecial_HandleType].Data.U32;
1469                     specialConfig->bIsSet_deviceHandleType = true;
1470                 }
1471                 break;
1472
1473             case ePropSpecial_Handle:
1474                 if (cfgPropsAll[ePropSpecial_Handle].Type != MFX_VARIANT_TYPE_UNSET) {
1475                     specialConfig->deviceHandle = (mfxHDL)cfgPropsAll[ePropSpecial_Handle].Data.Ptr;
1476                     specialConfig->bIsSet_deviceHandle = true;
1477                 }
1478                 break;
1479
1480             case ePropSpecial_NumThread:
1481                 if (cfgPropsAll[ePropSpecial_NumThread].Type != MFX_VARIANT_TYPE_UNSET) {
1482                     specialConfig->NumThread        = cfgPropsAll[ePropSpecial_NumThread].Data.U32;
1483                     specialConfig->bIsSet_NumThread = true;
1484                 }
1485                 break;
1486
1487             case ePropSpecial_DeviceCopy:
1488                 if (cfgPropsAll[ePropSpecial_DeviceCopy].Type != MFX_VARIANT_TYPE_UNSET) {
1489                     specialConfig->DeviceCopy = cfgPropsAll[ePropSpecial_DeviceCopy].Data.U16;
1490                     specialConfig->bIsSet_DeviceCopy = true;
1491                 }
1492                 break;
1493
1494             case ePropSpecial_ExtBuffer:
1495                 // extBufs were already pushed into the overall list, above
1496                 break;
1497
1498             // will be passed to RT in MFXInitialize(), if unset will be 0
1499             case ePropSpecial_DXGIAdapterIndex:
1500                 if (cfgPropsAll[idx].Type == MFX_VARIANT_TYPE_U32) {
1501                     specialConfig->dxgiAdapterIdx =
1502                         (mfxU32)cfgPropsAll[ePropSpecial_DXGIAdapterIndex].Data.U32;
1503                     specialConfig->bIsSet_dxgiAdapterIdx = true;
1504                     continue;
1505                 }
1506                 break;
1507
1508             default:
1509                 if (cfgPropsAll[idx].Type != MFX_VARIANT_TYPE_UNSET)
1510                     bLowLatency = false;
1511                 break;
1512         }
1513     }
1514
1515     return bLowLatency;
1516 }
1517
1518 bool ConfigCtxVPL::ParseDeviceIDx86(mfxChar *cDeviceID, mfxU32 &deviceID, mfxU32 &adapterIdx) {
1519     std::string strDevID(cDeviceID);
1520     std::regex reDevIDAll("[0-9a-fA-F]+/[0-9]+");
1521     std::regex reDevIDMin("[0-9a-fA-F]+");
1522
1523     deviceID   = DEVICE_ID_UNKNOWN;
1524     adapterIdx = ADAPTER_IDX_UNKNOWN;
1525
1526     bool bHasAdapterIdx = false;
1527     if (std::regex_match(strDevID, reDevIDAll)) {
1528         // check for DeviceID in format "devID/adapterIdx"
1529         //   devID = hex value
1530         //   adapterIdx = decimal integer
1531         bHasAdapterIdx = true;
1532     }
1533     else if (std::regex_match(strDevID, reDevIDMin)) {
1534         // check for DeviceID in format "devID"
1535         //   (no adpaterIdx)
1536         bHasAdapterIdx = false;
1537     }
1538     else {
1539         // invalid format
1540         return false;
1541     }
1542
1543     // get deviceID (value before the slash, if present)
1544     try {
1545         deviceID = std::stoi(strDevID, 0, 16);
1546     }
1547     catch (...) {
1548         return false;
1549     }
1550
1551     if (bHasAdapterIdx) {
1552         // get adapter index (value after the slash)
1553         size_t idx = strDevID.rfind('/');
1554         if (idx == std::string::npos)
1555             return false;
1556
1557         try {
1558             adapterIdx = std::stoi(strDevID.substr(idx + 1));
1559         }
1560         catch (...) {
1561             return false;
1562         }
1563     }
1564
1565     return true;
1566 }