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" | 5 #include "content/common/gpu/media/vaapi_wrapper.h" |
6 | 6 |
7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 return (ret); \ | 55 return (ret); \ |
56 } \ | 56 } \ |
57 } while (0) | 57 } while (0) |
58 | 58 |
59 namespace content { | 59 namespace content { |
60 | 60 |
61 // Maximum framerate of encoded profile. This value is an arbitary limit | 61 // Maximum framerate of encoded profile. This value is an arbitary limit |
62 // and not taken from HW documentation. | 62 // and not taken from HW documentation. |
63 const int kMaxEncoderFramerate = 30; | 63 const int kMaxEncoderFramerate = 30; |
64 | 64 |
| 65 #if defined(USE_OZONE) |
| 66 base::LazyInstance<VaapiWrapper::VADisplayState> |
| 67 VaapiWrapper::g_va_display_state_ = LAZY_INSTANCE_INITIALIZER; |
| 68 #endif |
| 69 |
65 base::LazyInstance<VaapiWrapper::LazyProfileInfos> | 70 base::LazyInstance<VaapiWrapper::LazyProfileInfos> |
66 VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER; | 71 VaapiWrapper::profile_infos_ = LAZY_INSTANCE_INITIALIZER; |
67 | 72 |
68 // Config attributes common for both encode and decode. | 73 // Config attributes common for both encode and decode. |
69 static const VAConfigAttrib kCommonVAConfigAttribs[] = { | 74 static const VAConfigAttrib kCommonVAConfigAttribs[] = { |
70 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, | 75 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, |
71 }; | 76 }; |
72 | 77 |
73 // Attributes required for encode. | 78 // Attributes required for encode. |
74 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { | 79 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 } | 121 } |
117 | 122 |
118 VASurface::~VASurface() { | 123 VASurface::~VASurface() { |
119 release_cb_.Run(va_surface_id_); | 124 release_cb_.Run(va_surface_id_); |
120 } | 125 } |
121 | 126 |
122 VaapiWrapper::VaapiWrapper() | 127 VaapiWrapper::VaapiWrapper() |
123 : va_display_(NULL), | 128 : va_display_(NULL), |
124 va_config_id_(VA_INVALID_ID), | 129 va_config_id_(VA_INVALID_ID), |
125 va_context_id_(VA_INVALID_ID), | 130 va_context_id_(VA_INVALID_ID), |
126 va_initialized_(false), | |
127 va_vpp_config_id_(VA_INVALID_ID), | 131 va_vpp_config_id_(VA_INVALID_ID), |
128 va_vpp_context_id_(VA_INVALID_ID), | 132 va_vpp_context_id_(VA_INVALID_ID), |
129 va_vpp_buffer_id_(VA_INVALID_ID) { | 133 va_vpp_buffer_id_(VA_INVALID_ID) { |
130 } | 134 } |
131 | 135 |
132 VaapiWrapper::~VaapiWrapper() { | 136 VaapiWrapper::~VaapiWrapper() { |
133 DestroyPendingBuffers(); | 137 DestroyPendingBuffers(); |
134 DestroyCodedBuffers(); | 138 DestroyCodedBuffers(); |
135 DestroySurfaces(); | 139 DestroySurfaces(); |
136 DeinitializeVpp(); | 140 DeinitializeVpp(); |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 LOG(ERROR) << kErrorMsg; | 311 LOG(ERROR) << kErrorMsg; |
308 else | 312 else |
309 DVLOG(1) << kErrorMsg; | 313 DVLOG(1) << kErrorMsg; |
310 return false; | 314 return false; |
311 } | 315 } |
312 | 316 |
313 report_error_to_uma_cb_ = report_error_to_uma_cb; | 317 report_error_to_uma_cb_ = report_error_to_uma_cb; |
314 | 318 |
315 base::AutoLock auto_lock(va_lock_); | 319 base::AutoLock auto_lock(va_lock_); |
316 | 320 |
| 321 VADisplayState* va_display_state = nullptr; |
| 322 |
317 #if defined(USE_X11) | 323 #if defined(USE_X11) |
318 va_display_ = vaGetDisplay(gfx::GetXDisplay()); | 324 va_display_state = new VADisplayState(); |
| 325 va_display_state_.reset(va_display_state); |
319 #elif defined(USE_OZONE) | 326 #elif defined(USE_OZONE) |
320 const char* kDriRenderNode0Path = "/dev/dri/renderD128"; | 327 va_display_state = &g_va_display_state_.Get(); |
321 drm_file_ = base::File(base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path), | |
322 base::File::FLAG_OPEN | base::File::FLAG_READ | | |
323 base::File::FLAG_WRITE); | |
324 va_display_ = vaGetDisplayDRM(drm_file_.GetPlatformFile()); | |
325 #endif // USE_X11 | 328 #endif // USE_X11 |
326 | 329 |
327 if (!vaDisplayIsValid(va_display_)) { | 330 if (!va_display_state) { |
328 LOG(ERROR) << "Could not get a valid VA display"; | 331 LOG(ERROR) << "Could not allocate VA display state"; |
329 return false; | 332 return false; |
330 } | 333 } |
331 | 334 |
332 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 335 VAStatus va_res = VA_STATUS_SUCCESS; |
333 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 336 if (!va_display_state->Initialize(&va_res)) { |
334 va_initialized_ = true; | 337 VA_LOG_ON_ERROR(va_res, "vaInitialize failed"); |
335 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | |
336 | |
337 if (VAAPIVersionLessThan(0, 34)) { | |
338 LOG(ERROR) << "VAAPI version < 0.34 is not supported."; | |
339 return false; | 338 return false; |
340 } | 339 } |
| 340 |
| 341 va_display_ = va_display_state->GetVADisplay(); |
341 return true; | 342 return true; |
342 } | 343 } |
343 | 344 |
344 bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { | 345 bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) { |
345 base::AutoLock auto_lock(va_lock_); | 346 base::AutoLock auto_lock(va_lock_); |
346 // Query the driver for supported profiles. | 347 // Query the driver for supported profiles. |
347 int max_profiles = vaMaxNumProfiles(va_display_); | 348 int max_profiles = vaMaxNumProfiles(va_display_); |
348 std::vector<VAProfile> supported_profiles( | 349 std::vector<VAProfile> supported_profiles( |
349 base::checked_cast<size_t>(max_profiles)); | 350 base::checked_cast<size_t>(max_profiles)); |
350 | 351 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 } | 486 } |
486 | 487 |
487 void VaapiWrapper::Deinitialize() { | 488 void VaapiWrapper::Deinitialize() { |
488 base::AutoLock auto_lock(va_lock_); | 489 base::AutoLock auto_lock(va_lock_); |
489 | 490 |
490 if (va_config_id_ != VA_INVALID_ID) { | 491 if (va_config_id_ != VA_INVALID_ID) { |
491 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); | 492 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); |
492 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); | 493 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); |
493 } | 494 } |
494 | 495 |
495 // Must check if vaInitialize completed successfully, to work around a bug in | 496 VADisplayState* va_display_state = nullptr; |
496 // libva. The bug was fixed upstream: | 497 |
497 // http://lists.freedesktop.org/archives/libva/2013-July/001807.html | 498 #if defined(USE_X11) |
498 // TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once | 499 va_display_state = va_display_state_.get(); |
499 // the fix has rolled out sufficiently. | 500 #elif defined(USE_OZONE) |
500 if (va_initialized_ && va_display_) { | 501 va_display_state = &g_va_display_state_.Get(); |
501 VAStatus va_res = vaTerminate(va_display_); | 502 #endif // USE_X11 |
| 503 |
| 504 if (va_display_state) { |
| 505 VAStatus va_res = VA_STATUS_SUCCESS; |
| 506 va_display_state->Deinitialize(&va_res); |
502 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); | 507 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); |
503 } | 508 } |
504 | 509 |
505 va_config_id_ = VA_INVALID_ID; | 510 va_config_id_ = VA_INVALID_ID; |
506 va_display_ = NULL; | 511 va_display_ = NULL; |
507 va_initialized_ = false; | |
508 } | |
509 | |
510 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { | |
511 return (major_version_ < major) || | |
512 (major_version_ == major && minor_version_ < minor); | |
513 } | 512 } |
514 | 513 |
515 bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, | 514 bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, |
516 size_t num_surfaces, | 515 size_t num_surfaces, |
517 std::vector<VASurfaceID>* va_surfaces) { | 516 std::vector<VASurfaceID>* va_surfaces) { |
518 base::AutoLock auto_lock(va_lock_); | 517 base::AutoLock auto_lock(va_lock_); |
519 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; | 518 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; |
520 | 519 |
521 DCHECK(va_surfaces->empty()); | 520 DCHECK(va_surfaces->empty()); |
522 DCHECK(va_surface_ids_.empty()); | 521 DCHECK(va_surface_ids_.empty()); |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 vaDestroyContext(va_display_, va_vpp_context_id_); | 1034 vaDestroyContext(va_display_, va_vpp_context_id_); |
1036 va_vpp_context_id_ = VA_INVALID_ID; | 1035 va_vpp_context_id_ = VA_INVALID_ID; |
1037 } | 1036 } |
1038 if (va_vpp_config_id_ != VA_INVALID_ID) { | 1037 if (va_vpp_config_id_ != VA_INVALID_ID) { |
1039 vaDestroyConfig(va_display_, va_vpp_config_id_); | 1038 vaDestroyConfig(va_display_, va_vpp_config_id_); |
1040 va_vpp_config_id_ = VA_INVALID_ID; | 1039 va_vpp_config_id_ = VA_INVALID_ID; |
1041 } | 1040 } |
1042 } | 1041 } |
1043 | 1042 |
1044 // static | 1043 // static |
| 1044 void VaapiWrapper::PreSandboxInitialization() { |
| 1045 #if defined(USE_OZONE) |
| 1046 const char* kDriRenderNode0Path = "/dev/dri/renderD128"; |
| 1047 base::File drm_file = base::File( |
| 1048 base::FilePath::FromUTF8Unsafe(kDriRenderNode0Path), |
| 1049 base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE); |
| 1050 g_va_display_state_.Get().SetDrmFd(drm_file.GetPlatformFile()); |
| 1051 #endif |
| 1052 } |
| 1053 |
| 1054 // static |
1045 bool VaapiWrapper::PostSandboxInitialization() { | 1055 bool VaapiWrapper::PostSandboxInitialization() { |
1046 StubPathMap paths; | 1056 StubPathMap paths; |
1047 | 1057 |
1048 paths[kModuleVa].push_back("libva.so.1"); | 1058 paths[kModuleVa].push_back("libva.so.1"); |
1049 | 1059 |
1050 #if defined(USE_X11) | 1060 #if defined(USE_X11) |
1051 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | 1061 paths[kModuleVa_x11].push_back("libva-x11.so.1"); |
1052 #elif defined(USE_OZONE) | 1062 #elif defined(USE_OZONE) |
1053 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | 1063 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
1054 #endif | 1064 #endif |
(...skipping 25 matching lines...) Expand all Loading... |
1080 | 1090 |
1081 bool VaapiWrapper::LazyProfileInfos::IsProfileSupported( | 1091 bool VaapiWrapper::LazyProfileInfos::IsProfileSupported( |
1082 CodecMode mode, VAProfile va_profile) { | 1092 CodecMode mode, VAProfile va_profile) { |
1083 for (const auto& profile : supported_profiles_[mode]) { | 1093 for (const auto& profile : supported_profiles_[mode]) { |
1084 if (profile.va_profile == va_profile) | 1094 if (profile.va_profile == va_profile) |
1085 return true; | 1095 return true; |
1086 } | 1096 } |
1087 return false; | 1097 return false; |
1088 } | 1098 } |
1089 | 1099 |
| 1100 VaapiWrapper::VADisplayState::VADisplayState() |
| 1101 : refcount_(0), |
| 1102 va_display_(nullptr), |
| 1103 major_version_(-1), |
| 1104 minor_version_(-1), |
| 1105 va_initialized_(false) {} |
| 1106 |
| 1107 VaapiWrapper::VADisplayState::~VADisplayState() {} |
| 1108 |
| 1109 bool VaapiWrapper::VADisplayState::Initialize(VAStatus* status) { |
| 1110 if (refcount_++ == 0) { |
| 1111 #if defined(USE_X11) |
| 1112 va_display_ = vaGetDisplay(gfx::GetXDisplay()); |
| 1113 #elif defined(USE_OZONE) |
| 1114 va_display_ = vaGetDisplayDRM(drm_fd_.get()); |
| 1115 #endif // USE_X11 |
| 1116 |
| 1117 if (!vaDisplayIsValid(va_display_)) { |
| 1118 LOG(ERROR) << "Could not get a valid VA display"; |
| 1119 return false; |
| 1120 } |
| 1121 |
| 1122 *status = vaInitialize(va_display_, &major_version_, &minor_version_); |
| 1123 if (*status != VA_STATUS_SUCCESS) |
| 1124 return false; |
| 1125 |
| 1126 va_initialized_ = true; |
| 1127 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
| 1128 } |
| 1129 |
| 1130 if (VAAPIVersionLessThan(0, 34)) { |
| 1131 LOG(ERROR) << "VAAPI version < 0.34 is not supported."; |
| 1132 return false; |
| 1133 } |
| 1134 return true; |
| 1135 } |
| 1136 |
| 1137 void VaapiWrapper::VADisplayState::Deinitialize(VAStatus* status) { |
| 1138 if (--refcount_ > 0) |
| 1139 return; |
| 1140 |
| 1141 // Must check if vaInitialize completed successfully, to work around a bug in |
| 1142 // libva. The bug was fixed upstream: |
| 1143 // http://lists.freedesktop.org/archives/libva/2013-July/001807.html |
| 1144 // TODO(mgiuca): Remove this check, and the |va_initialized_| variable, once |
| 1145 // the fix has rolled out sufficiently. |
| 1146 if (va_initialized_ && va_display_) { |
| 1147 *status = vaTerminate(va_display_); |
| 1148 } |
| 1149 va_initialized_ = false; |
| 1150 } |
| 1151 |
| 1152 VADisplay VaapiWrapper::VADisplayState::GetVADisplay() const { |
| 1153 return va_display_; |
| 1154 } |
| 1155 |
| 1156 #if defined(USE_OZONE) |
| 1157 void VaapiWrapper::VADisplayState::SetDrmFd(base::PlatformFile fd) { |
| 1158 drm_fd_.reset(dup(fd)); |
| 1159 } |
| 1160 #endif // USE_OZONE |
| 1161 |
| 1162 bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { |
| 1163 return (major_version_ < major) || |
| 1164 (major_version_ == major && minor_version_ < minor); |
| 1165 } |
| 1166 |
1090 } // namespace content | 1167 } // namespace content |
OLD | NEW |