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 // Auto-generated for dlopen libva libraries | 13 // Auto-generated for dlopen libva libraries |
14 #include "content/common/gpu/media/va_stubs.h" | 14 #include "content/common/gpu/media/va_stubs.h" |
15 #include "third_party/libyuv/include/libyuv.h" | 15 #include "third_party/libyuv/include/libyuv.h" |
16 #if defined(USE_X11) | |
17 #include "third_party/libva/va/va_x11.h" | |
18 #include "ui/gfx/x/x11_types.h" | |
19 #else | |
20 #include "third_party/libva/va/drm/va_drm.h" | |
21 #include "third_party/libva/va/va_drmcommon.h" | |
22 #include "ui/ozone/public/ozone_platform.h" | |
23 #include "ui/ozone/public/surface_factory_ozone.h" | |
24 #endif // USE_X11 | |
25 #include "ui/gl/gl_bindings.h" | |
16 | 26 |
17 using content_common_gpu_media::kModuleVa; | 27 using content_common_gpu_media::kModuleVa; |
28 #if defined(USE_X11) | |
29 using content_common_gpu_media::kModuleVa_x11; | |
30 #else | |
31 using content_common_gpu_media::kModuleVa_drm; | |
32 #endif // USE_X11 | |
18 using content_common_gpu_media::InitializeStubs; | 33 using content_common_gpu_media::InitializeStubs; |
19 using content_common_gpu_media::StubPathMap; | 34 using content_common_gpu_media::StubPathMap; |
20 | 35 |
21 // libva-x11 depends on libva, so dlopen libva-x11 is enough | |
22 static const base::FilePath::CharType kVaLib[] = | |
23 FILE_PATH_LITERAL("libva-x11.so.1"); | |
24 | |
25 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ | 36 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ |
26 do { \ | 37 do { \ |
27 DVLOG(1) << err_msg \ | 38 DVLOG(1) << err_msg \ |
28 << " VA error: " << vaErrorStr(va_error); \ | 39 << " VA error: " << vaErrorStr(va_error); \ |
29 report_error_to_uma_cb_.Run(); \ | 40 report_error_to_uma_cb_.Run(); \ |
30 } while (0) | 41 } while (0) |
31 | 42 |
32 #define VA_LOG_ON_ERROR(va_error, err_msg) \ | 43 #define VA_LOG_ON_ERROR(va_error, err_msg) \ |
33 do { \ | 44 do { \ |
34 if ((va_error) != VA_STATUS_SUCCESS) \ | 45 if ((va_error) != VA_STATUS_SUCCESS) \ |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 VaapiWrapper::~VaapiWrapper() { | 132 VaapiWrapper::~VaapiWrapper() { |
122 DestroyPendingBuffers(); | 133 DestroyPendingBuffers(); |
123 DestroyCodedBuffers(); | 134 DestroyCodedBuffers(); |
124 DestroySurfaces(); | 135 DestroySurfaces(); |
125 Deinitialize(); | 136 Deinitialize(); |
126 } | 137 } |
127 | 138 |
128 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 139 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( |
129 CodecMode mode, | 140 CodecMode mode, |
130 media::VideoCodecProfile profile, | 141 media::VideoCodecProfile profile, |
131 Display* x_display, | |
132 const base::Closure& report_error_to_uma_cb) { | 142 const base::Closure& report_error_to_uma_cb) { |
143 static bool vaapi_functions_initialized = PostSandboxInitialization(); | |
133 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 144 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
134 | 145 |
135 if (!vaapi_wrapper->Initialize( | 146 if (!vaapi_functions_initialized) { |
136 mode, profile, x_display, report_error_to_uma_cb)) | 147 DVLOG(1) << "Failed to initialize VAAPI libs"; |
148 return vaapi_wrapper.Pass(); | |
149 } | |
150 | |
151 VADisplay va_display = NULL; | |
152 #if defined(USE_X11) | |
153 va_display = vaGetDisplay(gfx::GetXDisplay()); | |
154 #else | |
155 ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); | |
156 ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); | |
157 | |
158 va_display = vaGetDisplayDRM(factory->GetDrmFd()); | |
Pawel Osciak
2014/10/08 08:17:22
Do we need to close the fd somewhere?
llandwerlin-old
2014/10/13 16:53:00
I don't think we need to do anything here.
The fil
| |
159 #endif // USE_X11 | |
160 | |
161 if (!va_display || | |
162 !vaapi_wrapper->Initialize( | |
163 va_display, mode, profile, report_error_to_uma_cb)) | |
137 vaapi_wrapper.reset(); | 164 vaapi_wrapper.reset(); |
138 | 165 |
139 return vaapi_wrapper.Pass(); | 166 return vaapi_wrapper.Pass(); |
140 } | 167 } |
141 | 168 |
142 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 169 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
143 VADisplayAttribute item = {VADisplayAttribRenderMode, | 170 VADisplayAttribute item = {VADisplayAttribRenderMode, |
144 1, // At least support '_LOCAL_OVERLAY'. | 171 1, // At least support '_LOCAL_OVERLAY'. |
145 -1, // The maximum possible support 'ALL'. | 172 -1, // The maximum possible support 'ALL'. |
146 VA_RENDER_MODE_LOCAL_GPU, | 173 VA_RENDER_MODE_LOCAL_GPU, |
147 VA_DISPLAY_ATTRIB_SETTABLE}; | 174 VA_DISPLAY_ATTRIB_SETTABLE}; |
148 | 175 |
149 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 176 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
150 if (va_res != VA_STATUS_SUCCESS) | 177 if (va_res != VA_STATUS_SUCCESS) |
151 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 178 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
152 } | 179 } |
153 | 180 |
154 bool VaapiWrapper::Initialize(CodecMode mode, | 181 bool VaapiWrapper::Initialize(VADisplay va_display, |
182 CodecMode mode, | |
155 media::VideoCodecProfile profile, | 183 media::VideoCodecProfile profile, |
156 Display* x_display, | |
157 const base::Closure& report_error_to_uma_cb) { | 184 const base::Closure& report_error_to_uma_cb) { |
158 static bool vaapi_functions_initialized = PostSandboxInitialization(); | |
159 if (!vaapi_functions_initialized) { | |
160 DVLOG(1) << "Failed to initialize VAAPI libs"; | |
161 return false; | |
162 } | |
163 | |
164 report_error_to_uma_cb_ = report_error_to_uma_cb; | 185 report_error_to_uma_cb_ = report_error_to_uma_cb; |
165 | 186 |
166 base::AutoLock auto_lock(va_lock_); | 187 base::AutoLock auto_lock(va_lock_); |
167 | 188 |
168 va_display_ = vaGetDisplay(x_display); | 189 va_display_ = va_display; |
169 if (!vaDisplayIsValid(va_display_)) { | 190 if (!vaDisplayIsValid(va_display_)) { |
170 DVLOG(1) << "Could not get a valid VA display"; | 191 DVLOG(1) << "Could not get a valid VA display"; |
171 return false; | 192 return false; |
172 } | 193 } |
173 | 194 |
174 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 195 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); |
175 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 196 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); |
176 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | 197 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
177 | 198 |
178 if (VAAPIVersionLessThan(0, 34)) { | 199 if (VAAPIVersionLessThan(0, 34)) { |
(...skipping 12 matching lines...) Expand all Loading... | |
191 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); | 212 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); |
192 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { | 213 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { |
193 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; | 214 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; |
194 return false; | 215 return false; |
195 } | 216 } |
196 | 217 |
197 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); | 218 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); |
198 | 219 |
199 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); | 220 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); |
200 if (va_profile == VAProfileNone) { | 221 if (va_profile == VAProfileNone) { |
201 DVLOG(1) << "Unsupported profile"; | 222 DVLOG(1) << "Unsupported profile : " << profile; |
202 return false; | 223 return false; |
203 } | 224 } |
204 | 225 |
205 // Query the driver for supported entrypoints. | 226 // Query the driver for supported entrypoints. |
206 int max_entrypoints = vaMaxNumEntrypoints(va_display_); | 227 int max_entrypoints = vaMaxNumEntrypoints(va_display_); |
207 std::vector<VAEntrypoint> supported_entrypoints( | 228 std::vector<VAEntrypoint> supported_entrypoints( |
208 base::checked_cast<size_t>(max_entrypoints)); | 229 base::checked_cast<size_t>(max_entrypoints)); |
209 | 230 |
210 int num_supported_entrypoints; | 231 int num_supported_entrypoints; |
211 va_res = vaQueryConfigEntrypoints(va_display_, | 232 va_res = vaQueryConfigEntrypoints(va_display_, |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 | 310 |
290 va_config_id_ = VA_INVALID_ID; | 311 va_config_id_ = VA_INVALID_ID; |
291 va_display_ = NULL; | 312 va_display_ = NULL; |
292 } | 313 } |
293 | 314 |
294 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { | 315 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { |
295 return (major_version_ < major) || | 316 return (major_version_ < major) || |
296 (major_version_ == major && minor_version_ < minor); | 317 (major_version_ == major && minor_version_ < minor); |
297 } | 318 } |
298 | 319 |
299 bool VaapiWrapper::CreateSurfaces(gfx::Size size, | 320 bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, |
300 size_t num_surfaces, | 321 size_t num_surfaces, |
301 std::vector<VASurfaceID>* va_surfaces) { | 322 std::vector<VASurfaceID>* va_surfaces) { |
302 base::AutoLock auto_lock(va_lock_); | 323 base::AutoLock auto_lock(va_lock_); |
303 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; | 324 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; |
304 | 325 |
305 DCHECK(va_surfaces->empty()); | 326 DCHECK(va_surfaces->empty()); |
306 DCHECK(va_surface_ids_.empty()); | 327 DCHECK(va_surface_ids_.empty()); |
307 va_surface_ids_.resize(num_surfaces); | 328 va_surface_ids_.resize(num_surfaces); |
308 | 329 |
309 // Allocate surfaces in driver. | 330 // Allocate surfaces in driver. |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
499 | 520 |
500 return true; | 521 return true; |
501 } | 522 } |
502 | 523 |
503 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { | 524 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { |
504 bool result = Execute(va_surface_id); | 525 bool result = Execute(va_surface_id); |
505 DestroyPendingBuffers(); | 526 DestroyPendingBuffers(); |
506 return result; | 527 return result; |
507 } | 528 } |
508 | 529 |
509 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, | |
510 Pixmap x_pixmap, | |
511 gfx::Size dest_size) { | |
512 base::AutoLock auto_lock(va_lock_); | |
513 | |
514 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | |
515 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | |
516 | |
517 // Put the data into an X Pixmap. | |
518 va_res = vaPutSurface(va_display_, | |
519 va_surface_id, | |
520 x_pixmap, | |
521 0, 0, dest_size.width(), dest_size.height(), | |
522 0, 0, dest_size.width(), dest_size.height(), | |
523 NULL, 0, 0); | |
524 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); | |
525 return true; | |
526 } | |
527 | |
528 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, | 530 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, |
529 VAImage* image, | 531 VAImage* image, |
530 void** mem) { | 532 void** mem) { |
531 base::AutoLock auto_lock(va_lock_); | 533 base::AutoLock auto_lock(va_lock_); |
532 | 534 |
533 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 535 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
534 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 536 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
535 | 537 |
536 // Derive a VAImage from the VASurface | 538 // Derive a VAImage from the VASurface |
537 va_res = vaDeriveImage(va_display_, va_surface_id, image); | 539 va_res = vaDeriveImage(va_display_, va_surface_id, image); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 660 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
659 | 661 |
660 va_res = vaDestroyBuffer(va_display_, buffer_id); | 662 va_res = vaDestroyBuffer(va_display_, buffer_id); |
661 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 663 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
662 | 664 |
663 DCHECK(coded_buffers_.erase(buffer_id)); | 665 DCHECK(coded_buffers_.erase(buffer_id)); |
664 | 666 |
665 return buffer_segment == NULL; | 667 return buffer_segment == NULL; |
666 } | 668 } |
667 | 669 |
670 VADisplay VaapiWrapper::GetDisplay() { | |
671 return va_display_; | |
672 } | |
673 | |
668 // static | 674 // static |
669 bool VaapiWrapper::PostSandboxInitialization() { | 675 bool VaapiWrapper::PostSandboxInitialization() { |
670 StubPathMap paths; | 676 StubPathMap paths; |
671 paths[kModuleVa].push_back(kVaLib); | 677 |
678 paths[kModuleVa].push_back("libva.so.1"); | |
679 | |
680 #if defined(USE_X11) | |
681 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | |
682 #else | |
683 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | |
684 #endif | |
672 | 685 |
673 return InitializeStubs(paths); | 686 return InitializeStubs(paths); |
674 } | 687 } |
675 | 688 |
676 } // namespace content | 689 } // namespace content |
OLD | NEW |