| 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 "content/common/gpu/media/vaapi_wrapper.h" | 11 #include "common/gpu/media/va_stubs.h" |
| 12 |
| 13 using common_gpu_media::kModuleVa; |
| 14 using common_gpu_media::InitializeStubs; |
| 15 using common_gpu_media::StubPathMap; |
| 16 |
| 17 // libva-x11 depend on libva, so dlopen libva-x11 is enough |
| 18 static const base::FilePath::CharType kVaLib[] = |
| 19 FILE_PATH_LITERAL("libva-x11.so.1"); |
| 10 | 20 |
| 11 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ | 21 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ |
| 12 do { \ | 22 do { \ |
| 13 DVLOG(1) << err_msg \ | 23 DVLOG(1) << err_msg \ |
| 14 << " VA error: " << VAAPI_ErrorStr(va_error); \ | 24 << " VA error: " << vaErrorStr(va_error); \ |
| 15 report_error_to_uma_cb_.Run(); \ | 25 report_error_to_uma_cb_.Run(); \ |
| 16 } while (0) | 26 } while (0) |
| 17 | 27 |
| 18 #define VA_LOG_ON_ERROR(va_error, err_msg) \ | 28 #define VA_LOG_ON_ERROR(va_error, err_msg) \ |
| 19 do { \ | 29 do { \ |
| 20 if ((va_error) != VA_STATUS_SUCCESS) \ | 30 if ((va_error) != VA_STATUS_SUCCESS) \ |
| 21 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ | 31 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ |
| 22 } while (0) | 32 } while (0) |
| 23 | 33 |
| 24 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ | 34 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ |
| 25 do { \ | 35 do { \ |
| 26 if ((va_error) != VA_STATUS_SUCCESS) { \ | 36 if ((va_error) != VA_STATUS_SUCCESS) { \ |
| 27 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ | 37 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ |
| 28 return (ret); \ | 38 return (ret); \ |
| 29 } \ | 39 } \ |
| 30 } while (0) | 40 } while (0) |
| 31 | 41 |
| 32 namespace content { | 42 namespace content { |
| 33 | 43 |
| 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. | 44 // Maps Profile enum values to VaProfile values. |
| 159 static bool ProfileToVAProfile(media::VideoCodecProfile profile, | 45 static bool ProfileToVAProfile(media::VideoCodecProfile profile, |
| 160 VAProfile* va_profile) { | 46 VAProfile* va_profile) { |
| 161 switch (profile) { | 47 switch (profile) { |
| 162 case media::H264PROFILE_BASELINE: | 48 case media::H264PROFILE_BASELINE: |
| 163 *va_profile = VAProfileH264Baseline; | 49 *va_profile = VAProfileH264Baseline; |
| 164 break; | 50 break; |
| 165 case media::H264PROFILE_MAIN: | 51 case media::H264PROFILE_MAIN: |
| 166 *va_profile = VAProfileH264Main; | 52 *va_profile = VAProfileH264Main; |
| 167 break; | 53 break; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 return vaapi_wrapper.Pass(); | 96 return vaapi_wrapper.Pass(); |
| 211 } | 97 } |
| 212 | 98 |
| 213 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 99 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
| 214 VADisplayAttribute item = {VADisplayAttribRenderMode, | 100 VADisplayAttribute item = {VADisplayAttribRenderMode, |
| 215 1, // At least support '_LOCAL_OVERLAY'. | 101 1, // At least support '_LOCAL_OVERLAY'. |
| 216 -1, // The maximum possible support 'ALL'. | 102 -1, // The maximum possible support 'ALL'. |
| 217 VA_RENDER_MODE_LOCAL_GPU, | 103 VA_RENDER_MODE_LOCAL_GPU, |
| 218 VA_DISPLAY_ATTRIB_SETTABLE}; | 104 VA_DISPLAY_ATTRIB_SETTABLE}; |
| 219 | 105 |
| 220 VAStatus va_res = VAAPI_SetDisplayAttributes(va_display_, &item, 1); | 106 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
| 221 if (va_res != VA_STATUS_SUCCESS) | 107 if (va_res != VA_STATUS_SUCCESS) |
| 222 DVLOG(2) << "VAAPI_SetDisplayAttributes unsupported, ignoring by default."; | 108 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
| 223 } | 109 } |
| 224 | 110 |
| 225 bool VaapiWrapper::Initialize(media::VideoCodecProfile profile, | 111 bool VaapiWrapper::Initialize(media::VideoCodecProfile profile, |
| 226 Display* x_display, | 112 Display* x_display, |
| 227 const base::Closure& report_error_to_uma_cb) { | 113 const base::Closure& report_error_to_uma_cb) { |
| 228 static bool vaapi_functions_initialized = PostSandboxInitialization(); | 114 static bool vaapi_functions_initialized = PostSandboxInitialization(); |
| 229 if (!vaapi_functions_initialized) { | 115 if (!vaapi_functions_initialized) { |
| 230 DVLOG(1) << "Failed to initialize VAAPI libs"; | 116 DVLOG(1) << "Failed to initialize VAAPI libs"; |
| 231 return false; | 117 return false; |
| 232 } | 118 } |
| 233 | 119 |
| 234 report_error_to_uma_cb_ = report_error_to_uma_cb; | 120 report_error_to_uma_cb_ = report_error_to_uma_cb; |
| 235 | 121 |
| 236 base::AutoLock auto_lock(va_lock_); | 122 base::AutoLock auto_lock(va_lock_); |
| 237 | 123 |
| 238 VAProfile va_profile; | 124 VAProfile va_profile; |
| 239 if (!ProfileToVAProfile(profile, &va_profile)) { | 125 if (!ProfileToVAProfile(profile, &va_profile)) { |
| 240 DVLOG(1) << "Unsupported profile"; | 126 DVLOG(1) << "Unsupported profile"; |
| 241 return false; | 127 return false; |
| 242 } | 128 } |
| 243 | 129 |
| 244 va_display_ = VAAPI_GetDisplay(x_display); | 130 va_display_ = vaGetDisplay(x_display); |
| 245 if (!VAAPI_DisplayIsValid(va_display_)) { | 131 if (!vaDisplayIsValid(va_display_)) { |
| 246 DVLOG(1) << "Could not get a valid VA display"; | 132 DVLOG(1) << "Could not get a valid VA display"; |
| 247 return false; | 133 return false; |
| 248 } | 134 } |
| 249 | 135 |
| 250 VAStatus va_res; | 136 VAStatus va_res; |
| 251 va_res = VAAPI_Initialize(va_display_, &major_version_, &minor_version_); | 137 va_res = vaInitialize(va_display_, &major_version_, &minor_version_); |
| 252 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 138 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); |
| 253 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | 139 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
| 254 | 140 |
| 141 if (VAAPIVersionLessThan(0, 34)) { |
| 142 DVLOG(1) << "VAAPI version < 0.34 is not supported."; |
| 143 return false; |
| 144 } |
| 145 |
| 255 VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0}; | 146 VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0}; |
| 256 | 147 |
| 257 const VAEntrypoint kEntrypoint = VAEntrypointVLD; | 148 const VAEntrypoint kEntrypoint = VAEntrypointVLD; |
| 258 va_res = VAAPI_GetConfigAttributes(va_display_, va_profile, kEntrypoint, | 149 va_res = vaGetConfigAttributes(va_display_, va_profile, kEntrypoint, |
| 259 &attrib, 1); | 150 &attrib, 1); |
| 260 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); | 151 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); |
| 261 | 152 |
| 262 if (!(attrib.value & VA_RT_FORMAT_YUV420)) { | 153 if (!(attrib.value & VA_RT_FORMAT_YUV420)) { |
| 263 DVLOG(1) << "YUV420 not supported by this VAAPI implementation"; | 154 DVLOG(1) << "YUV420 not supported by this VAAPI implementation"; |
| 264 return false; | 155 return false; |
| 265 } | 156 } |
| 266 | 157 |
| 267 TryToSetVADisplayAttributeToLocalGPU(); | 158 TryToSetVADisplayAttributeToLocalGPU(); |
| 268 | 159 |
| 269 va_res = VAAPI_CreateConfig(va_display_, va_profile, kEntrypoint, | 160 va_res = vaCreateConfig(va_display_, va_profile, kEntrypoint, |
| 270 &attrib, 1, &va_config_id_); | 161 &attrib, 1, &va_config_id_); |
| 271 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | 162 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); |
| 272 | 163 |
| 273 return true; | 164 return true; |
| 274 } | 165 } |
| 275 | 166 |
| 276 void VaapiWrapper::Deinitialize() { | 167 void VaapiWrapper::Deinitialize() { |
| 277 base::AutoLock auto_lock(va_lock_); | 168 base::AutoLock auto_lock(va_lock_); |
| 278 | 169 |
| 279 if (va_config_id_ != VA_INVALID_ID) { | 170 if (va_config_id_ != VA_INVALID_ID) { |
| 280 VAStatus va_res = VAAPI_DestroyConfig(va_display_, va_config_id_); | 171 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); |
| 281 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); | 172 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); |
| 282 } | 173 } |
| 283 | 174 |
| 284 if (va_display_) { | 175 if (va_display_) { |
| 285 VAStatus va_res = VAAPI_Terminate(va_display_); | 176 VAStatus va_res = vaTerminate(va_display_); |
| 286 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); | 177 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); |
| 287 } | 178 } |
| 288 | 179 |
| 289 va_config_id_ = VA_INVALID_ID; | 180 va_config_id_ = VA_INVALID_ID; |
| 290 va_display_ = NULL; | 181 va_display_ = NULL; |
| 291 } | 182 } |
| 292 | 183 |
| 293 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { | 184 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { |
| 294 return (major_version_ < major) || | 185 return (major_version_ < major) || |
| 295 (major_version_ == major && minor_version_ < minor); | 186 (major_version_ == major && minor_version_ < minor); |
| 296 } | 187 } |
| 297 | 188 |
| 298 bool VaapiWrapper::CreateSurfaces(gfx::Size size, | 189 bool VaapiWrapper::CreateSurfaces(gfx::Size size, |
| 299 size_t num_surfaces, | 190 size_t num_surfaces, |
| 300 std::vector<VASurfaceID>* va_surfaces) { | 191 std::vector<VASurfaceID>* va_surfaces) { |
| 301 base::AutoLock auto_lock(va_lock_); | 192 base::AutoLock auto_lock(va_lock_); |
| 302 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; | 193 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; |
| 303 | 194 |
| 304 DCHECK(va_surfaces->empty()); | 195 DCHECK(va_surfaces->empty()); |
| 305 DCHECK(va_surface_ids_.empty()); | 196 DCHECK(va_surface_ids_.empty()); |
| 306 va_surface_ids_.resize(num_surfaces); | 197 va_surface_ids_.resize(num_surfaces); |
| 307 | 198 |
| 308 // Allocate surfaces in driver. | 199 // Allocate surfaces in driver. |
| 309 VAStatus va_res; | 200 VAStatus va_res = vaCreateSurfaces(va_display_, |
| 310 if (VAAPIVersionLessThan(0, 34)) { | 201 VA_RT_FORMAT_YUV420, |
| 311 va_res = reinterpret_cast<VaapiCreateSurfaces6>(VAAPI_CreateSurfaces)( | 202 size.width(), size.height(), |
| 312 va_display_, | 203 &va_surface_ids_[0], |
| 313 size.width(), size.height(), | 204 va_surface_ids_.size(), |
| 314 VA_RT_FORMAT_YUV420, | 205 NULL, 0); |
| 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 | 206 |
| 327 VA_LOG_ON_ERROR(va_res, "vaCreateSurfaces failed"); | 207 VA_LOG_ON_ERROR(va_res, "vaCreateSurfaces failed"); |
| 328 if (va_res != VA_STATUS_SUCCESS) { | 208 if (va_res != VA_STATUS_SUCCESS) { |
| 329 va_surface_ids_.clear(); | 209 va_surface_ids_.clear(); |
| 330 return false; | 210 return false; |
| 331 } | 211 } |
| 332 | 212 |
| 333 // And create a context associated with them. | 213 // And create a context associated with them. |
| 334 va_res = VAAPI_CreateContext(va_display_, va_config_id_, | 214 va_res = vaCreateContext(va_display_, va_config_id_, |
| 335 size.width(), size.height(), VA_PROGRESSIVE, | 215 size.width(), size.height(), VA_PROGRESSIVE, |
| 336 &va_surface_ids_[0], va_surface_ids_.size(), | 216 &va_surface_ids_[0], va_surface_ids_.size(), |
| 337 &va_context_id_); | 217 &va_context_id_); |
| 338 | 218 |
| 339 VA_LOG_ON_ERROR(va_res, "vaCreateContext failed"); | 219 VA_LOG_ON_ERROR(va_res, "vaCreateContext failed"); |
| 340 if (va_res != VA_STATUS_SUCCESS) { | 220 if (va_res != VA_STATUS_SUCCESS) { |
| 341 DestroySurfaces(); | 221 DestroySurfaces(); |
| 342 return false; | 222 return false; |
| 343 } | 223 } |
| 344 | 224 |
| 345 *va_surfaces = va_surface_ids_; | 225 *va_surfaces = va_surface_ids_; |
| 346 return true; | 226 return true; |
| 347 } | 227 } |
| 348 | 228 |
| 349 void VaapiWrapper::DestroySurfaces() { | 229 void VaapiWrapper::DestroySurfaces() { |
| 350 base::AutoLock auto_lock(va_lock_); | 230 base::AutoLock auto_lock(va_lock_); |
| 351 DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; | 231 DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; |
| 352 | 232 |
| 353 if (va_context_id_ != VA_INVALID_ID) { | 233 if (va_context_id_ != VA_INVALID_ID) { |
| 354 VAStatus va_res = VAAPI_DestroyContext(va_display_, va_context_id_); | 234 VAStatus va_res = vaDestroyContext(va_display_, va_context_id_); |
| 355 VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed"); | 235 VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed"); |
| 356 } | 236 } |
| 357 | 237 |
| 358 if (!va_surface_ids_.empty()) { | 238 if (!va_surface_ids_.empty()) { |
| 359 VAStatus va_res = VAAPI_DestroySurfaces(va_display_, &va_surface_ids_[0], | 239 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_ids_[0], |
| 360 va_surface_ids_.size()); | 240 va_surface_ids_.size()); |
| 361 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); | 241 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); |
| 362 } | 242 } |
| 363 | 243 |
| 364 va_surface_ids_.clear(); | 244 va_surface_ids_.clear(); |
| 365 va_context_id_ = VA_INVALID_ID; | 245 va_context_id_ = VA_INVALID_ID; |
| 366 } | 246 } |
| 367 | 247 |
| 368 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, | 248 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, |
| 369 size_t size, | 249 size_t size, |
| 370 void* buffer) { | 250 void* buffer) { |
| 371 base::AutoLock auto_lock(va_lock_); | 251 base::AutoLock auto_lock(va_lock_); |
| 372 | 252 |
| 373 VABufferID buffer_id; | 253 VABufferID buffer_id; |
| 374 VAStatus va_res = VAAPI_CreateBuffer(va_display_, va_context_id_, | 254 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, |
| 375 va_buffer_type, size, | 255 va_buffer_type, size, |
| 376 1, buffer, &buffer_id); | 256 1, buffer, &buffer_id); |
| 377 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); | 257 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); |
| 378 | 258 |
| 379 switch (va_buffer_type) { | 259 switch (va_buffer_type) { |
| 380 case VASliceParameterBufferType: | 260 case VASliceParameterBufferType: |
| 381 case VASliceDataBufferType: | 261 case VASliceDataBufferType: |
| 382 pending_slice_bufs_.push_back(buffer_id); | 262 pending_slice_bufs_.push_back(buffer_id); |
| 383 break; | 263 break; |
| 384 | 264 |
| 385 default: | 265 default: |
| 386 pending_va_bufs_.push_back(buffer_id); | 266 pending_va_bufs_.push_back(buffer_id); |
| 387 break; | 267 break; |
| 388 } | 268 } |
| 389 | 269 |
| 390 return true; | 270 return true; |
| 391 } | 271 } |
| 392 | 272 |
| 393 void VaapiWrapper::DestroyPendingBuffers() { | 273 void VaapiWrapper::DestroyPendingBuffers() { |
| 394 base::AutoLock auto_lock(va_lock_); | 274 base::AutoLock auto_lock(va_lock_); |
| 395 | 275 |
| 396 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) { | 276 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) { |
| 397 VAStatus va_res = VAAPI_DestroyBuffer(va_display_, pending_va_bufs_[i]); | 277 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]); |
| 398 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 278 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
| 399 } | 279 } |
| 400 | 280 |
| 401 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) { | 281 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) { |
| 402 VAStatus va_res = VAAPI_DestroyBuffer(va_display_, pending_slice_bufs_[i]); | 282 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]); |
| 403 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 283 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
| 404 } | 284 } |
| 405 | 285 |
| 406 pending_va_bufs_.clear(); | 286 pending_va_bufs_.clear(); |
| 407 pending_slice_bufs_.clear(); | 287 pending_slice_bufs_.clear(); |
| 408 } | 288 } |
| 409 | 289 |
| 410 bool VaapiWrapper::SubmitDecode(VASurfaceID va_surface_id) { | 290 bool VaapiWrapper::SubmitDecode(VASurfaceID va_surface_id) { |
| 411 base::AutoLock auto_lock(va_lock_); | 291 base::AutoLock auto_lock(va_lock_); |
| 412 | 292 |
| 413 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); | 293 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); |
| 414 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); | 294 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); |
| 415 DVLOG(4) << "Decoding into VA surface " << va_surface_id; | 295 DVLOG(4) << "Decoding into VA surface " << va_surface_id; |
| 416 | 296 |
| 417 // Get ready to decode into surface. | 297 // Get ready to decode into surface. |
| 418 VAStatus va_res = VAAPI_BeginPicture(va_display_, va_context_id_, | 298 VAStatus va_res = vaBeginPicture(va_display_, va_context_id_, |
| 419 va_surface_id); | 299 va_surface_id); |
| 420 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); | 300 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); |
| 421 | 301 |
| 422 // Commit parameter and slice buffers. | 302 // Commit parameter and slice buffers. |
| 423 va_res = VAAPI_RenderPicture(va_display_, va_context_id_, | 303 va_res = vaRenderPicture(va_display_, va_context_id_, |
| 424 &pending_va_bufs_[0], pending_va_bufs_.size()); | 304 &pending_va_bufs_[0], pending_va_bufs_.size()); |
| 425 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false); | 305 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false); |
| 426 | 306 |
| 427 va_res = VAAPI_RenderPicture(va_display_, va_context_id_, | 307 va_res = vaRenderPicture(va_display_, va_context_id_, |
| 428 &pending_slice_bufs_[0], | 308 &pending_slice_bufs_[0], |
| 429 pending_slice_bufs_.size()); | 309 pending_slice_bufs_.size()); |
| 430 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false); | 310 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false); |
| 431 | 311 |
| 432 // Instruct HW decoder to start processing committed buffers (decode this | 312 // Instruct HW decoder to start processing committed buffers (decode this |
| 433 // picture). This does not block until the end of decode. | 313 // picture). This does not block until the end of decode. |
| 434 va_res = VAAPI_EndPicture(va_display_, va_context_id_); | 314 va_res = vaEndPicture(va_display_, va_context_id_); |
| 435 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false); | 315 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false); |
| 436 | 316 |
| 437 return true; | 317 return true; |
| 438 } | 318 } |
| 439 | 319 |
| 440 bool VaapiWrapper::DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id) { | 320 bool VaapiWrapper::DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id) { |
| 441 bool result = SubmitDecode(va_surface_id); | 321 bool result = SubmitDecode(va_surface_id); |
| 442 DestroyPendingBuffers(); | 322 DestroyPendingBuffers(); |
| 443 return result; | 323 return result; |
| 444 } | 324 } |
| 445 | 325 |
| 446 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, | 326 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, |
| 447 Pixmap x_pixmap, | 327 Pixmap x_pixmap, |
| 448 gfx::Size dest_size) { | 328 gfx::Size dest_size) { |
| 449 base::AutoLock auto_lock(va_lock_); | 329 base::AutoLock auto_lock(va_lock_); |
| 450 | 330 |
| 451 VAStatus va_res = VAAPI_SyncSurface(va_display_, va_surface_id); | 331 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
| 452 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 332 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
| 453 | 333 |
| 454 // Put the data into an X Pixmap. | 334 // Put the data into an X Pixmap. |
| 455 va_res = VAAPI_PutSurface(va_display_, | 335 va_res = vaPutSurface(va_display_, |
| 456 va_surface_id, | 336 va_surface_id, |
| 457 x_pixmap, | 337 x_pixmap, |
| 458 0, 0, dest_size.width(), dest_size.height(), | 338 0, 0, dest_size.width(), dest_size.height(), |
| 459 0, 0, dest_size.width(), dest_size.height(), | 339 0, 0, dest_size.width(), dest_size.height(), |
| 460 NULL, 0, 0); | 340 NULL, 0, 0); |
| 461 VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap", | 341 VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap", |
| 462 false); | 342 false); |
| 463 return true; | 343 return true; |
| 464 } | 344 } |
| 465 | 345 |
| 466 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, | 346 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, |
| 467 VAImage* image, | 347 VAImage* image, |
| 468 void** mem) { | 348 void** mem) { |
| 469 base::AutoLock auto_lock(va_lock_); | 349 base::AutoLock auto_lock(va_lock_); |
| 470 | 350 |
| 471 VAStatus va_res = VAAPI_SyncSurface(va_display_, va_surface_id); | 351 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
| 472 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 352 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
| 473 | 353 |
| 474 // Derive a VAImage from the VASurface | 354 // Derive a VAImage from the VASurface |
| 475 va_res = VAAPI_DeriveImage(va_display_, va_surface_id, image); | 355 va_res = vaDeriveImage(va_display_, va_surface_id, image); |
| 476 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); | 356 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); |
| 477 if (va_res != VA_STATUS_SUCCESS) | 357 if (va_res != VA_STATUS_SUCCESS) |
| 478 return false; | 358 return false; |
| 479 | 359 |
| 480 // Map the VAImage into memory | 360 // Map the VAImage into memory |
| 481 va_res = VAAPI_MapBuffer(va_display_, image->buf, mem); | 361 va_res = vaMapBuffer(va_display_, image->buf, mem); |
| 482 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); | 362 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); |
| 483 if (va_res == VA_STATUS_SUCCESS) | 363 if (va_res == VA_STATUS_SUCCESS) |
| 484 return true; | 364 return true; |
| 485 | 365 |
| 486 VAAPI_DestroyImage(va_display_, image->image_id); | 366 vaDestroyImage(va_display_, image->image_id); |
| 487 return false; | 367 return false; |
| 488 } | 368 } |
| 489 | 369 |
| 490 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) { | 370 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) { |
| 491 base::AutoLock auto_lock(va_lock_); | 371 base::AutoLock auto_lock(va_lock_); |
| 492 | 372 |
| 493 VAAPI_UnmapBuffer(va_display_, image->buf); | 373 vaUnmapBuffer(va_display_, image->buf); |
| 494 VAAPI_DestroyImage(va_display_, image->image_id); | 374 vaDestroyImage(va_display_, image->image_id); |
| 495 } | 375 } |
| 496 | 376 |
| 497 // static | 377 // static |
| 498 bool VaapiWrapper::PostSandboxInitialization() { | 378 bool VaapiWrapper::PostSandboxInitialization() { |
| 499 vaapi_handle = dlopen("libva.so.1", RTLD_NOW); | 379 StubPathMap paths; |
| 500 vaapi_x11_handle = dlopen("libva-x11.so.1", RTLD_NOW); | 380 paths[kModuleVa].push_back(kVaLib); |
| 501 | 381 |
| 502 if (!vaapi_handle || !vaapi_x11_handle) | 382 return InitializeStubs(paths); |
| 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 } | 383 } |
| 541 | 384 |
| 542 } // namespace content | 385 } // namespace content |
| OLD | NEW |