Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / media / vaapi_wrapper.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <dlfcn.h>
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "content/common/gpu/media/vaapi_wrapper.h"
10
11 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg)         \
12   do {                                                     \
13     DVLOG(1) << err_msg                                    \
14              << " VA error: " << VAAPI_ErrorStr(va_error); \
15     report_error_to_uma_cb_.Run();                         \
16   } while (0)
17
18 #define VA_LOG_ON_ERROR(va_error, err_msg)                 \
19   do {                                                     \
20     if ((va_error) != VA_STATUS_SUCCESS)                   \
21       LOG_VA_ERROR_AND_REPORT(va_error, err_msg);          \
22   } while (0)
23
24 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret)       \
25   do {                                                     \
26     if ((va_error) != VA_STATUS_SUCCESS) {                 \
27       LOG_VA_ERROR_AND_REPORT(va_error, err_msg);          \
28       return (ret);                                        \
29     }                                                      \
30   } while (0)
31
32 namespace content {
33
34 static void *vaapi_handle = NULL;
35 static void *vaapi_x11_handle = NULL;
36
37 typedef VAStatus (*VaapiBeginPicture)(VADisplay dpy,
38                                       VAContextID context,
39                                       VASurfaceID render_target);
40 typedef VAStatus (*VaapiCreateBuffer)(VADisplay dpy,
41                                       VAContextID context,
42                                       VABufferType type,
43                                       unsigned int size,
44                                       unsigned int num_elements,
45                                       void *data,
46                                       VABufferID *buf_id);
47 typedef VAStatus (*VaapiCreateConfig)(VADisplay dpy,
48                                       VAProfile profile,
49                                       VAEntrypoint entrypoint,
50                                       VAConfigAttrib *attrib_list,
51                                       int num_attribs,
52                                       VAConfigID *config_id);
53 typedef VAStatus (*VaapiCreateContext)(VADisplay dpy,
54                                        VAConfigID config_id,
55                                        int picture_width,
56                                        int picture_height,
57                                        int flag,
58                                        VASurfaceID *render_targets,
59                                        int num_render_targets,
60                                        VAContextID *context);
61 // In VAAPI version < 0.34, vaCreateSurface has 6 parameters, but in VAAPI
62 // version >= 0.34, vaCreateSurface has 8 parameters.
63 // TODO(chihchung): Remove the old path once ChromeOS updates to 1.2.1.
64 typedef void *VaapiCreateSurfaces;
65 typedef VAStatus (*VaapiCreateSurfaces6)(VADisplay dpy,
66                                          int width,
67                                          int height,
68                                          int format,
69                                          int num_surfaces,
70                                          VASurfaceID *surfaces);
71 typedef VAStatus (*VaapiCreateSurfaces8)(VADisplay dpy,
72                                          unsigned int format,
73                                          unsigned int width,
74                                          unsigned int height,
75                                          VASurfaceID *surfaces,
76                                          unsigned int num_surfaces,
77                                          VASurfaceAttrib *attrib_list,
78                                          unsigned int num_attribs);
79 typedef VAStatus (*VaapiDeriveImage)(VADisplay dpy,
80                                      VASurfaceID surface,
81                                      VAImage* image);
82 typedef VAStatus (*VaapiDestroyBuffer)(VADisplay dpy, VABufferID buffer_id);
83 typedef VAStatus (*VaapiDestroyConfig)(VADisplay dpy, VAConfigID config_id);
84 typedef VAStatus (*VaapiDestroyContext)(VADisplay dpy, VAContextID context);
85 typedef VAStatus (*VaapiDestroyImage)(VADisplay dpy, VAImageID image);
86 typedef VAStatus (*VaapiDestroySurfaces)(VADisplay dpy,
87                                          VASurfaceID *surfaces,
88                                          int num_surfaces);
89 typedef int (*VaapiDisplayIsValid)(VADisplay dpy);
90 typedef VAStatus (*VaapiEndPicture)(VADisplay dpy, VAContextID context);
91 typedef const char* (*VaapiErrorStr)(VAStatus error_status);
92 typedef VAStatus (*VaapiGetConfigAttributes)(VADisplay dpy,
93                                              VAProfile profile,
94                                              VAEntrypoint entrypoint,
95                                              VAConfigAttrib *attrib_list,
96                                              int num_attribs);
97 typedef VADisplay (*VaapiGetDisplay)(Display *dpy);
98 typedef VAStatus (*VaapiInitialize)(VADisplay dpy,
99                                     int *major_version,
100                                     int *minor_version);
101 typedef VAStatus (*VaapiMapBuffer)(VADisplay dpy,
102                                    VABufferID buf_id,
103                                    void** pbuf);
104 typedef VAStatus (*VaapiPutSurface)(VADisplay dpy,
105                                     VASurfaceID surface,
106                                     Drawable draw,
107                                     short srcx,
108                                     short srcy,
109                                     unsigned short srcw,
110                                     unsigned short srch,
111                                     short destx,
112                                     short desty,
113                                     unsigned short destw,
114                                     unsigned short desth,
115                                     VARectangle *cliprects,
116                                     unsigned int number_cliprects,
117                                     unsigned int flags);
118 typedef VAStatus (*VaapiRenderPicture)(VADisplay dpy,
119                                        VAContextID context,
120                                        VABufferID *buffers,
121                                        int num_buffers);
122 typedef VAStatus (*VaapiSetDisplayAttributes)(VADisplay dpy,
123                                               VADisplayAttribute *type,
124                                               int num_attributes);
125 typedef VAStatus (*VaapiSyncSurface)(VADisplay dpy, VASurfaceID render_target);
126 typedef VAStatus (*VaapiTerminate)(VADisplay dpy);
127 typedef VAStatus (*VaapiUnmapBuffer)(VADisplay dpy, VABufferID buf_id);
128
129 #define VAAPI_SYM(name, handle) Vaapi##name VAAPI_##name = NULL
130
131 VAAPI_SYM(BeginPicture, vaapi_handle);
132 VAAPI_SYM(CreateBuffer, vaapi_handle);
133 VAAPI_SYM(CreateConfig, vaapi_handle);
134 VAAPI_SYM(CreateContext, vaapi_handle);
135 VAAPI_SYM(CreateSurfaces, vaapi_handle);
136 VAAPI_SYM(DeriveImage, vaapi_handle);
137 VAAPI_SYM(DestroyBuffer, vaapi_handle);
138 VAAPI_SYM(DestroyConfig, vaapi_handle);
139 VAAPI_SYM(DestroyContext, vaapi_handle);
140 VAAPI_SYM(DestroyImage, vaapi_handle);
141 VAAPI_SYM(DestroySurfaces, vaapi_handle);
142 VAAPI_SYM(DisplayIsValid, vaapi_handle);
143 VAAPI_SYM(EndPicture, vaapi_handle);
144 VAAPI_SYM(ErrorStr, vaapi_handle);
145 VAAPI_SYM(GetConfigAttributes, vaapi_handle);
146 VAAPI_SYM(GetDisplay, vaapi_x11_handle);
147 VAAPI_SYM(Initialize, vaapi_handle);
148 VAAPI_SYM(MapBuffer, vaapi_handle);
149 VAAPI_SYM(PutSurface, vaapi_x11_handle);
150 VAAPI_SYM(RenderPicture, vaapi_handle);
151 VAAPI_SYM(SetDisplayAttributes, vaapi_handle);
152 VAAPI_SYM(SyncSurface, vaapi_x11_handle);
153 VAAPI_SYM(Terminate, vaapi_handle);
154 VAAPI_SYM(UnmapBuffer, vaapi_handle);
155
156 #undef VAAPI_SYM
157
158 // Maps Profile enum values to VaProfile values.
159 static bool ProfileToVAProfile(media::VideoCodecProfile profile,
160                                VAProfile* va_profile) {
161   switch (profile) {
162     case media::H264PROFILE_BASELINE:
163       *va_profile = VAProfileH264Baseline;
164       break;
165     case media::H264PROFILE_MAIN:
166       *va_profile = VAProfileH264Main;
167       break;
168     // TODO(posciak): See if we can/want support other variants
169     // of media::H264PROFILE_HIGH*.
170     case media::H264PROFILE_HIGH:
171       *va_profile = VAProfileH264High;
172       break;
173     default:
174       return false;
175   }
176   return true;
177 }
178
179 VASurface::VASurface(VASurfaceID va_surface_id, const ReleaseCB& release_cb)
180     : va_surface_id_(va_surface_id),
181       release_cb_(release_cb) {
182   DCHECK(!release_cb_.is_null());
183 }
184
185 VASurface::~VASurface() {
186   release_cb_.Run(va_surface_id_);
187 }
188
189 VaapiWrapper::VaapiWrapper()
190     : va_display_(NULL),
191       va_config_id_(VA_INVALID_ID),
192       va_context_id_(VA_INVALID_ID) {
193 }
194
195 VaapiWrapper::~VaapiWrapper() {
196   DestroyPendingBuffers();
197   DestroySurfaces();
198   Deinitialize();
199 }
200
201 scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
202     media::VideoCodecProfile profile,
203     Display* x_display,
204     const base::Closure& report_error_to_uma_cb) {
205   scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
206
207   if (!vaapi_wrapper->Initialize(profile, x_display, report_error_to_uma_cb))
208     vaapi_wrapper.reset();
209
210   return vaapi_wrapper.Pass();
211 }
212
213 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
214   VADisplayAttribute item = {VADisplayAttribRenderMode,
215                              1,  // At least support '_LOCAL_OVERLAY'.
216                              -1,  // The maximum possible support 'ALL'.
217                              VA_RENDER_MODE_LOCAL_GPU,
218                              VA_DISPLAY_ATTRIB_SETTABLE};
219
220   VAStatus va_res = VAAPI_SetDisplayAttributes(va_display_, &item, 1);
221   if (va_res != VA_STATUS_SUCCESS)
222     DVLOG(2) << "VAAPI_SetDisplayAttributes unsupported, ignoring by default.";
223 }
224
225 bool VaapiWrapper::Initialize(media::VideoCodecProfile profile,
226                               Display* x_display,
227                               const base::Closure& report_error_to_uma_cb) {
228   static bool vaapi_functions_initialized = PostSandboxInitialization();
229   if (!vaapi_functions_initialized) {
230     DVLOG(1) << "Failed to initialize VAAPI libs";
231     return false;
232   }
233
234   report_error_to_uma_cb_ = report_error_to_uma_cb;
235
236   base::AutoLock auto_lock(va_lock_);
237
238   VAProfile va_profile;
239   if (!ProfileToVAProfile(profile, &va_profile)) {
240     DVLOG(1) << "Unsupported profile";
241     return false;
242   }
243
244   va_display_ = VAAPI_GetDisplay(x_display);
245   if (!VAAPI_DisplayIsValid(va_display_)) {
246     DVLOG(1) << "Could not get a valid VA display";
247     return false;
248   }
249
250   VAStatus va_res;
251   va_res = VAAPI_Initialize(va_display_, &major_version_, &minor_version_);
252   VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false);
253   DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
254
255   VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0};
256
257   const VAEntrypoint kEntrypoint = VAEntrypointVLD;
258   va_res = VAAPI_GetConfigAttributes(va_display_, va_profile, kEntrypoint,
259                                      &attrib, 1);
260   VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false);
261
262   if (!(attrib.value & VA_RT_FORMAT_YUV420)) {
263     DVLOG(1) << "YUV420 not supported by this VAAPI implementation";
264     return false;
265   }
266
267   TryToSetVADisplayAttributeToLocalGPU();
268
269   va_res = VAAPI_CreateConfig(va_display_, va_profile, kEntrypoint,
270                               &attrib, 1, &va_config_id_);
271   VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false);
272
273   return true;
274 }
275
276 void VaapiWrapper::Deinitialize() {
277   base::AutoLock auto_lock(va_lock_);
278
279   if (va_config_id_ != VA_INVALID_ID) {
280     VAStatus va_res = VAAPI_DestroyConfig(va_display_, va_config_id_);
281     VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed");
282   }
283
284   if (va_display_) {
285     VAStatus va_res = VAAPI_Terminate(va_display_);
286     VA_LOG_ON_ERROR(va_res, "vaTerminate failed");
287   }
288
289   va_config_id_ = VA_INVALID_ID;
290   va_display_ = NULL;
291 }
292
293 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) {
294   return (major_version_ < major) ||
295       (major_version_ == major && minor_version_ < minor);
296 }
297
298 bool VaapiWrapper::CreateSurfaces(gfx::Size size,
299                                   size_t num_surfaces,
300                                    std::vector<VASurfaceID>* va_surfaces) {
301   base::AutoLock auto_lock(va_lock_);
302   DVLOG(2) << "Creating " << num_surfaces << " surfaces";
303
304   DCHECK(va_surfaces->empty());
305   DCHECK(va_surface_ids_.empty());
306   va_surface_ids_.resize(num_surfaces);
307
308   // Allocate surfaces in driver.
309   VAStatus va_res;
310   if (VAAPIVersionLessThan(0, 34)) {
311     va_res = reinterpret_cast<VaapiCreateSurfaces6>(VAAPI_CreateSurfaces)(
312         va_display_,
313         size.width(), size.height(),
314         VA_RT_FORMAT_YUV420,
315         va_surface_ids_.size(),
316         &va_surface_ids_[0]);
317   } else {
318     va_res = reinterpret_cast<VaapiCreateSurfaces8>(VAAPI_CreateSurfaces)(
319         va_display_,
320         VA_RT_FORMAT_YUV420,
321         size.width(), size.height(),
322         &va_surface_ids_[0],
323         va_surface_ids_.size(),
324         NULL, 0);
325   }
326
327   VA_LOG_ON_ERROR(va_res, "vaCreateSurfaces failed");
328   if (va_res != VA_STATUS_SUCCESS) {
329     va_surface_ids_.clear();
330     return false;
331   }
332
333   // And create a context associated with them.
334   va_res = VAAPI_CreateContext(va_display_, va_config_id_,
335                                size.width(), size.height(), VA_PROGRESSIVE,
336                                &va_surface_ids_[0], va_surface_ids_.size(),
337                                &va_context_id_);
338
339   VA_LOG_ON_ERROR(va_res, "vaCreateContext failed");
340   if (va_res != VA_STATUS_SUCCESS) {
341     DestroySurfaces();
342     return false;
343   }
344
345   *va_surfaces = va_surface_ids_;
346   return true;
347 }
348
349 void VaapiWrapper::DestroySurfaces() {
350   base::AutoLock auto_lock(va_lock_);
351   DVLOG(2) << "Destroying " << va_surface_ids_.size()  << " surfaces";
352
353   if (va_context_id_ != VA_INVALID_ID) {
354     VAStatus va_res = VAAPI_DestroyContext(va_display_, va_context_id_);
355     VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed");
356   }
357
358   if (!va_surface_ids_.empty()) {
359     VAStatus va_res = VAAPI_DestroySurfaces(va_display_, &va_surface_ids_[0],
360                                             va_surface_ids_.size());
361     VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed");
362   }
363
364   va_surface_ids_.clear();
365   va_context_id_ = VA_INVALID_ID;
366 }
367
368 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
369                                 size_t size,
370                                 void* buffer) {
371   base::AutoLock auto_lock(va_lock_);
372
373   VABufferID buffer_id;
374   VAStatus va_res = VAAPI_CreateBuffer(va_display_, va_context_id_,
375                                        va_buffer_type, size,
376                                        1, buffer, &buffer_id);
377   VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
378
379   switch (va_buffer_type) {
380     case VASliceParameterBufferType:
381     case VASliceDataBufferType:
382       pending_slice_bufs_.push_back(buffer_id);
383       break;
384
385     default:
386       pending_va_bufs_.push_back(buffer_id);
387       break;
388   }
389
390   return true;
391 }
392
393 void VaapiWrapper::DestroyPendingBuffers() {
394   base::AutoLock auto_lock(va_lock_);
395
396   for (size_t i = 0; i < pending_va_bufs_.size(); ++i) {
397     VAStatus va_res = VAAPI_DestroyBuffer(va_display_, pending_va_bufs_[i]);
398     VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
399   }
400
401   for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) {
402     VAStatus va_res = VAAPI_DestroyBuffer(va_display_, pending_slice_bufs_[i]);
403     VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
404   }
405
406   pending_va_bufs_.clear();
407   pending_slice_bufs_.clear();
408 }
409
410 bool VaapiWrapper::SubmitDecode(VASurfaceID va_surface_id) {
411   base::AutoLock auto_lock(va_lock_);
412
413   DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size();
414   DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size();
415   DVLOG(4) << "Decoding into VA surface " << va_surface_id;
416
417   // Get ready to decode into surface.
418   VAStatus va_res = VAAPI_BeginPicture(va_display_, va_context_id_,
419                                        va_surface_id);
420   VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false);
421
422   // Commit parameter and slice buffers.
423   va_res = VAAPI_RenderPicture(va_display_, va_context_id_,
424                                &pending_va_bufs_[0], pending_va_bufs_.size());
425   VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false);
426
427   va_res = VAAPI_RenderPicture(va_display_, va_context_id_,
428                                &pending_slice_bufs_[0],
429                                pending_slice_bufs_.size());
430   VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false);
431
432   // Instruct HW decoder to start processing committed buffers (decode this
433   // picture). This does not block until the end of decode.
434   va_res = VAAPI_EndPicture(va_display_, va_context_id_);
435   VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false);
436
437   return true;
438 }
439
440 bool VaapiWrapper::DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
441   bool result = SubmitDecode(va_surface_id);
442   DestroyPendingBuffers();
443   return result;
444 }
445
446 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
447                                         Pixmap x_pixmap,
448                                         gfx::Size dest_size) {
449   base::AutoLock auto_lock(va_lock_);
450
451   VAStatus va_res = VAAPI_SyncSurface(va_display_, va_surface_id);
452   VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
453
454   // Put the data into an X Pixmap.
455   va_res = VAAPI_PutSurface(va_display_,
456                             va_surface_id,
457                             x_pixmap,
458                             0, 0, dest_size.width(), dest_size.height(),
459                             0, 0, dest_size.width(), dest_size.height(),
460                             NULL, 0, 0);
461   VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap",
462                        false);
463   return true;
464 }
465
466 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id,
467                                         VAImage* image,
468                                         void** mem) {
469   base::AutoLock auto_lock(va_lock_);
470
471   VAStatus va_res = VAAPI_SyncSurface(va_display_, va_surface_id);
472   VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
473
474   // Derive a VAImage from the VASurface
475   va_res = VAAPI_DeriveImage(va_display_, va_surface_id, image);
476   VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed");
477   if (va_res != VA_STATUS_SUCCESS)
478     return false;
479
480   // Map the VAImage into memory
481   va_res = VAAPI_MapBuffer(va_display_, image->buf, mem);
482   VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
483   if (va_res == VA_STATUS_SUCCESS)
484     return true;
485
486   VAAPI_DestroyImage(va_display_, image->image_id);
487   return false;
488 }
489
490 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) {
491   base::AutoLock auto_lock(va_lock_);
492
493   VAAPI_UnmapBuffer(va_display_, image->buf);
494   VAAPI_DestroyImage(va_display_, image->image_id);
495 }
496
497 // static
498 bool VaapiWrapper::PostSandboxInitialization() {
499   vaapi_handle = dlopen("libva.so.1", RTLD_NOW);
500   vaapi_x11_handle = dlopen("libva-x11.so.1", RTLD_NOW);
501
502   if (!vaapi_handle || !vaapi_x11_handle)
503     return false;
504 #define VAAPI_DLSYM_OR_RETURN_ON_ERROR(name, handle)                          \
505   do {                                                                        \
506     VAAPI_##name = reinterpret_cast<Vaapi##name>(dlsym((handle), "va"#name)); \
507     if (VAAPI_##name == NULL) {                                               \
508       DVLOG(1) << "Failed to dlsym va"#name;                                  \
509       return false;                                                           \
510     }                                                                         \
511   } while (0)
512
513   VAAPI_DLSYM_OR_RETURN_ON_ERROR(BeginPicture, vaapi_handle);
514   VAAPI_DLSYM_OR_RETURN_ON_ERROR(CreateBuffer, vaapi_handle);
515   VAAPI_DLSYM_OR_RETURN_ON_ERROR(CreateConfig, vaapi_handle);
516   VAAPI_DLSYM_OR_RETURN_ON_ERROR(CreateContext, vaapi_handle);
517   VAAPI_DLSYM_OR_RETURN_ON_ERROR(CreateSurfaces, vaapi_handle);
518   VAAPI_DLSYM_OR_RETURN_ON_ERROR(DeriveImage, vaapi_handle);
519   VAAPI_DLSYM_OR_RETURN_ON_ERROR(DestroyBuffer, vaapi_handle);
520   VAAPI_DLSYM_OR_RETURN_ON_ERROR(DestroyConfig, vaapi_handle);
521   VAAPI_DLSYM_OR_RETURN_ON_ERROR(DestroyContext, vaapi_handle);
522   VAAPI_DLSYM_OR_RETURN_ON_ERROR(DestroyImage, vaapi_handle);
523   VAAPI_DLSYM_OR_RETURN_ON_ERROR(DestroySurfaces, vaapi_handle);
524   VAAPI_DLSYM_OR_RETURN_ON_ERROR(DisplayIsValid, vaapi_handle);
525   VAAPI_DLSYM_OR_RETURN_ON_ERROR(EndPicture, vaapi_handle);
526   VAAPI_DLSYM_OR_RETURN_ON_ERROR(ErrorStr, vaapi_handle);
527   VAAPI_DLSYM_OR_RETURN_ON_ERROR(GetConfigAttributes, vaapi_handle);
528   VAAPI_DLSYM_OR_RETURN_ON_ERROR(GetDisplay, vaapi_x11_handle);
529   VAAPI_DLSYM_OR_RETURN_ON_ERROR(Initialize, vaapi_handle);
530   VAAPI_DLSYM_OR_RETURN_ON_ERROR(MapBuffer, vaapi_handle);
531   VAAPI_DLSYM_OR_RETURN_ON_ERROR(PutSurface, vaapi_x11_handle);
532   VAAPI_DLSYM_OR_RETURN_ON_ERROR(RenderPicture, vaapi_handle);
533   VAAPI_DLSYM_OR_RETURN_ON_ERROR(SetDisplayAttributes, vaapi_handle);
534   VAAPI_DLSYM_OR_RETURN_ON_ERROR(SyncSurface, vaapi_handle);
535   VAAPI_DLSYM_OR_RETURN_ON_ERROR(Terminate, vaapi_handle);
536   VAAPI_DLSYM_OR_RETURN_ON_ERROR(UnmapBuffer, vaapi_handle);
537 #undef VAAPI_DLSYM
538
539   return true;
540 }
541
542 }  // namespace content