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()); | |
jiajia.qin
2014/09/16 11:09:55
Hi, llandwerlin. Does it work for other external d
llandwerlin-old
2014/09/16 12:28:58
What do you mean by external display?
Are you usin
spang
2014/09/16 16:31:28
No, it doesn't work with wayland. I'm hoping we ca
| |
159 #endif // USE_X11 | |
160 | |
161 if (!va_display || !vaapi_wrapper->Initialize(va_display, | |
162 mode, | |
163 profile, | |
164 report_error_to_uma_cb)) | |
137 vaapi_wrapper.reset(); | 165 vaapi_wrapper.reset(); |
138 | 166 |
139 return vaapi_wrapper.Pass(); | 167 return vaapi_wrapper.Pass(); |
140 } | 168 } |
141 | 169 |
142 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 170 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
143 VADisplayAttribute item = {VADisplayAttribRenderMode, | 171 VADisplayAttribute item = {VADisplayAttribRenderMode, |
144 1, // At least support '_LOCAL_OVERLAY'. | 172 1, // At least support '_LOCAL_OVERLAY'. |
145 -1, // The maximum possible support 'ALL'. | 173 -1, // The maximum possible support 'ALL'. |
146 VA_RENDER_MODE_LOCAL_GPU, | 174 VA_RENDER_MODE_LOCAL_GPU, |
147 VA_DISPLAY_ATTRIB_SETTABLE}; | 175 VA_DISPLAY_ATTRIB_SETTABLE}; |
148 | 176 |
149 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 177 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
150 if (va_res != VA_STATUS_SUCCESS) | 178 if (va_res != VA_STATUS_SUCCESS) |
151 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 179 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
152 } | 180 } |
153 | 181 |
154 bool VaapiWrapper::Initialize(CodecMode mode, | 182 bool VaapiWrapper::Initialize(VADisplay va_display, |
183 CodecMode mode, | |
155 media::VideoCodecProfile profile, | 184 media::VideoCodecProfile profile, |
156 Display* x_display, | |
157 const base::Closure& report_error_to_uma_cb) { | 185 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; | 186 report_error_to_uma_cb_ = report_error_to_uma_cb; |
165 | 187 |
166 base::AutoLock auto_lock(va_lock_); | 188 base::AutoLock auto_lock(va_lock_); |
167 | 189 |
168 va_display_ = vaGetDisplay(x_display); | 190 va_display_ = va_display; |
169 if (!vaDisplayIsValid(va_display_)) { | 191 if (!vaDisplayIsValid(va_display_)) { |
170 DVLOG(1) << "Could not get a valid VA display"; | 192 DVLOG(1) << "Could not get a valid VA display"; |
171 return false; | 193 return false; |
172 } | 194 } |
173 | 195 |
174 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 196 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); |
175 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 197 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); |
176 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | 198 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
177 | 199 |
178 if (VAAPIVersionLessThan(0, 34)) { | 200 if (VAAPIVersionLessThan(0, 34)) { |
(...skipping 12 matching lines...) Expand all Loading... | |
191 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); | 213 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); |
192 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { | 214 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { |
193 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; | 215 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; |
194 return false; | 216 return false; |
195 } | 217 } |
196 | 218 |
197 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); | 219 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); |
198 | 220 |
199 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); | 221 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); |
200 if (va_profile == VAProfileNone) { | 222 if (va_profile == VAProfileNone) { |
201 DVLOG(1) << "Unsupported profile"; | 223 DVLOG(1) << "Unsupported profile : " << profile; |
202 return false; | 224 return false; |
203 } | 225 } |
204 | 226 |
205 // Query the driver for supported entrypoints. | 227 // Query the driver for supported entrypoints. |
206 int max_entrypoints = vaMaxNumEntrypoints(va_display_); | 228 int max_entrypoints = vaMaxNumEntrypoints(va_display_); |
207 std::vector<VAEntrypoint> supported_entrypoints( | 229 std::vector<VAEntrypoint> supported_entrypoints( |
208 base::checked_cast<size_t>(max_entrypoints)); | 230 base::checked_cast<size_t>(max_entrypoints)); |
209 | 231 |
210 int num_supported_entrypoints; | 232 int num_supported_entrypoints; |
211 va_res = vaQueryConfigEntrypoints(va_display_, | 233 va_res = vaQueryConfigEntrypoints(va_display_, |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 | 311 |
290 va_config_id_ = VA_INVALID_ID; | 312 va_config_id_ = VA_INVALID_ID; |
291 va_display_ = NULL; | 313 va_display_ = NULL; |
292 } | 314 } |
293 | 315 |
294 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { | 316 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { |
295 return (major_version_ < major) || | 317 return (major_version_ < major) || |
296 (major_version_ == major && minor_version_ < minor); | 318 (major_version_ == major && minor_version_ < minor); |
297 } | 319 } |
298 | 320 |
299 bool VaapiWrapper::CreateSurfaces(gfx::Size size, | 321 bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, |
300 size_t num_surfaces, | 322 size_t num_surfaces, |
301 std::vector<VASurfaceID>* va_surfaces) { | 323 std::vector<VASurfaceID>* va_surfaces) { |
302 base::AutoLock auto_lock(va_lock_); | 324 base::AutoLock auto_lock(va_lock_); |
303 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; | 325 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; |
304 | 326 |
305 DCHECK(va_surfaces->empty()); | 327 DCHECK(va_surfaces->empty()); |
306 DCHECK(va_surface_ids_.empty()); | 328 DCHECK(va_surface_ids_.empty()); |
307 va_surface_ids_.resize(num_surfaces); | 329 va_surface_ids_.resize(num_surfaces); |
308 | 330 |
309 // Allocate surfaces in driver. | 331 // Allocate surfaces in driver. |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
499 | 521 |
500 return true; | 522 return true; |
501 } | 523 } |
502 | 524 |
503 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { | 525 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { |
504 bool result = Execute(va_surface_id); | 526 bool result = Execute(va_surface_id); |
505 DestroyPendingBuffers(); | 527 DestroyPendingBuffers(); |
506 return result; | 528 return result; |
507 } | 529 } |
508 | 530 |
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, | 531 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, |
529 VAImage* image, | 532 VAImage* image, |
530 void** mem) { | 533 void** mem) { |
531 base::AutoLock auto_lock(va_lock_); | 534 base::AutoLock auto_lock(va_lock_); |
532 | 535 |
533 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 536 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
534 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 537 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
535 | 538 |
536 // Derive a VAImage from the VASurface | 539 // Derive a VAImage from the VASurface |
537 va_res = vaDeriveImage(va_display_, va_surface_id, image); | 540 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"); | 661 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
659 | 662 |
660 va_res = vaDestroyBuffer(va_display_, buffer_id); | 663 va_res = vaDestroyBuffer(va_display_, buffer_id); |
661 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 664 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
662 | 665 |
663 DCHECK(coded_buffers_.erase(buffer_id)); | 666 DCHECK(coded_buffers_.erase(buffer_id)); |
664 | 667 |
665 return buffer_segment == NULL; | 668 return buffer_segment == NULL; |
666 } | 669 } |
667 | 670 |
671 VADisplay VaapiWrapper::GetDisplay() { | |
672 return va_display_; | |
673 } | |
674 | |
675 | |
668 // static | 676 // static |
669 bool VaapiWrapper::PostSandboxInitialization() { | 677 bool VaapiWrapper::PostSandboxInitialization() { |
670 StubPathMap paths; | 678 StubPathMap paths; |
671 paths[kModuleVa].push_back(kVaLib); | 679 |
680 paths[kModuleVa].push_back("libva.so.1"); | |
681 | |
682 #if defined(USE_X11) | |
683 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | |
684 #else | |
685 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | |
686 #endif | |
672 | 687 |
673 return InitializeStubs(paths); | 688 return InitializeStubs(paths); |
674 } | 689 } |
675 | 690 |
676 } // namespace content | 691 } // namespace content |
OLD | NEW |