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 "content/common/gpu/media/vaapi_picture.h" |
17 #include "third_party/libyuv/include/libyuv.h" | 17 #include "third_party/libyuv/include/libyuv.h" |
18 #include "ui/gl/gl_bindings.h" | 18 #include "ui/gl/gl_bindings.h" |
19 #if defined(USE_X11) | 19 #if defined(USE_X11) |
20 #include "ui/gfx/x/x11_types.h" | 20 #include "ui/gfx/x/x11_types.h" |
| 21 #elif defined(USE_OZONE) |
| 22 #include "third_party/libva/va/drm/va_drm.h" |
| 23 #include "ui/ozone/public/ozone_platform.h" |
| 24 #include "ui/ozone/public/surface_factory_ozone.h" |
21 #endif // USE_X11 | 25 #endif // USE_X11 |
22 | 26 |
23 using content_common_gpu_media::kModuleVa; | 27 using content_common_gpu_media::kModuleVa; |
24 #if defined(USE_X11) | 28 #if defined(USE_X11) |
25 using content_common_gpu_media::kModuleVa_x11; | 29 using content_common_gpu_media::kModuleVa_x11; |
| 30 #elif defined(USE_OZONE) |
| 31 using content_common_gpu_media::kModuleVa_drm; |
26 #endif // USE_X11 | 32 #endif // USE_X11 |
27 using content_common_gpu_media::InitializeStubs; | 33 using content_common_gpu_media::InitializeStubs; |
28 using content_common_gpu_media::StubPathMap; | 34 using content_common_gpu_media::StubPathMap; |
29 | 35 |
30 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ | 36 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ |
31 do { \ | 37 do { \ |
32 LOG(ERROR) << err_msg \ | 38 LOG(ERROR) << err_msg \ |
33 << " VA error: " << vaErrorStr(va_error); \ | 39 << " VA error: " << vaErrorStr(va_error); \ |
34 report_error_to_uma_cb_.Run(); \ | 40 report_error_to_uma_cb_.Run(); \ |
35 } while (0) | 41 } while (0) |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 } | 141 } |
136 | 142 |
137 VASurface::~VASurface() { | 143 VASurface::~VASurface() { |
138 release_cb_.Run(va_surface_id_); | 144 release_cb_.Run(va_surface_id_); |
139 } | 145 } |
140 | 146 |
141 VaapiWrapper::VaapiWrapper() | 147 VaapiWrapper::VaapiWrapper() |
142 : va_display_(NULL), | 148 : va_display_(NULL), |
143 va_config_id_(VA_INVALID_ID), | 149 va_config_id_(VA_INVALID_ID), |
144 va_context_id_(VA_INVALID_ID), | 150 va_context_id_(VA_INVALID_ID), |
145 va_initialized_(false) { | 151 va_initialized_(false), |
| 152 va_vpp_config_id_(VA_INVALID_ID), |
| 153 va_vpp_context_id_(VA_INVALID_ID), |
| 154 va_vpp_buffer_id_(VA_INVALID_ID) { |
146 } | 155 } |
147 | 156 |
148 VaapiWrapper::~VaapiWrapper() { | 157 VaapiWrapper::~VaapiWrapper() { |
149 DestroyPendingBuffers(); | 158 DestroyPendingBuffers(); |
150 DestroyCodedBuffers(); | 159 DestroyCodedBuffers(); |
151 DestroySurfaces(); | 160 DestroySurfaces(); |
| 161 DeinitializeVpp(); |
152 Deinitialize(); | 162 Deinitialize(); |
153 } | 163 } |
154 | 164 |
155 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 165 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( |
156 CodecMode mode, | 166 CodecMode mode, |
157 media::VideoCodecProfile profile, | 167 media::VideoCodecProfile profile, |
158 const base::Closure& report_error_to_uma_cb) { | 168 const base::Closure& report_error_to_uma_cb) { |
159 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 169 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
160 | 170 |
161 if (!vaapi_wrapper->Initialize(mode, profile, report_error_to_uma_cb)) | 171 if (!vaapi_wrapper->Initialize(mode, profile, report_error_to_uma_cb)) |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 DVLOG(1) << kErrorMsg; | 230 DVLOG(1) << kErrorMsg; |
221 return false; | 231 return false; |
222 } | 232 } |
223 | 233 |
224 report_error_to_uma_cb_ = report_error_to_uma_cb; | 234 report_error_to_uma_cb_ = report_error_to_uma_cb; |
225 | 235 |
226 base::AutoLock auto_lock(va_lock_); | 236 base::AutoLock auto_lock(va_lock_); |
227 | 237 |
228 #if defined(USE_X11) | 238 #if defined(USE_X11) |
229 va_display_ = vaGetDisplay(gfx::GetXDisplay()); | 239 va_display_ = vaGetDisplay(gfx::GetXDisplay()); |
| 240 #elif defined(USE_OZONE) |
| 241 ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); |
| 242 ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); |
| 243 |
| 244 va_display_ = vaGetDisplayDRM(factory->GetDrmFd()); |
230 #endif // USE_X11 | 245 #endif // USE_X11 |
231 | 246 |
232 if (!vaDisplayIsValid(va_display_)) { | 247 if (!vaDisplayIsValid(va_display_)) { |
233 LOG(ERROR) << "Could not get a valid VA display"; | 248 LOG(ERROR) << "Could not get a valid VA display"; |
234 return false; | 249 return false; |
235 } | 250 } |
236 | 251 |
237 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 252 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); |
238 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 253 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); |
239 va_initialized_ = true; | 254 va_initialized_ = true; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 if (!va_surface_ids_.empty()) { | 453 if (!va_surface_ids_.empty()) { |
439 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_ids_[0], | 454 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_ids_[0], |
440 va_surface_ids_.size()); | 455 va_surface_ids_.size()); |
441 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); | 456 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); |
442 } | 457 } |
443 | 458 |
444 va_surface_ids_.clear(); | 459 va_surface_ids_.clear(); |
445 va_context_id_ = VA_INVALID_ID; | 460 va_context_id_ = VA_INVALID_ID; |
446 } | 461 } |
447 | 462 |
| 463 scoped_refptr<VASurface> VaapiWrapper::CreateUnownedSurface( |
| 464 unsigned int va_format, |
| 465 const gfx::Size& size, |
| 466 const std::vector<VASurfaceAttrib>& va_attribs) { |
| 467 base::AutoLock auto_lock(va_lock_); |
| 468 |
| 469 std::vector<VASurfaceAttrib> attribs(va_attribs); |
| 470 VASurfaceID va_surface_id; |
| 471 VAStatus va_res = |
| 472 vaCreateSurfaces(va_display_, va_format, size.width(), size.height(), |
| 473 &va_surface_id, 1, &attribs[0], attribs.size()); |
| 474 |
| 475 scoped_refptr<VASurface> va_surface; |
| 476 VA_SUCCESS_OR_RETURN(va_res, "Failed to create unowned VASurface", |
| 477 va_surface); |
| 478 |
| 479 // This is safe to use Unretained() here, because the VDA takes care |
| 480 // of the destruction order. All the surfaces will be destroyed |
| 481 // before VaapiWrapper. |
| 482 va_surface = new VASurface( |
| 483 va_surface_id, size, |
| 484 base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this))); |
| 485 |
| 486 return va_surface; |
| 487 } |
| 488 |
| 489 void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { |
| 490 base::AutoLock auto_lock(va_lock_); |
| 491 |
| 492 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); |
| 493 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); |
| 494 } |
| 495 |
448 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, | 496 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, |
449 size_t size, | 497 size_t size, |
450 void* buffer) { | 498 void* buffer) { |
451 base::AutoLock auto_lock(va_lock_); | 499 base::AutoLock auto_lock(va_lock_); |
452 | 500 |
453 VABufferID buffer_id; | 501 VABufferID buffer_id; |
454 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, | 502 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, |
455 va_buffer_type, size, | 503 va_buffer_type, size, |
456 1, buffer, &buffer_id); | 504 1, buffer, &buffer_id); |
457 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); | 505 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 798 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
751 | 799 |
752 va_res = vaDestroyBuffer(va_display_, buffer_id); | 800 va_res = vaDestroyBuffer(va_display_, buffer_id); |
753 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 801 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
754 | 802 |
755 DCHECK(coded_buffers_.erase(buffer_id)); | 803 DCHECK(coded_buffers_.erase(buffer_id)); |
756 | 804 |
757 return buffer_segment == NULL; | 805 return buffer_segment == NULL; |
758 } | 806 } |
759 | 807 |
| 808 bool VaapiWrapper::BlitSurface(VASurfaceID va_surface_id_src, |
| 809 const gfx::Size& src_size, |
| 810 VASurfaceID va_surface_id_dest, |
| 811 const gfx::Size& dest_size) { |
| 812 base::AutoLock auto_lock(va_lock_); |
| 813 |
| 814 // Initialize the post processing engine if not already done. |
| 815 if (va_vpp_buffer_id_ == VA_INVALID_ID) { |
| 816 if (!InitializeVpp_Locked()) |
| 817 return false; |
| 818 } |
| 819 |
| 820 VAProcPipelineParameterBuffer* pipeline_param; |
| 821 VA_SUCCESS_OR_RETURN(vaMapBuffer(va_display_, va_vpp_buffer_id_, |
| 822 reinterpret_cast<void**>(&pipeline_param)), |
| 823 "Couldn't map vpp buffer", false); |
| 824 |
| 825 memset(pipeline_param, 0, sizeof *pipeline_param); |
| 826 |
| 827 VARectangle input_region; |
| 828 input_region.x = input_region.y = 0; |
| 829 input_region.width = src_size.width(); |
| 830 input_region.height = src_size.height(); |
| 831 pipeline_param->surface_region = &input_region; |
| 832 pipeline_param->surface = va_surface_id_src; |
| 833 pipeline_param->surface_color_standard = VAProcColorStandardNone; |
| 834 |
| 835 VARectangle output_region; |
| 836 output_region.x = output_region.y = 0; |
| 837 output_region.width = dest_size.width(); |
| 838 output_region.height = dest_size.height(); |
| 839 pipeline_param->output_region = &output_region; |
| 840 pipeline_param->output_background_color = 0xff000000; |
| 841 pipeline_param->output_color_standard = VAProcColorStandardNone; |
| 842 |
| 843 VA_SUCCESS_OR_RETURN(vaUnmapBuffer(va_display_, va_vpp_buffer_id_), |
| 844 "Couldn't unmap vpp buffer", false); |
| 845 |
| 846 VA_SUCCESS_OR_RETURN( |
| 847 vaBeginPicture(va_display_, va_vpp_context_id_, va_surface_id_dest), |
| 848 "Couldn't begin picture", false); |
| 849 |
| 850 VA_SUCCESS_OR_RETURN( |
| 851 vaRenderPicture(va_display_, va_vpp_context_id_, &va_vpp_buffer_id_, 1), |
| 852 "Couldn't render picture", false); |
| 853 |
| 854 VA_SUCCESS_OR_RETURN(vaEndPicture(va_display_, va_vpp_context_id_), |
| 855 "Couldn't end picture", false); |
| 856 |
| 857 return true; |
| 858 } |
| 859 |
| 860 bool VaapiWrapper::InitializeVpp_Locked() { |
| 861 va_lock_.AssertAcquired(); |
| 862 |
| 863 VA_SUCCESS_OR_RETURN( |
| 864 vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, NULL, 0, |
| 865 &va_vpp_config_id_), |
| 866 "Couldn't create config", false); |
| 867 |
| 868 // The size of the picture for the context is irrelevant in the case |
| 869 // of the VPP, just passing 1x1. |
| 870 VA_SUCCESS_OR_RETURN(vaCreateContext(va_display_, va_vpp_config_id_, 1, 1, 0, |
| 871 NULL, 0, &va_vpp_context_id_), |
| 872 "Couldn't create context", false); |
| 873 |
| 874 VA_SUCCESS_OR_RETURN(vaCreateBuffer(va_display_, va_vpp_context_id_, |
| 875 VAProcPipelineParameterBufferType, |
| 876 sizeof(VAProcPipelineParameterBuffer), 1, |
| 877 NULL, &va_vpp_buffer_id_), |
| 878 "Couldn't create buffer", false); |
| 879 |
| 880 return true; |
| 881 } |
| 882 |
| 883 void VaapiWrapper::DeinitializeVpp() { |
| 884 base::AutoLock auto_lock(va_lock_); |
| 885 |
| 886 if (va_vpp_buffer_id_ != VA_INVALID_ID) { |
| 887 vaDestroyBuffer(va_display_, va_vpp_buffer_id_); |
| 888 va_vpp_buffer_id_ = VA_INVALID_ID; |
| 889 } |
| 890 if (va_vpp_context_id_ != VA_INVALID_ID) { |
| 891 vaDestroyContext(va_display_, va_vpp_context_id_); |
| 892 va_vpp_context_id_ = VA_INVALID_ID; |
| 893 } |
| 894 if (va_vpp_config_id_ != VA_INVALID_ID) { |
| 895 vaDestroyConfig(va_display_, va_vpp_config_id_); |
| 896 va_vpp_config_id_ = VA_INVALID_ID; |
| 897 } |
| 898 } |
| 899 |
760 // static | 900 // static |
761 bool VaapiWrapper::PostSandboxInitialization() { | 901 bool VaapiWrapper::PostSandboxInitialization() { |
762 StubPathMap paths; | 902 StubPathMap paths; |
763 | 903 |
764 paths[kModuleVa].push_back("libva.so.1"); | 904 paths[kModuleVa].push_back("libva.so.1"); |
765 | 905 |
766 #if defined(USE_X11) | 906 #if defined(USE_X11) |
767 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | 907 paths[kModuleVa_x11].push_back("libva-x11.so.1"); |
| 908 #elif defined(USE_OZONE) |
| 909 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
768 #endif | 910 #endif |
769 | 911 |
770 return InitializeStubs(paths); | 912 return InitializeStubs(paths); |
771 } | 913 } |
772 | 914 |
773 } // namespace content | 915 } // namespace content |
OLD | NEW |