1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
3  */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 
8 #pragma GCC visibility push(default)
9 #include <va/va.h>
10 #pragma GCC visibility pop
11 
12 #include "mozilla/Types.h"
13 #include <dlfcn.h>
14 #include <pthread.h>
15 #include <stdlib.h>
16 
17 #define GET_FUNC(func, lib) (func##Fn = dlsym(lib, #func))
18 
19 #define IS_FUNC_LOADED(func) (func##Fn != NULL)
20 
21 static VAStatus (*vaDestroyBufferFn)(VADisplay dpy, VABufferID buffer_id);
22 static VAStatus (*vaBeginPictureFn)(VADisplay dpy, VAContextID context,
23                                     VASurfaceID render_target);
24 static VAStatus (*vaEndPictureFn)(VADisplay dpy, VAContextID context);
25 static VAStatus (*vaRenderPictureFn)(VADisplay dpy, VAContextID context,
26                                      VABufferID* buffers, int num_buffers);
27 static int (*vaMaxNumProfilesFn)(VADisplay dpy);
28 static VAStatus (*vaCreateContextFn)(VADisplay dpy, VAConfigID config_id,
29                                      int picture_width, int picture_height,
30                                      int flag, VASurfaceID* render_targets,
31                                      int num_render_targets,
32                                      VAContextID* context /* out */);
33 static VAStatus (*vaDestroyContextFn)(VADisplay dpy, VAContextID context);
34 static VAStatus (*vaCreateBufferFn)(VADisplay dpy, VAContextID context,
35                                     VABufferType type,         /* in */
36                                     unsigned int size,         /* in */
37                                     unsigned int num_elements, /* in */
38                                     void* data,                /* in */
39                                     VABufferID* buf_id /* out */);
40 static VAStatus (*vaQuerySurfaceAttributesFn)(VADisplay dpy, VAConfigID config,
41                                               VASurfaceAttrib* attrib_list,
42                                               unsigned int* num_attribs);
43 static VAStatus (*vaQueryConfigProfilesFn)(VADisplay dpy,
44                                            VAProfile* profile_list, /* out */
45                                            int* num_profiles /* out */);
46 static const char* (*vaErrorStrFn)(VAStatus error_status);
47 static VAStatus (*vaCreateConfigFn)(VADisplay dpy, VAProfile profile,
48                                     VAEntrypoint entrypoint,
49                                     VAConfigAttrib* attrib_list,
50                                     int num_attribs,
51                                     VAConfigID* config_id /* out */);
52 static VAStatus (*vaDestroyConfigFn)(VADisplay dpy, VAConfigID config_id);
53 static int (*vaMaxNumImageFormatsFn)(VADisplay dpy);
54 static VAStatus (*vaQueryImageFormatsFn)(VADisplay dpy,
55                                          VAImageFormat* format_list, /* out */
56                                          int* num_formats /* out */);
57 static const char* (*vaQueryVendorStringFn)(VADisplay dpy);
58 static VAStatus (*vaDestroySurfacesFn)(VADisplay dpy, VASurfaceID* surfaces,
59                                        int num_surfaces);
60 static VAStatus (*vaCreateSurfacesFn)(VADisplay dpy, unsigned int format,
61                                       unsigned int width, unsigned int height,
62                                       VASurfaceID* surfaces,
63                                       unsigned int num_surfaces,
64                                       VASurfaceAttrib* attrib_list,
65                                       unsigned int num_attribs);
66 static VAStatus (*vaDeriveImageFn)(VADisplay dpy, VASurfaceID surface,
67                                    VAImage* image /* out */);
68 static VAStatus (*vaDestroyImageFn)(VADisplay dpy, VAImageID image);
69 static VAStatus (*vaPutImageFn)(VADisplay dpy, VASurfaceID surface,
70                                 VAImageID image, int src_x, int src_y,
71                                 unsigned int src_width, unsigned int src_height,
72                                 int dest_x, int dest_y, unsigned int dest_width,
73                                 unsigned int dest_height);
74 static VAStatus (*vaSyncSurfaceFn)(VADisplay dpy, VASurfaceID render_target);
75 static VAStatus (*vaCreateImageFn)(VADisplay dpy, VAImageFormat* format,
76                                    int width, int height,
77                                    VAImage* image /* out */);
78 static VAStatus (*vaGetImageFn)(
79     VADisplay dpy, VASurfaceID surface,
80     int x,                     /* coordinates of the upper left source pixel */
81     int y, unsigned int width, /* width and height of the region */
82     unsigned int height, VAImageID image);
83 static VAStatus (*vaMapBufferFn)(VADisplay dpy, VABufferID buf_id, /* in */
84                                  void** pbuf /* out */);
85 static VAStatus (*vaUnmapBufferFn)(VADisplay dpy, VABufferID buf_id /* in */);
86 static VAStatus (*vaTerminateFn)(VADisplay dpy);
87 static VAStatus (*vaInitializeFn)(VADisplay dpy, int* major_version, /* out */
88                                   int* minor_version /* out */);
89 static VAStatus (*vaSetDriverNameFn)(VADisplay dpy, char* driver_name);
90 static int (*vaMaxNumEntrypointsFn)(VADisplay dpy);
91 static VAStatus (*vaQueryConfigEntrypointsFn)(VADisplay dpy, VAProfile profile,
92                                               VAEntrypoint* entrypoint_list,
93                                               int* num_entrypoints);
94 static VAMessageCallback (*vaSetErrorCallbackFn)(VADisplay dpy,
95                                                  VAMessageCallback callback,
96                                                  void* user_context);
97 static VAMessageCallback (*vaSetInfoCallbackFn)(VADisplay dpy,
98                                                 VAMessageCallback callback,
99                                                 void* user_context);
LoadVALibrary()100 int LoadVALibrary() {
101   static pthread_mutex_t sVALock = PTHREAD_MUTEX_INITIALIZER;
102   static void* sVALib = NULL;
103   static int sVAInitialized = 0;
104   static int sVALoaded = 0;
105 
106   pthread_mutex_lock(&sVALock);
107 
108   if (!sVAInitialized) {
109     sVAInitialized = 1;
110     sVALib = dlopen("libva.so.2", RTLD_LAZY);
111     if (!sVALib) {
112       pthread_mutex_unlock(&sVALock);
113       return 0;
114     }
115     GET_FUNC(vaDestroyBuffer, sVALib);
116     GET_FUNC(vaBeginPicture, sVALib);
117     GET_FUNC(vaEndPicture, sVALib);
118     GET_FUNC(vaRenderPicture, sVALib);
119     GET_FUNC(vaMaxNumProfiles, sVALib);
120     GET_FUNC(vaCreateContext, sVALib);
121     GET_FUNC(vaDestroyContext, sVALib);
122     GET_FUNC(vaCreateBuffer, sVALib);
123     GET_FUNC(vaQuerySurfaceAttributes, sVALib);
124     GET_FUNC(vaQueryConfigProfiles, sVALib);
125     GET_FUNC(vaErrorStr, sVALib);
126     GET_FUNC(vaCreateConfig, sVALib);
127     GET_FUNC(vaDestroyConfig, sVALib);
128     GET_FUNC(vaMaxNumImageFormats, sVALib);
129     GET_FUNC(vaQueryImageFormats, sVALib);
130     GET_FUNC(vaQueryVendorString, sVALib);
131     GET_FUNC(vaDestroySurfaces, sVALib);
132     GET_FUNC(vaCreateSurfaces, sVALib);
133     GET_FUNC(vaDeriveImage, sVALib);
134     GET_FUNC(vaDestroyImage, sVALib);
135     GET_FUNC(vaPutImage, sVALib);
136     GET_FUNC(vaSyncSurface, sVALib);
137     GET_FUNC(vaCreateImage, sVALib);
138     GET_FUNC(vaGetImage, sVALib);
139     GET_FUNC(vaMapBuffer, sVALib);
140     GET_FUNC(vaUnmapBuffer, sVALib);
141     GET_FUNC(vaTerminate, sVALib);
142     GET_FUNC(vaInitialize, sVALib);
143     GET_FUNC(vaSetDriverName, sVALib);
144     GET_FUNC(vaMaxNumEntrypoints, sVALib);
145     GET_FUNC(vaQueryConfigEntrypoints, sVALib);
146     GET_FUNC(vaSetErrorCallback, sVALib);
147     GET_FUNC(vaSetInfoCallback, sVALib);
148 
149     sVALoaded =
150         (IS_FUNC_LOADED(vaDestroyBuffer) && IS_FUNC_LOADED(vaBeginPicture) &&
151          IS_FUNC_LOADED(vaEndPicture) && IS_FUNC_LOADED(vaRenderPicture) &&
152          IS_FUNC_LOADED(vaMaxNumProfiles) && IS_FUNC_LOADED(vaCreateContext) &&
153          IS_FUNC_LOADED(vaDestroyContext) && IS_FUNC_LOADED(vaCreateBuffer) &&
154          IS_FUNC_LOADED(vaQuerySurfaceAttributes) &&
155          IS_FUNC_LOADED(vaQueryConfigProfiles) && IS_FUNC_LOADED(vaErrorStr) &&
156          IS_FUNC_LOADED(vaCreateConfig) && IS_FUNC_LOADED(vaDestroyConfig) &&
157          IS_FUNC_LOADED(vaMaxNumImageFormats) &&
158          IS_FUNC_LOADED(vaQueryImageFormats) &&
159          IS_FUNC_LOADED(vaQueryVendorString) &&
160          IS_FUNC_LOADED(vaDestroySurfaces) &&
161          IS_FUNC_LOADED(vaCreateSurfaces) && IS_FUNC_LOADED(vaDeriveImage) &&
162          IS_FUNC_LOADED(vaDestroyImage) && IS_FUNC_LOADED(vaPutImage) &&
163          IS_FUNC_LOADED(vaSyncSurface) && IS_FUNC_LOADED(vaCreateImage) &&
164          IS_FUNC_LOADED(vaGetImage) && IS_FUNC_LOADED(vaMapBuffer) &&
165          IS_FUNC_LOADED(vaUnmapBuffer) && IS_FUNC_LOADED(vaTerminate) &&
166          IS_FUNC_LOADED(vaInitialize) && IS_FUNC_LOADED(vaSetDriverName) &&
167          IS_FUNC_LOADED(vaMaxNumEntrypoints) &&
168          IS_FUNC_LOADED(vaQueryConfigEntrypoints) &&
169          IS_FUNC_LOADED(vaSetErrorCallback) &&
170          IS_FUNC_LOADED(vaSetInfoCallback));
171   }
172   pthread_mutex_unlock(&sVALock);
173   return sVALoaded;
174 }
175 
176 #pragma GCC visibility push(default)
177 
vaDestroyBuffer(VADisplay dpy,VABufferID buffer_id)178 VAStatus vaDestroyBuffer(VADisplay dpy, VABufferID buffer_id) {
179   if (LoadVALibrary()) {
180     return vaDestroyBufferFn(dpy, buffer_id);
181   }
182   return VA_STATUS_ERROR_UNIMPLEMENTED;
183 }
184 
vaBeginPicture(VADisplay dpy,VAContextID context,VASurfaceID render_target)185 VAStatus vaBeginPicture(VADisplay dpy, VAContextID context,
186                         VASurfaceID render_target) {
187   if (LoadVALibrary()) {
188     return vaBeginPictureFn(dpy, context, render_target);
189   }
190   return VA_STATUS_ERROR_UNIMPLEMENTED;
191 }
192 
vaEndPicture(VADisplay dpy,VAContextID context)193 VAStatus vaEndPicture(VADisplay dpy, VAContextID context) {
194   if (LoadVALibrary()) {
195     return vaEndPictureFn(dpy, context);
196   }
197   return VA_STATUS_ERROR_UNIMPLEMENTED;
198 }
199 
vaRenderPicture(VADisplay dpy,VAContextID context,VABufferID * buffers,int num_buffers)200 VAStatus vaRenderPicture(VADisplay dpy, VAContextID context,
201                          VABufferID* buffers, int num_buffers) {
202   if (LoadVALibrary()) {
203     return vaRenderPictureFn(dpy, context, buffers, num_buffers);
204   }
205   return VA_STATUS_ERROR_UNIMPLEMENTED;
206 }
207 
vaMaxNumProfiles(VADisplay dpy)208 int vaMaxNumProfiles(VADisplay dpy) {
209   if (LoadVALibrary()) {
210     return vaMaxNumProfilesFn(dpy);
211   }
212   return 0;
213 }
214 
vaCreateContext(VADisplay dpy,VAConfigID config_id,int picture_width,int picture_height,int flag,VASurfaceID * render_targets,int num_render_targets,VAContextID * context)215 VAStatus vaCreateContext(VADisplay dpy, VAConfigID config_id, int picture_width,
216                          int picture_height, int flag,
217                          VASurfaceID* render_targets, int num_render_targets,
218                          VAContextID* context /* out */) {
219   if (LoadVALibrary()) {
220     return vaCreateContextFn(dpy, config_id, picture_width, picture_height,
221                              flag, render_targets, num_render_targets, context);
222   }
223   *context = 0;
224   return VA_STATUS_ERROR_UNIMPLEMENTED;
225 }
226 
vaDestroyContext(VADisplay dpy,VAContextID context)227 VAStatus vaDestroyContext(VADisplay dpy, VAContextID context) {
228   if (LoadVALibrary()) {
229     return vaDestroyContextFn(dpy, context);
230   }
231   return VA_STATUS_ERROR_UNIMPLEMENTED;
232 }
233 
vaCreateBuffer(VADisplay dpy,VAContextID context,VABufferType type,unsigned int size,unsigned int num_elements,void * data,VABufferID * buf_id)234 VAStatus vaCreateBuffer(VADisplay dpy, VAContextID context,
235                         VABufferType type,         /* in */
236                         unsigned int size,         /* in */
237                         unsigned int num_elements, /* in */
238                         void* data,                /* in */
239                         VABufferID* buf_id /* out */) {
240   if (LoadVALibrary()) {
241     return vaCreateBufferFn(dpy, context, type, size, num_elements, data,
242                             buf_id);
243   }
244   *buf_id = 0;
245   return VA_STATUS_ERROR_UNIMPLEMENTED;
246 }
247 
vaQuerySurfaceAttributes(VADisplay dpy,VAConfigID config,VASurfaceAttrib * attrib_list,unsigned int * num_attribs)248 VAStatus vaQuerySurfaceAttributes(VADisplay dpy, VAConfigID config,
249                                   VASurfaceAttrib* attrib_list,
250                                   unsigned int* num_attribs) {
251   if (LoadVALibrary()) {
252     return vaQuerySurfaceAttributesFn(dpy, config, attrib_list, num_attribs);
253   }
254   return VA_STATUS_ERROR_UNIMPLEMENTED;
255 }
256 
vaQueryConfigProfiles(VADisplay dpy,VAProfile * profile_list,int * num_profiles)257 VAStatus vaQueryConfigProfiles(VADisplay dpy, VAProfile* profile_list, /* out */
258                                int* num_profiles /* out */) {
259   if (LoadVALibrary()) {
260     return vaQueryConfigProfilesFn(dpy, profile_list, num_profiles);
261   }
262   *num_profiles = 0;
263   return VA_STATUS_ERROR_UNIMPLEMENTED;
264 }
265 
vaErrorStr(VAStatus error_status)266 const char* vaErrorStr(VAStatus error_status) {
267   if (LoadVALibrary()) {
268     return vaErrorStrFn(error_status);
269   }
270   static char tmp[] = "Unimplemented";
271   return tmp;
272 }
273 
vaCreateConfig(VADisplay dpy,VAProfile profile,VAEntrypoint entrypoint,VAConfigAttrib * attrib_list,int num_attribs,VAConfigID * config_id)274 VAStatus vaCreateConfig(VADisplay dpy, VAProfile profile,
275                         VAEntrypoint entrypoint, VAConfigAttrib* attrib_list,
276                         int num_attribs, VAConfigID* config_id /* out */) {
277   if (LoadVALibrary()) {
278     return vaCreateConfigFn(dpy, profile, entrypoint, attrib_list, num_attribs,
279                             config_id);
280   }
281   *config_id = 0;
282   return VA_STATUS_ERROR_UNIMPLEMENTED;
283 }
284 
vaDestroyConfig(VADisplay dpy,VAConfigID config_id)285 VAStatus vaDestroyConfig(VADisplay dpy, VAConfigID config_id) {
286   if (LoadVALibrary()) {
287     return vaDestroyConfigFn(dpy, config_id);
288   }
289   return VA_STATUS_ERROR_UNIMPLEMENTED;
290 }
291 
vaMaxNumImageFormats(VADisplay dpy)292 int vaMaxNumImageFormats(VADisplay dpy) {
293   if (LoadVALibrary()) {
294     return vaMaxNumImageFormatsFn(dpy);
295   }
296   return 0;
297 }
298 
vaQueryImageFormats(VADisplay dpy,VAImageFormat * format_list,int * num_formats)299 VAStatus vaQueryImageFormats(VADisplay dpy, VAImageFormat* format_list,
300                              int* num_formats) {
301   if (LoadVALibrary()) {
302     return vaQueryImageFormatsFn(dpy, format_list, num_formats);
303   }
304   return VA_STATUS_ERROR_UNIMPLEMENTED;
305 }
306 
vaQueryVendorString(VADisplay dpy)307 const char* vaQueryVendorString(VADisplay dpy) {
308   if (LoadVALibrary()) {
309     return vaQueryVendorStringFn(dpy);
310   }
311   return NULL;
312 }
313 
vaDestroySurfaces(VADisplay dpy,VASurfaceID * surfaces,int num_surfaces)314 VAStatus vaDestroySurfaces(VADisplay dpy, VASurfaceID* surfaces,
315                            int num_surfaces) {
316   if (LoadVALibrary()) {
317     return vaDestroySurfacesFn(dpy, surfaces, num_surfaces);
318   }
319   return VA_STATUS_ERROR_UNIMPLEMENTED;
320 }
321 
vaCreateSurfaces(VADisplay dpy,unsigned int format,unsigned int width,unsigned int height,VASurfaceID * surfaces,unsigned int num_surfaces,VASurfaceAttrib * attrib_list,unsigned int num_attribs)322 VAStatus vaCreateSurfaces(VADisplay dpy, unsigned int format,
323                           unsigned int width, unsigned int height,
324                           VASurfaceID* surfaces, unsigned int num_surfaces,
325                           VASurfaceAttrib* attrib_list,
326                           unsigned int num_attribs) {
327   if (LoadVALibrary()) {
328     return vaCreateSurfacesFn(dpy, format, width, height, surfaces,
329                               num_surfaces, attrib_list, num_attribs);
330   }
331   return VA_STATUS_ERROR_UNIMPLEMENTED;
332 }
333 
vaDeriveImage(VADisplay dpy,VASurfaceID surface,VAImage * image)334 VAStatus vaDeriveImage(VADisplay dpy, VASurfaceID surface,
335                        VAImage* image /* out */) {
336   if (LoadVALibrary()) {
337     return vaDeriveImageFn(dpy, surface, image);
338   }
339   return VA_STATUS_ERROR_UNIMPLEMENTED;
340 }
341 
vaDestroyImage(VADisplay dpy,VAImageID image)342 VAStatus vaDestroyImage(VADisplay dpy, VAImageID image) {
343   if (LoadVALibrary()) {
344     return vaDestroyImageFn(dpy, image);
345   }
346   return VA_STATUS_ERROR_UNIMPLEMENTED;
347 }
348 
vaPutImage(VADisplay dpy,VASurfaceID surface,VAImageID image,int src_x,int src_y,unsigned int src_width,unsigned int src_height,int dest_x,int dest_y,unsigned int dest_width,unsigned int dest_height)349 VAStatus vaPutImage(VADisplay dpy, VASurfaceID surface, VAImageID image,
350                     int src_x, int src_y, unsigned int src_width,
351                     unsigned int src_height, int dest_x, int dest_y,
352                     unsigned int dest_width, unsigned int dest_height) {
353   if (LoadVALibrary()) {
354     return vaPutImageFn(dpy, surface, image, src_x, src_y, src_width,
355                         src_height, dest_x, dest_y, dest_width, dest_height);
356   }
357   return VA_STATUS_ERROR_UNIMPLEMENTED;
358 }
359 
vaSyncSurface(VADisplay dpy,VASurfaceID render_target)360 VAStatus vaSyncSurface(VADisplay dpy, VASurfaceID render_target) {
361   if (LoadVALibrary()) {
362     return vaSyncSurfaceFn(dpy, render_target);
363   }
364   return VA_STATUS_ERROR_UNIMPLEMENTED;
365 }
366 
vaCreateImage(VADisplay dpy,VAImageFormat * format,int width,int height,VAImage * image)367 VAStatus vaCreateImage(VADisplay dpy, VAImageFormat* format, int width,
368                        int height, VAImage* image /* out */) {
369   if (LoadVALibrary()) {
370     return vaCreateImageFn(dpy, format, width, height, image);
371   }
372   return VA_STATUS_ERROR_UNIMPLEMENTED;
373 }
374 
vaGetImage(VADisplay dpy,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image)375 VAStatus vaGetImage(VADisplay dpy, VASurfaceID surface,
376                     int x, /* coordinates of the upper left source pixel */
377                     int y,
378                     unsigned int width, /* width and height of the region */
379                     unsigned int height, VAImageID image) {
380   if (LoadVALibrary()) {
381     return vaGetImageFn(dpy, surface, x, y, width, height, image);
382   }
383   return VA_STATUS_ERROR_UNIMPLEMENTED;
384 }
385 
vaMapBuffer(VADisplay dpy,VABufferID buf_id,void ** pbuf)386 VAStatus vaMapBuffer(VADisplay dpy, VABufferID buf_id, /* in */
387                      void** pbuf /* out */) {
388   if (LoadVALibrary()) {
389     return vaMapBufferFn(dpy, buf_id, pbuf);
390   }
391   return VA_STATUS_ERROR_UNIMPLEMENTED;
392 }
393 
vaUnmapBuffer(VADisplay dpy,VABufferID buf_id)394 VAStatus vaUnmapBuffer(VADisplay dpy, VABufferID buf_id /* in */) {
395   if (LoadVALibrary()) {
396     return vaUnmapBufferFn(dpy, buf_id);
397   }
398   return VA_STATUS_ERROR_UNIMPLEMENTED;
399 }
400 
vaTerminate(VADisplay dpy)401 VAStatus vaTerminate(VADisplay dpy) {
402   if (LoadVALibrary()) {
403     return vaTerminateFn(dpy);
404   }
405   return VA_STATUS_ERROR_UNIMPLEMENTED;
406 }
407 
vaInitialize(VADisplay dpy,int * major_version,int * minor_version)408 VAStatus vaInitialize(VADisplay dpy, int* major_version, /* out */
409                       int* minor_version /* out */) {
410   if (LoadVALibrary()) {
411     return vaInitializeFn(dpy, major_version, minor_version);
412   }
413   return VA_STATUS_ERROR_UNIMPLEMENTED;
414 }
415 
vaSetDriverName(VADisplay dpy,char * driver_name)416 VAStatus vaSetDriverName(VADisplay dpy, char* driver_name) {
417   if (LoadVALibrary()) {
418     return vaSetDriverNameFn(dpy, driver_name);
419   }
420   return VA_STATUS_ERROR_UNIMPLEMENTED;
421 }
422 
vaMaxNumEntrypoints(VADisplay dpy)423 int vaMaxNumEntrypoints(VADisplay dpy) {
424   if (LoadVALibrary()) {
425     return vaMaxNumEntrypointsFn(dpy);
426   }
427   return 0;
428 }
429 
vaQueryConfigEntrypoints(VADisplay dpy,VAProfile profile,VAEntrypoint * entrypoint_list,int * num_entrypoints)430 VAStatus vaQueryConfigEntrypoints(VADisplay dpy, VAProfile profile,
431                                   VAEntrypoint* entrypoint_list,
432                                   int* num_entrypoints) {
433   if (LoadVALibrary()) {
434     return vaQueryConfigEntrypointsFn(dpy, profile, entrypoint_list,
435                                       num_entrypoints);
436   }
437   return VA_STATUS_ERROR_UNIMPLEMENTED;
438 }
439 
vaSetErrorCallback(VADisplay dpy,VAMessageCallback callback,void * user_context)440 VAMessageCallback vaSetErrorCallback(VADisplay dpy, VAMessageCallback callback,
441                                      void* user_context) {
442   if (LoadVALibrary()) {
443     return vaSetErrorCallbackFn(dpy, callback, user_context);
444   }
445   return NULL;
446 }
447 
vaSetInfoCallback(VADisplay dpy,VAMessageCallback callback,void * user_context)448 VAMessageCallback vaSetInfoCallback(VADisplay dpy, VAMessageCallback callback,
449                                     void* user_context) {
450   if (LoadVALibrary()) {
451     return vaSetInfoCallbackFn(dpy, callback, user_context);
452   }
453   return NULL;
454 }
455 
456 #pragma GCC visibility pop
457