| 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 |