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