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" | 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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/numerics/safe_conversions.h" | 12 #include "base/numerics/safe_conversions.h" |
| 13 #include "base/sys_info.h" | 13 #include "base/sys_info.h" |
| 14 // Auto-generated for dlopen libva libraries | 14 // Auto-generated for dlopen libva libraries |
| 15 #include "content/common/gpu/media/va_stubs.h" | 15 #include "content/common/gpu/media/va_stubs.h" |
| 16 #include "content/common/gpu/media/vaapi_picture.h" | |
| 16 #include "third_party/libyuv/include/libyuv.h" | 17 #include "third_party/libyuv/include/libyuv.h" |
| 18 #include "ui/gl/gl_bindings.h" | |
| 19 #if defined(USE_X11) | |
| 20 #include "ui/gfx/x/x11_types.h" | |
| 21 #endif // USE_X11 | |
| 17 | 22 |
| 18 using content_common_gpu_media::kModuleVa; | 23 using content_common_gpu_media::kModuleVa; |
| 24 #if defined(USE_X11) | |
| 25 using content_common_gpu_media::kModuleVa_x11; | |
| 26 #endif // USE_X11 | |
| 19 using content_common_gpu_media::InitializeStubs; | 27 using content_common_gpu_media::InitializeStubs; |
| 20 using content_common_gpu_media::StubPathMap; | 28 using content_common_gpu_media::StubPathMap; |
| 21 | 29 |
| 22 // libva-x11 depends on libva, so dlopen libva-x11 is enough | |
| 23 static const base::FilePath::CharType kVaLib[] = | |
| 24 FILE_PATH_LITERAL("libva-x11.so.1"); | |
| 25 | |
| 26 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ | 30 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ |
| 27 do { \ | 31 do { \ |
| 28 LOG(ERROR) << err_msg \ | 32 LOG(ERROR) << err_msg \ |
| 29 << " VA error: " << vaErrorStr(va_error); \ | 33 << " VA error: " << vaErrorStr(va_error); \ |
| 30 report_error_to_uma_cb_.Run(); \ | 34 report_error_to_uma_cb_.Run(); \ |
| 31 } while (0) | 35 } while (0) |
| 32 | 36 |
| 33 #define VA_LOG_ON_ERROR(va_error, err_msg) \ | 37 #define VA_LOG_ON_ERROR(va_error, err_msg) \ |
| 34 do { \ | 38 do { \ |
| 35 if ((va_error) != VA_STATUS_SUCCESS) \ | 39 if ((va_error) != VA_STATUS_SUCCESS) \ |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 VAProfileH264ConstrainedBaseline) != | 120 VAProfileH264ConstrainedBaseline) != |
| 117 supported_profiles.end()) { | 121 supported_profiles.end()) { |
| 118 va_profile = VAProfileH264ConstrainedBaseline; | 122 va_profile = VAProfileH264ConstrainedBaseline; |
| 119 DVLOG(1) << "Falling back to constrained baseline profile."; | 123 DVLOG(1) << "Falling back to constrained baseline profile."; |
| 120 } | 124 } |
| 121 } | 125 } |
| 122 | 126 |
| 123 return va_profile; | 127 return va_profile; |
| 124 } | 128 } |
| 125 | 129 |
| 126 VASurface::VASurface(VASurfaceID va_surface_id, const ReleaseCB& release_cb) | 130 VASurface::VASurface(VASurfaceID va_surface_id, |
| 127 : va_surface_id_(va_surface_id), | 131 const gfx::Size& size, |
| 128 release_cb_(release_cb) { | 132 const ReleaseCB& release_cb) |
| 133 : va_surface_id_(va_surface_id), size_(size), release_cb_(release_cb) { | |
| 129 DCHECK(!release_cb_.is_null()); | 134 DCHECK(!release_cb_.is_null()); |
| 130 } | 135 } |
| 131 | 136 |
| 132 VASurface::~VASurface() { | 137 VASurface::~VASurface() { |
| 133 release_cb_.Run(va_surface_id_); | 138 release_cb_.Run(va_surface_id_); |
| 134 } | 139 } |
| 135 | 140 |
| 136 VaapiWrapper::VaapiWrapper() | 141 VaapiWrapper::VaapiWrapper() |
| 137 : va_display_(NULL), | 142 : va_display_(NULL), |
| 138 va_config_id_(VA_INVALID_ID), | 143 va_config_id_(VA_INVALID_ID), |
| 139 va_context_id_(VA_INVALID_ID), | 144 va_context_id_(VA_INVALID_ID), |
| 140 va_initialized_(false) { | 145 va_initialized_(false) { |
| 141 } | 146 } |
| 142 | 147 |
| 143 VaapiWrapper::~VaapiWrapper() { | 148 VaapiWrapper::~VaapiWrapper() { |
| 144 DestroyPendingBuffers(); | 149 DestroyPendingBuffers(); |
| 145 DestroyCodedBuffers(); | 150 DestroyCodedBuffers(); |
| 146 DestroySurfaces(); | 151 DestroySurfaces(); |
| 147 Deinitialize(); | 152 Deinitialize(); |
| 148 } | 153 } |
| 149 | 154 |
| 150 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 155 scoped_refptr<VaapiWrapper> VaapiWrapper::Create( |
| 151 CodecMode mode, | 156 CodecMode mode, |
| 152 media::VideoCodecProfile profile, | 157 media::VideoCodecProfile profile, |
| 153 Display* x_display, | |
| 154 const base::Closure& report_error_to_uma_cb) { | 158 const base::Closure& report_error_to_uma_cb) { |
| 155 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 159 scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
| 156 | 160 |
| 157 if (!vaapi_wrapper->Initialize( | 161 if (!vaapi_wrapper->Initialize(mode, profile, report_error_to_uma_cb)) |
| 158 mode, profile, x_display, report_error_to_uma_cb)) | 162 vaapi_wrapper = NULL; |
| 159 vaapi_wrapper.reset(); | |
| 160 | 163 |
| 161 return vaapi_wrapper.Pass(); | 164 return vaapi_wrapper; |
| 162 } | 165 } |
| 163 | 166 |
| 164 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles( | 167 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles( |
| 165 Display* x_display, | |
| 166 const base::Closure& report_error_to_uma_cb) { | 168 const base::Closure& report_error_to_uma_cb) { |
| 167 std::vector<media::VideoCodecProfile> supported_profiles; | 169 std::vector<media::VideoCodecProfile> supported_profiles; |
| 168 | 170 |
| 169 scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper()); | 171 scoped_refptr<VaapiWrapper> wrapper(new VaapiWrapper()); |
| 170 if (!wrapper->VaInitialize(x_display, report_error_to_uma_cb)) { | 172 if (!wrapper->VaInitialize(report_error_to_uma_cb)) { |
| 171 return supported_profiles; | 173 return supported_profiles; |
| 172 } | 174 } |
| 173 | 175 |
| 174 std::vector<VAProfile> va_profiles; | 176 std::vector<VAProfile> va_profiles; |
| 175 if (!wrapper->GetSupportedVaProfiles(&va_profiles)) | 177 if (!wrapper->GetSupportedVaProfiles(&va_profiles)) |
| 176 return supported_profiles; | 178 return supported_profiles; |
| 177 | 179 |
| 178 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode); | 180 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode); |
| 179 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | 181 for (size_t i = 0; i < arraysize(kProfileMap); i++) { |
| 180 VAProfile va_profile = | 182 VAProfile va_profile = |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 195 1, // At least support '_LOCAL_OVERLAY'. | 197 1, // At least support '_LOCAL_OVERLAY'. |
| 196 -1, // The maximum possible support 'ALL'. | 198 -1, // The maximum possible support 'ALL'. |
| 197 VA_RENDER_MODE_LOCAL_GPU, | 199 VA_RENDER_MODE_LOCAL_GPU, |
| 198 VA_DISPLAY_ATTRIB_SETTABLE}; | 200 VA_DISPLAY_ATTRIB_SETTABLE}; |
| 199 | 201 |
| 200 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 202 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
| 201 if (va_res != VA_STATUS_SUCCESS) | 203 if (va_res != VA_STATUS_SUCCESS) |
| 202 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 204 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
| 203 } | 205 } |
| 204 | 206 |
| 205 bool VaapiWrapper::VaInitialize(Display* x_display, | 207 bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) { |
| 206 const base::Closure& report_error_to_uma_cb) { | |
| 207 static bool vaapi_functions_initialized = PostSandboxInitialization(); | 208 static bool vaapi_functions_initialized = PostSandboxInitialization(); |
| 208 if (!vaapi_functions_initialized) { | 209 if (!vaapi_functions_initialized) { |
| 209 bool running_on_chromeos = false; | 210 bool running_on_chromeos = false; |
| 210 #if defined(OS_CHROMEOS) | 211 #if defined(OS_CHROMEOS) |
| 211 // When chrome runs on linux with chromeos=1, do not log error message | 212 // When chrome runs on linux with chromeos=1, do not log error message |
| 212 // without VAAPI libraries. | 213 // without VAAPI libraries. |
| 213 running_on_chromeos = base::SysInfo::IsRunningOnChromeOS(); | 214 running_on_chromeos = base::SysInfo::IsRunningOnChromeOS(); |
| 214 #endif | 215 #endif |
| 215 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; | 216 static const char kErrorMsg[] = "Failed to initialize VAAPI libs"; |
| 216 if (running_on_chromeos) | 217 if (running_on_chromeos) |
| 217 LOG(ERROR) << kErrorMsg; | 218 LOG(ERROR) << kErrorMsg; |
| 218 else | 219 else |
| 219 DVLOG(1) << kErrorMsg; | 220 DVLOG(1) << kErrorMsg; |
| 220 return false; | 221 return false; |
| 221 } | 222 } |
| 222 | 223 |
| 223 report_error_to_uma_cb_ = report_error_to_uma_cb; | 224 report_error_to_uma_cb_ = report_error_to_uma_cb; |
| 224 | 225 |
| 225 base::AutoLock auto_lock(va_lock_); | 226 base::AutoLock auto_lock(va_lock_); |
| 226 | 227 |
| 227 va_display_ = vaGetDisplay(x_display); | 228 #if defined(USE_X11) |
| 229 va_display_ = vaGetDisplay(gfx::GetXDisplay()); | |
| 230 #endif // USE_X11 | |
| 231 | |
| 228 if (!vaDisplayIsValid(va_display_)) { | 232 if (!vaDisplayIsValid(va_display_)) { |
| 229 LOG(ERROR) << "Could not get a valid VA display"; | 233 LOG(ERROR) << "Could not get a valid VA display"; |
| 230 return false; | 234 return false; |
| 231 } | 235 } |
| 232 | 236 |
| 233 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 237 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); |
| 234 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 238 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); |
| 235 va_initialized_ = true; | 239 va_initialized_ = true; |
| 236 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | 240 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
| 237 | 241 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 318 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
| 315 << " for attribute type " << required_attribs[i].type; | 319 << " for attribute type " << required_attribs[i].type; |
| 316 return false; | 320 return false; |
| 317 } | 321 } |
| 318 } | 322 } |
| 319 return true; | 323 return true; |
| 320 } | 324 } |
| 321 | 325 |
| 322 bool VaapiWrapper::Initialize(CodecMode mode, | 326 bool VaapiWrapper::Initialize(CodecMode mode, |
| 323 media::VideoCodecProfile profile, | 327 media::VideoCodecProfile profile, |
| 324 Display* x_display, | |
| 325 const base::Closure& report_error_to_uma_cb) { | 328 const base::Closure& report_error_to_uma_cb) { |
| 326 if (!VaInitialize(x_display, report_error_to_uma_cb)) | 329 if (!VaInitialize(report_error_to_uma_cb)) |
| 327 return false; | 330 return false; |
| 328 std::vector<VAProfile> supported_va_profiles; | 331 std::vector<VAProfile> supported_va_profiles; |
| 329 if (!GetSupportedVaProfiles(&supported_va_profiles)) | 332 if (!GetSupportedVaProfiles(&supported_va_profiles)) |
| 330 return false; | 333 return false; |
| 331 VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles); | 334 VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles); |
| 332 if (va_profile == VAProfileNone) { | 335 if (va_profile == VAProfileNone) { |
| 333 DVLOG(1) << "Unsupported profile"; | 336 DVLOG(1) << "Unsupported profile"; |
| 334 return false; | 337 return false; |
| 335 } | 338 } |
| 336 VAEntrypoint entrypoint = | 339 VAEntrypoint entrypoint = |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 376 va_config_id_ = VA_INVALID_ID; | 379 va_config_id_ = VA_INVALID_ID; |
| 377 va_display_ = NULL; | 380 va_display_ = NULL; |
| 378 va_initialized_ = false; | 381 va_initialized_ = false; |
| 379 } | 382 } |
| 380 | 383 |
| 381 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { | 384 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { |
| 382 return (major_version_ < major) || | 385 return (major_version_ < major) || |
| 383 (major_version_ == major && minor_version_ < minor); | 386 (major_version_ == major && minor_version_ < minor); |
| 384 } | 387 } |
| 385 | 388 |
| 386 bool VaapiWrapper::CreateSurfaces(gfx::Size size, | 389 bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, |
| 387 size_t num_surfaces, | 390 size_t num_surfaces, |
| 388 std::vector<VASurfaceID>* va_surfaces) { | 391 std::vector<VASurfaceID>* va_surfaces) { |
| 389 base::AutoLock auto_lock(va_lock_); | 392 base::AutoLock auto_lock(va_lock_); |
| 390 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; | 393 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; |
| 391 | 394 |
| 392 DCHECK(va_surfaces->empty()); | 395 DCHECK(va_surfaces->empty()); |
| 393 DCHECK(va_surface_ids_.empty()); | 396 DCHECK(va_surface_ids_.empty()); |
| 394 va_surface_ids_.resize(num_surfaces); | 397 va_surface_ids_.resize(num_surfaces); |
| 395 | 398 |
| 396 // Allocate surfaces in driver. | 399 // Allocate surfaces in driver. |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 586 | 589 |
| 587 return true; | 590 return true; |
| 588 } | 591 } |
| 589 | 592 |
| 590 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { | 593 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { |
| 591 bool result = Execute(va_surface_id); | 594 bool result = Execute(va_surface_id); |
| 592 DestroyPendingBuffers(); | 595 DestroyPendingBuffers(); |
| 593 return result; | 596 return result; |
| 594 } | 597 } |
| 595 | 598 |
| 596 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, | |
| 597 Pixmap x_pixmap, | |
| 598 gfx::Size dest_size) { | |
| 599 base::AutoLock auto_lock(va_lock_); | |
| 600 | |
| 601 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | |
| 602 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | |
| 603 | |
| 604 // Put the data into an X Pixmap. | |
| 605 va_res = vaPutSurface(va_display_, | |
| 606 va_surface_id, | |
| 607 x_pixmap, | |
| 608 0, 0, dest_size.width(), dest_size.height(), | |
| 609 0, 0, dest_size.width(), dest_size.height(), | |
| 610 NULL, 0, 0); | |
| 611 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); | |
| 612 return true; | |
| 613 } | |
| 614 | |
| 615 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, | 599 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, |
| 616 VAImage* image, | 600 VAImage* image, |
| 617 void** mem) { | 601 void** mem) { |
| 618 base::AutoLock auto_lock(va_lock_); | 602 base::AutoLock auto_lock(va_lock_); |
| 619 | 603 |
| 620 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 604 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
| 621 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 605 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
| 622 | 606 |
| 623 // Derive a VAImage from the VASurface | 607 // Derive a VAImage from the VASurface |
| 624 va_res = vaDeriveImage(va_display_, va_surface_id, image); | 608 va_res = vaDeriveImage(va_display_, va_surface_id, image); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 745 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 729 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
| 746 | 730 |
| 747 va_res = vaDestroyBuffer(va_display_, buffer_id); | 731 va_res = vaDestroyBuffer(va_display_, buffer_id); |
| 748 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 732 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
| 749 | 733 |
| 750 DCHECK(coded_buffers_.erase(buffer_id)); | 734 DCHECK(coded_buffers_.erase(buffer_id)); |
| 751 | 735 |
| 752 return buffer_segment == NULL; | 736 return buffer_segment == NULL; |
| 753 } | 737 } |
| 754 | 738 |
| 739 #if defined(USE_X11) | |
| 740 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, | |
|
Pawel Osciak
2014/12/20 20:46:51
Please don't move around things that don't change,
llandwerlin-old
2014/12/20 21:11:43
Acknowledged.
| |
| 741 Pixmap x_pixmap, | |
| 742 gfx::Size dest_size) { | |
| 743 base::AutoLock auto_lock(va_lock_); | |
| 744 | |
| 745 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | |
| 746 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | |
| 747 | |
| 748 // Put the data into an X Pixmap. | |
| 749 va_res = vaPutSurface(va_display_, va_surface_id, x_pixmap, 0, 0, | |
| 750 dest_size.width(), dest_size.height(), 0, 0, | |
| 751 dest_size.width(), dest_size.height(), NULL, 0, 0); | |
| 752 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); | |
| 753 return true; | |
| 754 } | |
| 755 #endif // USE_X11 | |
| 756 | |
| 755 // static | 757 // static |
| 756 bool VaapiWrapper::PostSandboxInitialization() { | 758 bool VaapiWrapper::PostSandboxInitialization() { |
| 757 StubPathMap paths; | 759 StubPathMap paths; |
| 758 paths[kModuleVa].push_back(kVaLib); | 760 |
| 761 paths[kModuleVa].push_back("libva.so.1"); | |
| 762 | |
| 763 #if defined(USE_X11) | |
| 764 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | |
| 765 #endif | |
| 759 | 766 |
| 760 return InitializeStubs(paths); | 767 return InitializeStubs(paths); |
| 761 } | 768 } |
| 762 | 769 |
| 763 } // namespace content | 770 } // namespace content |
| OLD | NEW |