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