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() { |
piman
2014/12/22 19:21:52
Can you add a DCHECK that this is called on the ma
llandwerlin-old
2014/12/22 23:36:42
All the pictures are owned by VaapiVideoDecodeAcce
| |
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 |
599 #if defined(USE_X11) | |
596 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, | 600 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, |
597 Pixmap x_pixmap, | 601 Pixmap x_pixmap, |
598 gfx::Size dest_size) { | 602 gfx::Size dest_size) { |
599 base::AutoLock auto_lock(va_lock_); | 603 base::AutoLock auto_lock(va_lock_); |
600 | 604 |
601 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 605 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
602 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 606 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
603 | 607 |
604 // Put the data into an X Pixmap. | 608 // Put the data into an X Pixmap. |
605 va_res = vaPutSurface(va_display_, | 609 va_res = vaPutSurface(va_display_, |
606 va_surface_id, | 610 va_surface_id, |
607 x_pixmap, | 611 x_pixmap, |
608 0, 0, dest_size.width(), dest_size.height(), | 612 0, 0, dest_size.width(), dest_size.height(), |
609 0, 0, dest_size.width(), dest_size.height(), | 613 0, 0, dest_size.width(), dest_size.height(), |
610 NULL, 0, 0); | 614 NULL, 0, 0); |
611 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); | 615 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); |
612 return true; | 616 return true; |
613 } | 617 } |
618 #endif // USE_X11 | |
614 | 619 |
615 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, | 620 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, |
616 VAImage* image, | 621 VAImage* image, |
617 void** mem) { | 622 void** mem) { |
618 base::AutoLock auto_lock(va_lock_); | 623 base::AutoLock auto_lock(va_lock_); |
619 | 624 |
620 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 625 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
621 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 626 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
622 | 627 |
623 // Derive a VAImage from the VASurface | 628 // Derive a VAImage from the VASurface |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
748 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 753 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
749 | 754 |
750 DCHECK(coded_buffers_.erase(buffer_id)); | 755 DCHECK(coded_buffers_.erase(buffer_id)); |
751 | 756 |
752 return buffer_segment == NULL; | 757 return buffer_segment == NULL; |
753 } | 758 } |
754 | 759 |
755 // static | 760 // static |
756 bool VaapiWrapper::PostSandboxInitialization() { | 761 bool VaapiWrapper::PostSandboxInitialization() { |
757 StubPathMap paths; | 762 StubPathMap paths; |
758 paths[kModuleVa].push_back(kVaLib); | 763 |
764 paths[kModuleVa].push_back("libva.so.1"); | |
765 | |
766 #if defined(USE_X11) | |
767 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | |
768 #endif | |
759 | 769 |
760 return InitializeStubs(paths); | 770 return InitializeStubs(paths); |
761 } | 771 } |
762 | 772 |
763 } // namespace content | 773 } // namespace content |
OLD | NEW |