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 #include <umc_va_base.h>
22
23 #include "umc_defs.h"
24 #include "umc_va_linux.h"
25 #include "umc_va_linux_protected.h"
26 #include "umc_va_video_processing.h"
27 #include "mfx_trace.h"
28 #include "umc_frame_allocator.h"
29 #include "mfxstructures.h"
30
31 #if defined(MFX_ENABLE_CPLIB)
32 #include "mfx_cenc.h"
33 #endif
34
35 #define UMC_VA_NUM_OF_COMP_BUFFERS 8
36 #define UMC_VA_DECODE_STREAM_OUT_ENABLE 2
37
va_to_umc_res(VAStatus va_res)38 UMC::Status va_to_umc_res(VAStatus va_res)
39 {
40 UMC::Status umcRes = UMC::UMC_OK;
41
42 switch (va_res)
43 {
44 case VA_STATUS_SUCCESS:
45 umcRes = UMC::UMC_OK;
46 break;
47 case VA_STATUS_ERROR_ALLOCATION_FAILED:
48 umcRes = UMC::UMC_ERR_ALLOC;
49 break;
50 case VA_STATUS_ERROR_ATTR_NOT_SUPPORTED:
51 case VA_STATUS_ERROR_UNSUPPORTED_PROFILE:
52 case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT:
53 case VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT:
54 case VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE:
55 case VA_STATUS_ERROR_FLAG_NOT_SUPPORTED:
56 case VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED:
57 umcRes = UMC::UMC_ERR_UNSUPPORTED;
58 break;
59 case VA_STATUS_ERROR_INVALID_DISPLAY:
60 case VA_STATUS_ERROR_INVALID_CONFIG:
61 case VA_STATUS_ERROR_INVALID_CONTEXT:
62 case VA_STATUS_ERROR_INVALID_SURFACE:
63 case VA_STATUS_ERROR_INVALID_BUFFER:
64 case VA_STATUS_ERROR_INVALID_IMAGE:
65 case VA_STATUS_ERROR_INVALID_SUBPICTURE:
66 umcRes = UMC::UMC_ERR_INVALID_PARAMS;
67 break;
68 case VA_STATUS_ERROR_INVALID_PARAMETER:
69 umcRes = UMC::UMC_ERR_INVALID_PARAMS;
70 break;
71 case VA_STATUS_ERROR_DECODING_ERROR:
72 umcRes = UMC::UMC_ERR_DEVICE_FAILED;
73 break;
74 case VA_STATUS_ERROR_HW_BUSY:
75 umcRes = UMC::UMC_ERR_GPU_HANG;
76 break;
77 default:
78 umcRes = UMC::UMC_ERR_FAILED;
79 break;
80 }
81 return umcRes;
82 }
83
umc_to_va_entrypoint(uint32_t umc_entrypoint)84 VAEntrypoint umc_to_va_entrypoint(uint32_t umc_entrypoint)
85 {
86 VAEntrypoint va_entrypoint = (VAEntrypoint)-1;
87
88 switch (umc_entrypoint)
89 {
90 case UMC::VA_VLD:
91 case UMC::VA_VLD | UMC::VA_PROFILE_444:
92 case UMC::VA_VLD | UMC::VA_PROFILE_10:
93 case UMC::VA_VLD | UMC::VA_PROFILE_REXT:
94 case UMC::VA_VLD | UMC::VA_PROFILE_444 | UMC::VA_PROFILE_10:
95 case UMC::VA_VLD | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_10:
96 case UMC::VA_VLD | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_422:
97 case UMC::VA_VLD | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_444:
98 case UMC::VA_VLD | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_10 | UMC::VA_PROFILE_422:
99 case UMC::VA_VLD | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_10 | UMC::VA_PROFILE_444:
100 #if (MFX_VERSION >= 1031)
101 case UMC::VA_VLD | UMC::VA_PROFILE_12:
102 case UMC::VA_VLD | UMC::VA_PROFILE_12 | UMC::VA_PROFILE_444:
103 case UMC::VA_VLD | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_12:
104 case UMC::VA_VLD | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_12 | UMC::VA_PROFILE_422:
105 case UMC::VA_VLD | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_12 | UMC::VA_PROFILE_444:
106 case UMC::VA_VLD | UMC::VA_PROFILE_SCC:
107 case UMC::VA_VLD | UMC::VA_PROFILE_SCC | UMC::VA_PROFILE_10:
108 case UMC::VA_VLD | UMC::VA_PROFILE_SCC | UMC::VA_PROFILE_444:
109 case UMC::VA_VLD | UMC::VA_PROFILE_SCC | UMC::VA_PROFILE_444 | UMC::VA_PROFILE_10:
110 #endif
111 va_entrypoint = VAEntrypointVLD;
112 break;
113 default:
114 va_entrypoint = (VAEntrypoint)-1;
115 break;
116 }
117 return va_entrypoint;
118 }
119
120 // profile priorities for codecs
121 uint32_t g_Profiles[] =
122 {
123 UMC::MPEG2_VLD,
124 UMC::H264_VLD,
125 UMC::H265_VLD,
126 UMC::VC1_VLD,
127 UMC::VP8_VLD,
128 UMC::VP9_VLD,
129 UMC::JPEG_VLD,
130 #if defined(MFX_ENABLE_AV1_VIDEO_DECODE)
131 UMC::AV1_VLD,
132 #endif
133 };
134
135 // va profile priorities for different codecs
136 VAProfile g_Mpeg2Profiles[] =
137 {
138 VAProfileMPEG2Main, VAProfileMPEG2Simple
139 };
140
141 VAProfile g_H264Profiles[] =
142 {
143 VAProfileH264High, VAProfileH264Main, VAProfileH264ConstrainedBaseline
144 };
145
146 VAProfile g_H265Profiles[] =
147 {
148 VAProfileHEVCMain
149 };
150
151 VAProfile g_H26510BitsProfiles[] =
152 {
153 VAProfileHEVCMain10
154 };
155
156 VAProfile g_VC1Profiles[] =
157 {
158 VAProfileVC1Advanced, VAProfileVC1Main, VAProfileVC1Simple
159 };
160
161 VAProfile g_VP8Profiles[] =
162 {
163 VAProfileVP8Version0_3
164 };
165
166 VAProfile g_VP9Profiles[] =
167 {
168 VAProfileVP9Profile1, // chroma subsampling: 4:2:0, 4:2:2, 4:4:4
169 VAProfileVP9Profile0 // chroma subsampling: 4:2:0
170 };
171
172 VAProfile g_VP910BitsProfiles[] =
173 {
174 VAProfileVP9Profile3, // chroma subsampling: 4:2:0, 4:2:2, 4:4:4
175 VAProfileVP9Profile2 // chroma subsampling: 4:2:0
176 };
177
178 #if defined(MFX_ENABLE_AV1_VIDEO_DECODE)
179 VAProfile g_AV1Profiles[] =
180 {
181 VAProfileAV1Profile0
182 };
183 VAProfile g_AV110BitsPProfiles[] =
184 {
185 VAProfileAV1Profile0
186 };
187 #endif
188
189 VAProfile g_JPEGProfiles[] =
190 {
191 VAProfileJPEGBaseline
192 };
193
get_next_va_profile(uint32_t umc_codec,uint32_t profile)194 VAProfile get_next_va_profile(uint32_t umc_codec, uint32_t profile)
195 {
196 VAProfile va_profile = (VAProfile)-1;
197
198 switch (umc_codec)
199 {
200 case UMC::VA_MPEG2:
201 if (profile < UMC_ARRAY_SIZE(g_Mpeg2Profiles)) va_profile = g_Mpeg2Profiles[profile];
202 break;
203 case UMC::VA_H264:
204 if (profile < UMC_ARRAY_SIZE(g_H264Profiles)) va_profile = g_H264Profiles[profile];
205 break;
206 case UMC::VA_H265:
207 if (profile < UMC_ARRAY_SIZE(g_H265Profiles)) va_profile = g_H265Profiles[profile];
208 break;
209 #if (MFX_VERSION >= 1027)
210 case UMC::VA_H265| UMC::VA_PROFILE_422 | UMC::VA_PROFILE_REXT:
211 if (profile < 1) va_profile = VAProfileHEVCMain422_10;
212 break;
213 case UMC::VA_H265| UMC::VA_PROFILE_444 | UMC::VA_PROFILE_REXT:
214 if (profile < 1) va_profile = VAProfileHEVCMain444;
215 break;
216 #endif
217 case UMC::VA_H265 | UMC::VA_PROFILE_10:
218 if (profile < UMC_ARRAY_SIZE(g_H26510BitsProfiles)) va_profile = g_H26510BitsProfiles[profile];
219 break;
220 #if (MFX_VERSION >= 1027)
221 case UMC::VA_H265 | UMC::VA_PROFILE_REXT:
222 case UMC::VA_H265 | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_10:
223 case UMC::VA_H265 | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_422 | UMC::VA_PROFILE_10:
224 if (profile < 1) va_profile = VAProfileHEVCMain422_10;
225 break;
226 case UMC::VA_H265| UMC::VA_PROFILE_444 | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_10:
227 if (profile < 1) va_profile = VAProfileHEVCMain444_10;
228 break;
229 #endif
230 #if (MFX_VERSION >= 1031)
231 case UMC::VA_H265 | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_12:
232 case UMC::VA_H265 | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_12 | UMC::VA_PROFILE_422:
233 if (profile < 1) va_profile = VAProfileHEVCMain422_12;
234 break;
235 case UMC::VA_H265 | UMC::VA_PROFILE_REXT | UMC::VA_PROFILE_12 | UMC::VA_PROFILE_444:
236 if (profile < 1) va_profile = VAProfileHEVCMain444_12;
237 break;
238 case UMC::VA_H265 | UMC::VA_PROFILE_SCC:
239 if (profile < 1) va_profile = VAProfileHEVCSccMain;
240 break;
241 case UMC::VA_H265 | UMC::VA_PROFILE_SCC | UMC::VA_PROFILE_10:
242 if (profile < 1) va_profile = VAProfileHEVCSccMain10;
243 break;
244 case UMC::VA_H265 | UMC::VA_PROFILE_SCC | UMC::VA_PROFILE_444:
245 if (profile < 1) va_profile = VAProfileHEVCSccMain444;
246 MFX_FALLTHROUGH;
247 case UMC::VA_H265 | UMC::VA_PROFILE_SCC | UMC::VA_PROFILE_444 | UMC::VA_PROFILE_10:
248 if (profile < 1) va_profile = VAProfileHEVCSccMain444_10;
249 break;
250 #endif
251
252 case UMC::VA_VC1:
253 if (profile < UMC_ARRAY_SIZE(g_VC1Profiles)) va_profile = g_VC1Profiles[profile];
254 break;
255 case UMC::VA_VP8:
256 if (profile < UMC_ARRAY_SIZE(g_VP8Profiles)) va_profile = g_VP8Profiles[profile];
257 break;
258 case UMC::VA_VP9:
259 case UMC::VA_VP9 | UMC::VA_PROFILE_444:
260 if (profile < UMC_ARRAY_SIZE(g_VP9Profiles)) va_profile = g_VP9Profiles[profile];
261 break;
262 case UMC::VA_VP9 | UMC::VA_PROFILE_10:
263 case UMC::VA_VP9 | UMC::VA_PROFILE_444 | UMC::VA_PROFILE_10:
264 if (profile < UMC_ARRAY_SIZE(g_VP910BitsProfiles)) va_profile = g_VP910BitsProfiles[profile];
265 break;
266 #if (MFX_VERSION >= 1031)
267 case UMC::VA_VP9 | UMC::VA_PROFILE_12:
268 case UMC::VA_VP9 | UMC::VA_PROFILE_12 | UMC::VA_PROFILE_444:
269 if (profile < UMC_ARRAY_SIZE(g_VP910BitsProfiles)) va_profile = g_VP910BitsProfiles[profile];
270 break;
271 #if defined(MFX_ENABLE_AV1_VIDEO_DECODE)
272 case UMC::VA_AV1:
273 if (profile < UMC_ARRAY_SIZE(g_AV1Profiles)) va_profile = g_AV1Profiles[profile];
274 break;
275 case UMC::VA_AV1 | UMC::VA_PROFILE_10:
276 if (profile < UMC_ARRAY_SIZE(g_AV110BitsPProfiles)) va_profile = g_AV110BitsPProfiles[profile];
277 break;
278 #endif
279 #endif
280 case UMC::VA_JPEG:
281 if (profile < UMC_ARRAY_SIZE(g_JPEGProfiles)) va_profile = g_JPEGProfiles[profile];
282 break;
283 default:
284 va_profile = (VAProfile)-1;
285 break;
286 }
287 return va_profile;
288 }
289
290 namespace UMC
291 {
292
VACompBuffer(void)293 VACompBuffer::VACompBuffer(void)
294 {
295 m_NumOfItem = 0;
296 m_index = -1;
297 m_id = -1;
298 m_bDestroy = false;
299 }
300
~VACompBuffer(void)301 VACompBuffer::~VACompBuffer(void)
302 {
303 }
304
SetBufferInfo(int32_t _type,int32_t _id,int32_t _index)305 Status VACompBuffer::SetBufferInfo(int32_t _type, int32_t _id, int32_t _index)
306 {
307 type = _type;
308 m_id = _id;
309 m_index = _index;
310 return UMC_OK;
311 }
312
SetDestroyStatus(bool _destroy)313 Status VACompBuffer::SetDestroyStatus(bool _destroy)
314 {
315 UNREFERENCED_PARAMETER(_destroy);
316 m_bDestroy = true;
317 return UMC_OK;
318 }
319
LinuxVideoAccelerator(void)320 LinuxVideoAccelerator::LinuxVideoAccelerator(void)
321 : m_sDecodeTraceStart("")
322 , m_sDecodeTraceEnd("")
323 {
324 m_dpy = NULL;
325 m_pContext = NULL;
326 m_pConfigId = NULL;
327 m_pKeepVAState = NULL;
328 m_FrameState = lvaBeforeBegin;
329
330 m_pCompBuffers = NULL;
331 m_NumOfFrameBuffers = 0;
332 m_uiCompBuffersNum = 0;
333 m_uiCompBuffersUsed = 0;
334
335 #if defined(ANDROID)
336 m_isUseStatuReport = false;
337 #else
338 m_isUseStatuReport = true;
339 #endif
340
341 m_bH264MVCSupport = false;
342 memset(&m_guidDecoder, 0 , sizeof(GUID));
343 }
344
~LinuxVideoAccelerator(void)345 LinuxVideoAccelerator::~LinuxVideoAccelerator(void)
346 {
347 Close();
348 }
349
Init(VideoAcceleratorParams * pInfo)350 Status LinuxVideoAccelerator::Init(VideoAcceleratorParams* pInfo)
351 {
352 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_HOTSPOTS, "LinuxVideoAccelerator::Init");
353 Status umcRes = UMC_OK;
354 VAStatus va_res = VA_STATUS_SUCCESS;
355 VAConfigAttrib va_attributes[4];
356
357 LinuxVideoAcceleratorParams* pParams = DynamicCast<LinuxVideoAcceleratorParams>(pInfo);
358 int32_t width = 0, height = 0;
359 bool needRecreateContext = false;
360
361 // checking errors in input parameters
362 if ((UMC_OK == umcRes) && (NULL == pParams))
363 umcRes = UMC_ERR_NULL_PTR;
364 if ((UMC_OK == umcRes) && (NULL == pParams->m_pVideoStreamInfo))
365 umcRes = UMC_ERR_INVALID_PARAMS;
366 if ((UMC_OK == umcRes) && (NULL == pParams->m_Display))
367 umcRes = UMC_ERR_INVALID_PARAMS;
368 if ((UMC_OK == umcRes) && (NULL == pParams->m_pConfigId))
369 umcRes = UMC_ERR_INVALID_PARAMS;
370 if ((UMC_OK == umcRes) && (NULL == pParams->m_pContext))
371 umcRes = UMC_ERR_INVALID_PARAMS;
372 if ((UMC_OK == umcRes) && (NULL == pParams->m_pKeepVAState))
373 umcRes = UMC_ERR_INVALID_PARAMS;
374 if ((UMC_OK == umcRes) && (NULL == pParams->m_allocator))
375 umcRes = UMC_ERR_INVALID_PARAMS;
376 if ((UMC_OK == umcRes) && (pParams->m_iNumberSurfaces < 0))
377 umcRes = UMC_ERR_INVALID_PARAMS;
378
379 // filling input parameters
380 if (UMC_OK == umcRes)
381 {
382 m_dpy = pParams->m_Display;
383 m_pKeepVAState = pParams->m_pKeepVAState;
384 width = pParams->m_pVideoStreamInfo->clip_info.width;
385 height = pParams->m_pVideoStreamInfo->clip_info.height;
386 m_NumOfFrameBuffers = pParams->m_iNumberSurfaces;
387 m_allocator = pParams->m_allocator;
388 m_FrameState = lvaBeforeBegin;
389
390 if (IS_PROTECTION_ANY(pParams->m_protectedVA))
391 {
392 m_protectedVA = new ProtectedVA(pParams->m_protectedVA);
393 }
394
395 if (pParams->m_needVideoProcessingVA)
396 {
397 m_videoProcessingVA = new VideoProcessingVA();
398 }
399
400 // profile or stream type should be set
401 if (UNKNOWN == (m_Profile & VA_CODEC))
402 {
403 umcRes = UMC_ERR_INVALID_PARAMS;
404 }
405 }
406 if ((UMC_OK == umcRes) && (UNKNOWN == m_Profile))
407 umcRes = UMC_ERR_INVALID_PARAMS;
408
409 bool needAllocatedSurfaces = (((m_Profile & VA_CODEC) != UMC::VA_H264)
410 && ((m_Profile & VA_CODEC) != UMC::VA_H265)
411 && ((m_Profile & VA_CODEC) != UMC::VA_VP8)
412 && ((m_Profile & VA_CODEC) != UMC::VA_VP9)
413 && ((m_Profile & VA_CODEC) != UMC::VA_VC1)
414 && ((m_Profile & VA_CODEC) != UMC::VA_MPEG2)
415 #if defined (MFX_ENABLE_AV1_VIDEO_DECODE)
416 && ((m_Profile & VA_CODEC) != UMC::VA_AV1)
417 #endif
418 #ifndef ANDROID
419 && ((m_Profile & VA_CODEC) != UMC::VA_JPEG)
420 #endif
421 );
422
423 SetTraceStrings(m_Profile & VA_CODEC);
424
425 // display initialization
426 if (UMC_OK == umcRes)
427 {
428 int32_t i,j;
429 int va_max_num_profiles = vaMaxNumProfiles (m_dpy);
430 int va_max_num_entrypoints = vaMaxNumEntrypoints(m_dpy);
431 int va_num_profiles = 0;
432 int va_num_entrypoints = 0;
433 VAProfile* va_profiles = NULL;
434 VAEntrypoint* va_entrypoints = NULL;
435 VAProfile va_profile = (VAProfile)-1;
436 VAEntrypoint va_entrypoint = (VAEntrypoint)-1;
437
438 if (UMC_OK == umcRes)
439 {
440 if ((va_max_num_profiles <= 0) || (va_max_num_entrypoints <= 0))
441 umcRes = UMC_ERR_FAILED;
442 }
443 if (UMC_OK == umcRes)
444 {
445 va_profiles = new VAProfile[va_max_num_profiles];
446 va_entrypoints = new VAEntrypoint[va_max_num_entrypoints];
447 va_res = vaQueryConfigProfiles(m_dpy, va_profiles, &va_num_profiles);
448 umcRes = va_to_umc_res(va_res);
449 }
450
451 if (UMC_OK == umcRes)
452 {
453 // checking support of some profile
454 for (i = 0; (va_profile = get_next_va_profile(m_Profile & (VA_PROFILE | VA_CODEC), i)) != -1; ++i)
455 {
456 for (j = 0; j < va_num_profiles; ++j)
457 {
458 if (va_profile == va_profiles[j])
459 break;
460 }
461 if (j < va_num_profiles)
462 {
463 break;
464 }
465 else
466 {
467 va_profile = (VAProfile)-1;
468 continue;
469 }
470 }
471 if (va_profile < 0) umcRes = UMC_ERR_FAILED;
472
473 if ((m_Profile & VA_CODEC) == UMC::VA_VC1)
474 {
475 if ((VC1_VIDEO_RCV == pInfo->m_pVideoStreamInfo->stream_subtype)
476 || (WMV3_VIDEO == pInfo->m_pVideoStreamInfo->stream_subtype))
477 va_profile = VAProfileVC1Main;
478 else
479 va_profile = VAProfileVC1Advanced;
480 }
481 }
482 if (UMC_OK == umcRes)
483 {
484 va_res = vaQueryConfigEntrypoints(m_dpy, va_profile, va_entrypoints, &va_num_entrypoints);
485 umcRes = va_to_umc_res(va_res);
486 }
487 if (UMC_OK == umcRes)
488 {
489 uint32_t k = 0, profile = UNKNOWN;
490
491 for (k = 0; k < UMC_ARRAY_SIZE(g_Profiles); ++k)
492 {
493 if (!(m_Profile & VA_ENTRY_POINT))
494 {
495 // entrypoint is not specified, we may chose
496 if (m_Profile != (g_Profiles[k] & VA_CODEC)) continue;
497 profile = g_Profiles[k];
498 }
499 else
500 {
501 // codec and entrypoint are specified, we just need to check validity
502 profile = m_Profile;
503 }
504 va_entrypoint = umc_to_va_entrypoint(profile & VA_ENTRY_POINT);
505 for (i = 0; i < va_num_entrypoints; ++i) if (va_entrypoint == va_entrypoints[i]) break;
506 if (i < va_num_entrypoints) break;
507 else
508 {
509 va_entrypoint = (VAEntrypoint)-1;
510 if (m_Profile == profile) break;
511 else continue;
512 }
513 }
514 m_Profile = (UMC::VideoAccelerationProfile)profile;
515 if (va_entrypoint == (VAEntrypoint)-1) umcRes = UMC_ERR_FAILED;
516 }
517 if (UMC_OK == umcRes)
518 {
519 int nattr = 0;
520 // Assuming finding VLD, find out the format for the render target
521 va_attributes[nattr++].type = VAConfigAttribRTFormat;
522
523 va_attributes[nattr].type = VAConfigAttribDecSliceMode;
524 va_attributes[nattr].value = VA_DEC_SLICE_MODE_NORMAL;
525 nattr++;
526
527 va_attributes[nattr++].type = VAConfigAttribDecProcessing;
528
529 va_attributes[nattr++].type = VAConfigAttribEncryption;
530
531 va_res = vaGetConfigAttributes(m_dpy, va_profile, va_entrypoint, va_attributes, nattr);
532 umcRes = va_to_umc_res(va_res);
533 }
534
535 if (UMC_OK == umcRes)
536 {
537 va_attributes[1].value = VA_DEC_SLICE_MODE_NORMAL;
538
539 }
540
541 int32_t attribsNumber = 2;
542
543 if (UMC_OK == umcRes && pParams->m_needVideoProcessingVA)
544 {
545 // for VAProfileJPEGBaseline current driver doesn't report
546 // VAConfigAttribDecProcessing status correctly
547 if (va_attributes[2].value == VA_DEC_PROCESSING_NONE && va_profile != VAProfileJPEGBaseline)
548 umcRes = UMC_ERR_FAILED;
549 else
550 attribsNumber++;
551 }
552
553 #ifdef MFX_ENABLE_CPLIB
554 if (UMC_OK == umcRes && m_protectedVA && IS_PROTECTION_CENC(m_protectedVA->GetProtected()))
555 {
556 va_attributes[attribsNumber].type = VAConfigAttribEncryption;
557 if (m_protectedVA->GetProtected() == MFX_PROTECTION_CENC_WV_CLASSIC)
558 {
559 if (va_attributes[3].value & VA_ENCRYPTION_TYPE_CENC_CBC)
560 va_attributes[attribsNumber].value = VA_ENCRYPTION_TYPE_CENC_CBC;
561 }
562 else if (m_protectedVA->GetProtected() == MFX_PROTECTION_CENC_WV_GOOGLE_DASH)
563 {
564 if (va_attributes[3].value & VA_ENCRYPTION_TYPE_CENC_CTR_LENGTH)
565 va_attributes[attribsNumber].value = VA_ENCRYPTION_TYPE_CENC_CTR_LENGTH;
566 }
567 else
568 umcRes = UMC_ERR_FAILED;
569
570 attribsNumber++;
571 }
572 #endif
573
574 if (UMC_OK == umcRes)
575 {
576 m_pConfigId = pParams->m_pConfigId;
577 if (*m_pConfigId == VA_INVALID_ID)
578 {
579 va_res = vaCreateConfig(m_dpy, va_profile, va_entrypoint, va_attributes, attribsNumber, m_pConfigId);
580 umcRes = va_to_umc_res(va_res);
581 needRecreateContext = true;
582 }
583 }
584
585 delete[] va_profiles;
586 delete[] va_entrypoints;
587 }
588
589 // creating context
590 if (UMC_OK == umcRes)
591 {
592 m_pContext = pParams->m_pContext;
593 if ((*m_pContext != VA_INVALID_ID) && needRecreateContext)
594 {
595 vaDestroyContext(m_dpy, *m_pContext);
596 *m_pContext = VA_INVALID_ID;
597 }
598 if (*m_pContext == VA_INVALID_ID)
599 {
600 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaCreateContext");
601
602 if (needAllocatedSurfaces)
603 {
604 VM_ASSERT(pParams->m_surf && "render targets tied to the context shoul not be NULL");
605 va_res = vaCreateContext(m_dpy, *m_pConfigId, width, height, pParams->m_CreateFlags, (VASurfaceID*)pParams->m_surf, m_NumOfFrameBuffers, m_pContext);
606 }
607 else
608 {
609 VM_ASSERT(!pParams->m_surf && "render targets tied to the context shoul be NULL");
610 va_res = vaCreateContext(m_dpy, *m_pConfigId, width, height, pParams->m_CreateFlags, NULL, 0, m_pContext);
611 }
612
613 umcRes = va_to_umc_res(va_res);
614 }
615 }
616
617 return umcRes;
618 }
619
Close(void)620 Status LinuxVideoAccelerator::Close(void)
621 {
622 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_HOTSPOTS, "LinuxVideoAccelerator::Close");
623
624 if (NULL != m_pCompBuffers)
625 {
626 for (uint32_t i = 0; i < m_uiCompBuffersUsed; ++i)
627 {
628 if (m_pCompBuffers[i]->NeedDestroy() && (NULL != m_dpy))
629 {
630 VABufferID id = m_pCompBuffers[i]->GetID();
631 mfxStatus sts = CheckAndDestroyVAbuffer(m_dpy, id);
632 std::ignore = MFX_STS_TRACE(sts);
633 }
634 UMC_DELETE(m_pCompBuffers[i]);
635 }
636 delete[] m_pCompBuffers;
637 m_pCompBuffers = nullptr;
638 }
639 if (NULL != m_dpy)
640 {
641 if ((m_pContext && (*m_pContext != VA_INVALID_ID)) && !(m_pKeepVAState && *m_pKeepVAState))
642 {
643 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaDestroyContext");
644 VAStatus vaSts = vaDestroyContext(m_dpy, *m_pContext);
645 std::ignore = MFX_STS_TRACE(vaSts);
646 *m_pContext = VA_INVALID_ID;
647 }
648 if ((m_pConfigId && (*m_pConfigId != VA_INVALID_ID)) && !(m_pKeepVAState && *m_pKeepVAState))
649 {
650 VAStatus vaSts = vaDestroyConfig(m_dpy, *m_pConfigId);
651 std::ignore = MFX_STS_TRACE(vaSts);
652 *m_pConfigId = VA_INVALID_ID;
653 }
654
655 m_dpy = NULL;
656 }
657
658 delete m_protectedVA;
659 m_protectedVA = nullptr;
660
661 delete m_videoProcessingVA;
662 m_videoProcessingVA = 0;
663
664 m_FrameState = lvaBeforeBegin;
665 m_uiCompBuffersNum = 0;
666 m_uiCompBuffersUsed = 0;
667
668 return VideoAccelerator::Close();
669 }
670
BeginFrame(int32_t FrameBufIndex)671 Status LinuxVideoAccelerator::BeginFrame(int32_t FrameBufIndex)
672 {
673 Status umcRes = UMC_OK;
674 VAStatus va_res = VA_STATUS_SUCCESS;
675
676 if ((UMC_OK == umcRes) && ((FrameBufIndex < 0) || (FrameBufIndex >= m_NumOfFrameBuffers)))
677 umcRes = UMC_ERR_INVALID_PARAMS;
678
679 VASurfaceID *surface;
680 Status sts = m_allocator->GetFrameHandle(FrameBufIndex, &surface);
681 if (sts != UMC_OK)
682 return sts;
683
684 if (UMC_OK == umcRes)
685 {
686 if (lvaBeforeBegin == m_FrameState)
687 {
688 {
689 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaBeginPicture");
690 MFX_LTRACE_2(MFX_TRACE_LEVEL_EXTCALL, m_sDecodeTraceStart, "%d|%d", *m_pContext, 0);
691 va_res = vaBeginPicture(m_dpy, *m_pContext, *surface);
692 }
693 umcRes = va_to_umc_res(va_res);
694 if (UMC_OK == umcRes) m_FrameState = lvaBeforeEnd;
695 }
696 }
697 return umcRes;
698 }
699
AllocCompBuffers(void)700 Status LinuxVideoAccelerator::AllocCompBuffers(void)
701 {
702 Status umcRes = UMC_OK;
703
704 if ((UMC_OK == umcRes) && (m_uiCompBuffersUsed >= m_uiCompBuffersNum))
705 {
706 if (NULL == m_pCompBuffers)
707 {
708 m_uiCompBuffersNum = UMC_VA_NUM_OF_COMP_BUFFERS;
709 m_pCompBuffers = new VACompBuffer*[m_uiCompBuffersNum];
710 }
711 else
712 {
713 uint32_t uiNewCompBuffersNum = 0;
714 VACompBuffer** pNewCompBuffers = NULL;
715
716 uiNewCompBuffersNum = m_uiCompBuffersNum + UMC_VA_NUM_OF_COMP_BUFFERS;
717 pNewCompBuffers = new VACompBuffer*[uiNewCompBuffersNum];
718
719 MFX_INTERNAL_CPY((uint8_t*)pNewCompBuffers, (const uint8_t*)m_pCompBuffers, m_uiCompBuffersNum*sizeof(VACompBuffer*));
720 delete[] m_pCompBuffers;
721 m_uiCompBuffersNum = uiNewCompBuffersNum;
722 m_pCompBuffers = pNewCompBuffers;
723 }
724 }
725 return umcRes;
726 }
727
GetCompBuffer(int32_t buffer_type,UMCVACompBuffer ** buf,int32_t size,int32_t index)728 void* LinuxVideoAccelerator::GetCompBuffer(int32_t buffer_type, UMCVACompBuffer **buf, int32_t size, int32_t index)
729 {
730 uint32_t i;
731 VACompBuffer* pCompBuf = NULL;
732 void* pBufferPointer = NULL;
733
734 if (NULL != buf) *buf = NULL;
735
736 std::lock_guard<std::mutex> guard(m_SyncMutex);
737 for (i = 0; i < m_uiCompBuffersUsed; ++i)
738 {
739 pCompBuf = m_pCompBuffers[i];
740 if ((pCompBuf->GetType() == buffer_type) && (pCompBuf->GetIndex() == index)) break;
741 }
742 if (i >= m_uiCompBuffersUsed)
743 {
744 AllocCompBuffers();
745 pCompBuf = GetCompBufferHW(buffer_type, size, index);
746 if (NULL != pCompBuf)
747 {
748 m_pCompBuffers[m_uiCompBuffersUsed] = pCompBuf;
749 ++m_uiCompBuffersUsed;
750 }
751 }
752 if (NULL != pCompBuf)
753 {
754 if (NULL != buf) *buf = pCompBuf;
755 pBufferPointer = pCompBuf->GetPtr();
756 }
757 return pBufferPointer;
758 }
759
GetCompBufferHW(int32_t type,int32_t size,int32_t index)760 VACompBuffer* LinuxVideoAccelerator::GetCompBufferHW(int32_t type, int32_t size, int32_t index)
761 {
762 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_INTERNAL, "GetCompBufferHW");
763 VAStatus va_res = VA_STATUS_SUCCESS;
764 VABufferID id;
765 uint8_t* buffer = NULL;
766 uint32_t buffer_size = 0;
767 VACompBuffer* pCompBuffer = NULL;
768
769 if (VA_STATUS_SUCCESS == va_res)
770 {
771 VABufferType va_type = (VABufferType)type;
772 unsigned int va_size = 0;
773 unsigned int va_num_elements = 0;
774
775 if (VASliceParameterBufferType == va_type)
776 {
777 switch (m_Profile & VA_CODEC)
778 {
779 case UMC::VA_MPEG2:
780 va_size = sizeof(VASliceParameterBufferMPEG2);
781 va_num_elements = size/sizeof(VASliceParameterBufferMPEG2);
782 break;
783 case UMC::VA_H264:
784 if (m_bH264ShortSlice)
785 {
786 va_size = sizeof(VASliceParameterBufferBase);
787 va_num_elements = size/sizeof(VASliceParameterBufferBase);
788 }
789 else
790 {
791 va_size = sizeof(VASliceParameterBufferH264);
792 va_num_elements = size/sizeof(VASliceParameterBufferH264);
793 }
794 break;
795 case UMC::VA_VC1:
796 va_size = sizeof(VASliceParameterBufferVC1);
797 va_num_elements = size/sizeof(VASliceParameterBufferVC1);
798 break;
799 case UMC::VA_VP8:
800 va_size = sizeof(VASliceParameterBufferVP8);
801 va_num_elements = size/sizeof(VASliceParameterBufferVP8);
802 break;
803 case UMC::VA_JPEG:
804 va_size = sizeof(VASliceParameterBufferJPEGBaseline);
805 va_num_elements = size/sizeof(VASliceParameterBufferJPEGBaseline);
806 break;
807 case UMC::VA_VP9:
808 va_size = sizeof(VASliceParameterBufferVP9);
809 va_num_elements = size/sizeof(VASliceParameterBufferVP9);
810 break;
811 case UMC::VA_H265:
812 case UMC::VA_H265 | UMC::VA_PROFILE_10:
813 va_size = sizeof(VASliceParameterBufferHEVC);
814 va_num_elements = size/sizeof(VASliceParameterBufferHEVC);
815 #if (MFX_VERSION >= 1027)
816 if ((m_Profile & VA_PROFILE_REXT)
817 #if (MFX_VERSION >= 1032)
818 || (m_Profile & VA_PROFILE_SCC)
819 #endif
820 )
821 {
822 va_size = sizeof(VASliceParameterBufferHEVCExtension);
823 va_num_elements = size/sizeof(VASliceParameterBufferHEVCExtension);
824 }
825 #endif
826 break;
827 #if defined(MFX_ENABLE_AV1_VIDEO_DECODE)
828 case UMC::VA_AV1:
829 va_size = sizeof(VASliceParameterBufferAV1);
830 va_num_elements = size/sizeof(VASliceParameterBufferAV1);
831 break;
832 #endif
833 default:
834 va_size = 0;
835 va_num_elements = 0;
836 break;
837 }
838 }
839 else
840 {
841 va_size = size;
842 va_num_elements = 1;
843 }
844 buffer_size = va_size * va_num_elements;
845
846 va_res = vaCreateBuffer(m_dpy, *m_pContext, va_type, va_size, va_num_elements, NULL, &id);
847 }
848 if (VA_STATUS_SUCCESS == va_res)
849 {
850 va_res = vaMapBuffer(m_dpy, id, (void**)&buffer);
851 }
852 if (VA_STATUS_SUCCESS == va_res)
853 {
854 pCompBuffer = new VACompBuffer();
855 pCompBuffer->SetBufferPointer(buffer, buffer_size);
856 pCompBuffer->SetDataSize(0);
857 pCompBuffer->SetBufferInfo(type, id, index);
858 pCompBuffer->SetDestroyStatus(true);
859 }
860 return pCompBuffer;
861 }
862
863 Status
Execute()864 LinuxVideoAccelerator::Execute()
865 {
866 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_INTERNAL, "Execute");
867 Status umcRes = UMC_OK;
868 VAStatus va_res = VA_STATUS_SUCCESS;
869 VAStatus va_sts = VA_STATUS_SUCCESS;
870 VABufferID id;
871 uint32_t i;
872 VACompBuffer* pCompBuf = NULL;
873
874 if (UMC_OK == umcRes)
875 {
876 std::lock_guard<std::mutex> guard(m_SyncMutex);
877 for (i = 0; i < m_uiCompBuffersUsed; i++)
878 {
879 pCompBuf = m_pCompBuffers[i];
880 id = pCompBuf->GetID();
881
882 if (!m_bH264ShortSlice)
883 {
884 if (pCompBuf->GetType() == VASliceParameterBufferType)
885 {
886 va_sts = vaBufferSetNumElements(m_dpy, id, pCompBuf->GetNumOfItem());
887 if (VA_STATUS_SUCCESS == va_res) va_res = va_sts;
888 }
889 }
890
891 va_sts = vaUnmapBuffer(m_dpy, id);
892 if (VA_STATUS_SUCCESS == va_res) va_res = va_sts;
893
894
895 {
896 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaRenderPicture");
897 va_sts = vaRenderPicture(m_dpy, *m_pContext, &id, 1); // TODO: send all at once?
898 if (VA_STATUS_SUCCESS == va_res) va_res = va_sts;
899 }
900 }
901 }
902
903 if (UMC_OK == umcRes)
904 {
905 umcRes = va_to_umc_res(va_res);
906 }
907 return umcRes;
908 }
909
EndFrame(void *)910 Status LinuxVideoAccelerator::EndFrame(void*)
911 {
912 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_INTERNAL, "EndFrame");
913 VAStatus va_res = VA_STATUS_SUCCESS;
914
915 std::lock_guard<std::mutex> guard(m_SyncMutex);
916
917 {
918 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaEndPicture");
919 va_res = vaEndPicture(m_dpy, *m_pContext);
920 MFX_LTRACE_2(MFX_TRACE_LEVEL_EXTCALL, m_sDecodeTraceEnd, "%d|%d", *m_pContext, 0);
921 }
922 std::ignore = MFX_STS_TRACE(va_res);
923 Status stsRet = va_to_umc_res(va_res);
924
925 m_FrameState = lvaBeforeBegin;
926
927 for (uint32_t i = 0; i < m_uiCompBuffersUsed; ++i)
928 {
929 if (m_pCompBuffers[i]->NeedDestroy())
930 {
931 VABufferID id = m_pCompBuffers[i]->GetID();
932 mfxStatus sts = CheckAndDestroyVAbuffer(m_dpy, id);
933 std::ignore = MFX_STS_TRACE(sts);
934
935 if (sts != MFX_ERR_NONE)
936 stsRet = UMC_ERR_FAILED;
937 }
938 UMC_DELETE(m_pCompBuffers[i]);
939 }
940 m_uiCompBuffersUsed = 0;
941
942 return stsRet;
943 }
944
945 /* TODO: need to rewrite return value type (possible problems with signed/unsigned) */
GetSurfaceID(int32_t idx)946 int32_t LinuxVideoAccelerator::GetSurfaceID(int32_t idx)
947 {
948 VASurfaceID *surface;
949 Status sts = UMC_OK;
950
951 try {
952 sts = m_allocator->GetFrameHandle(idx, &surface);
953 } catch (std::exception&) {
954 return VA_INVALID_SURFACE;
955 }
956
957 if (sts != UMC_OK)
958 return VA_INVALID_SURFACE;
959
960 return *surface;
961 }
962
GetDecodingError()963 uint16_t LinuxVideoAccelerator::GetDecodingError()
964 {
965 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "GetDecodingError");
966 uint16_t error = 0;
967
968 #ifndef ANDROID
969 // NOTE: at the moment there is no such support for Android, so no need to execute...
970 VAStatus va_sts;
971
972 // TODO: to reduce number of checks we can cache all used render targets
973 // during vaBeginPicture() call. For now check all render targets binded to context
974 for(int cnt = 0; cnt < m_NumOfFrameBuffers; ++cnt)
975 {
976 VASurfaceDecodeMBErrors* pVaDecErr = NULL;
977 VASurfaceID *surface;
978 Status sts = m_allocator->GetFrameHandle(cnt, &surface);
979 if (sts != UMC_OK)
980 return sts;
981
982 va_sts = vaQuerySurfaceError(m_dpy, *surface, VA_STATUS_ERROR_DECODING_ERROR, (void**)&pVaDecErr);
983
984 if (VA_STATUS_SUCCESS == va_sts)
985 {
986 if (NULL != pVaDecErr)
987 {
988 for (int i = 0; pVaDecErr[i].status != -1; ++i)
989 {
990 error = MFX_CORRUPTION_MAJOR;
991 }
992 }
993 else
994 {
995 error = MFX_CORRUPTION_MAJOR;
996 }
997 }
998 }
999 #endif
1000 return error;
1001 }
1002
1003
SetTraceStrings(uint32_t umc_codec)1004 void LinuxVideoAccelerator::SetTraceStrings(uint32_t umc_codec)
1005 {
1006 switch (umc_codec)
1007 {
1008 case UMC::VA_MPEG2:
1009 m_sDecodeTraceStart = "A|DECODE|MPEG2|PACKET_START|";
1010 m_sDecodeTraceEnd = "A|DECODE|MPEG2|PACKET_END|";
1011 break;
1012 case UMC::VA_H264:
1013 m_sDecodeTraceStart = "A|DECODE|H264|PACKET_START|";
1014 m_sDecodeTraceEnd = "A|DECODE|H264|PACKET_END|";
1015 break;
1016 case UMC::VA_H265:
1017 m_sDecodeTraceStart = "A|DECODE|H265|PACKET_START|";
1018 m_sDecodeTraceEnd = "A|DECODE|H265|PACKET_END|";
1019 break;
1020 case UMC::VA_VC1:
1021 m_sDecodeTraceStart = "A|DECODE|VC1|PACKET_START|";
1022 m_sDecodeTraceEnd = "A|DECODE|VC1|PACKET_END|";
1023 break;
1024 case UMC::VA_VP8:
1025 m_sDecodeTraceStart = "A|DECODE|VP8|PACKET_START|";
1026 m_sDecodeTraceEnd = "A|DECODE|VP8|PACKET_END|";
1027 break;
1028 case UMC::VA_VP9:
1029 m_sDecodeTraceStart = "A|DECODE|VP9|PACKET_START|";
1030 m_sDecodeTraceEnd = "A|DECODE|VP9|PACKET_END|";
1031 break;
1032 case UMC::VA_JPEG:
1033 m_sDecodeTraceStart = "A|DECODE|JPEG|PACKET_START|";
1034 m_sDecodeTraceEnd = "A|DECODE|JPEG|PACKET_END|";
1035 break;
1036 default:
1037 m_sDecodeTraceStart = "";
1038 m_sDecodeTraceEnd = "";
1039 break;
1040 }
1041 }
1042
QueryTaskStatus(int32_t FrameBufIndex,void * status,void * error)1043 Status LinuxVideoAccelerator::QueryTaskStatus(int32_t FrameBufIndex, void * status, void * error)
1044 {
1045 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_HOTSPOTS, "QueryTaskStatus");
1046 if ((FrameBufIndex < 0) || (FrameBufIndex >= m_NumOfFrameBuffers))
1047 return UMC_ERR_INVALID_PARAMS;
1048
1049 VASurfaceID *surface;
1050 Status sts = m_allocator->GetFrameHandle(FrameBufIndex, &surface);
1051 if (sts != UMC_OK)
1052 return sts;
1053
1054 VASurfaceStatus surface_status;
1055
1056 VAStatus va_status = vaQuerySurfaceStatus(m_dpy, *surface, &surface_status);
1057 VAStatus va_sts;
1058 if ((VA_STATUS_SUCCESS == va_status) && (VASurfaceReady == surface_status))
1059 {
1060 // handle decoding errors
1061 va_sts = vaSyncSurface(m_dpy, *surface);
1062
1063 if (error)
1064 {
1065 switch (va_sts)
1066 {
1067 case VA_STATUS_ERROR_DECODING_ERROR:
1068 *(uint16_t*)error = GetDecodingError();
1069 break;
1070
1071 case VA_STATUS_ERROR_HW_BUSY:
1072 va_status = VA_STATUS_ERROR_HW_BUSY;
1073 break;
1074 }
1075 }
1076 }
1077
1078 if (NULL != status)
1079 {
1080 *(VASurfaceStatus*)status = surface_status; // done or not
1081 }
1082
1083 Status umcRes = va_to_umc_res(va_status); // OK or not
1084
1085 return umcRes;
1086 }
1087
SyncTask(int32_t FrameBufIndex,void * surfCorruption)1088 Status LinuxVideoAccelerator::SyncTask(int32_t FrameBufIndex, void *surfCorruption)
1089 {
1090 if ((FrameBufIndex < 0) || (FrameBufIndex >= m_NumOfFrameBuffers))
1091 return UMC_ERR_INVALID_PARAMS;
1092
1093 VASurfaceID *surface;
1094 Status umcRes = m_allocator->GetFrameHandle(FrameBufIndex, &surface);
1095 if (umcRes != UMC_OK)
1096 return umcRes;
1097
1098 VAStatus va_sts = VA_STATUS_SUCCESS;
1099 {
1100 MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_EXTCALL, "vaSyncSurface");
1101 va_sts = vaSyncSurface(m_dpy, *surface);
1102 }
1103 if (VA_STATUS_ERROR_DECODING_ERROR == va_sts)
1104 {
1105 if (surfCorruption) *(uint16_t*)surfCorruption = GetDecodingError();
1106 return UMC_OK;
1107 }
1108 if (VA_STATUS_ERROR_OPERATION_FAILED == va_sts)
1109 {
1110 if (surfCorruption) *(uint16_t*)surfCorruption = MFX_CORRUPTION_MAJOR;
1111 return UMC_OK;
1112 }
1113 return va_to_umc_res(va_sts);
1114 }
1115
1116 }; // namespace UMC
1117
1118