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