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/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/numerics/safe_conversions.h" | 13 #include "base/numerics/safe_conversions.h" |
14 #include "base/sys_info.h" | 14 #include "base/sys_info.h" |
15 // Auto-generated for dlopen libva libraries | 15 // Auto-generated for dlopen libva libraries |
16 #include "content/common/gpu/media/va_stubs.h" | 16 #include "content/common/gpu/media/va_stubs.h" |
17 #include "content/common/gpu/media/vaapi_picture.h" | 17 #include "content/common/gpu/media/vaapi_picture.h" |
18 #include "content/public/common/content_switches.h" | 18 #include "content/public/common/content_switches.h" |
19 #include "third_party/libyuv/include/libyuv.h" | 19 #include "third_party/libyuv/include/libyuv.h" |
20 #include "ui/gl/gl_bindings.h" | 20 #include "ui/gl/gl_bindings.h" |
21 #if defined(USE_X11) | 21 #if defined(USE_X11) |
22 #include "ui/gfx/x/x11_types.h" | 22 #include "ui/gfx/x/x11_types.h" |
23 #elif defined(USE_OZONE) | 23 #elif defined(USE_OZONE) |
24 #include "third_party/libva/va/drm/va_drm.h" | 24 #include "third_party/libva/va/drm/va_drm.h" |
| 25 #include "third_party/libva/va/va_drmcommon.h" |
25 #include "ui/ozone/public/ozone_platform.h" | 26 #include "ui/ozone/public/ozone_platform.h" |
26 #include "ui/ozone/public/surface_factory_ozone.h" | 27 #include "ui/ozone/public/surface_factory_ozone.h" |
27 #endif // USE_X11 | 28 #endif // USE_X11 |
28 | 29 |
29 using content_common_gpu_media::kModuleVa; | 30 using content_common_gpu_media::kModuleVa; |
30 #if defined(USE_X11) | 31 #if defined(USE_X11) |
31 using content_common_gpu_media::kModuleVa_x11; | 32 using content_common_gpu_media::kModuleVa_x11; |
32 #elif defined(USE_OZONE) | 33 #elif defined(USE_OZONE) |
33 using content_common_gpu_media::kModuleVa_drm; | 34 using content_common_gpu_media::kModuleVa_drm; |
34 #endif // USE_X11 | 35 #endif // USE_X11 |
(...skipping 14 matching lines...) Loading... |
49 } while (0) | 50 } while (0) |
50 | 51 |
51 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ | 52 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ |
52 do { \ | 53 do { \ |
53 if ((va_error) != VA_STATUS_SUCCESS) { \ | 54 if ((va_error) != VA_STATUS_SUCCESS) { \ |
54 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ | 55 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ |
55 return (ret); \ | 56 return (ret); \ |
56 } \ | 57 } \ |
57 } while (0) | 58 } while (0) |
58 | 59 |
| 60 #if defined(USE_OZONE) |
| 61 namespace { |
| 62 |
| 63 uint32_t BufferFormatToVAFourCC(gfx::BufferFormat fmt) { |
| 64 switch (fmt) { |
| 65 case gfx::BufferFormat::BGRX_8888: |
| 66 return VA_FOURCC_BGRX; |
| 67 case gfx::BufferFormat::UYVY_422: |
| 68 return VA_FOURCC_UYVY; |
| 69 default: |
| 70 NOTREACHED(); |
| 71 return 0; |
| 72 } |
| 73 } |
| 74 |
| 75 uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt) { |
| 76 switch (fmt) { |
| 77 case gfx::BufferFormat::UYVY_422: |
| 78 return VA_RT_FORMAT_YUV422; |
| 79 case gfx::BufferFormat::BGRX_8888: |
| 80 return VA_RT_FORMAT_RGB32; |
| 81 default: |
| 82 NOTREACHED(); |
| 83 return 0; |
| 84 } |
| 85 } |
| 86 |
| 87 } // namespace |
| 88 #endif |
| 89 |
59 namespace content { | 90 namespace content { |
60 | 91 |
61 // Maximum framerate of encoded profile. This value is an arbitary limit | 92 // Maximum framerate of encoded profile. This value is an arbitary limit |
62 // and not taken from HW documentation. | 93 // and not taken from HW documentation. |
63 const int kMaxEncoderFramerate = 30; | 94 const int kMaxEncoderFramerate = 30; |
64 | 95 |
65 base::LazyInstance<VaapiWrapper::VADisplayState> | 96 base::LazyInstance<VaapiWrapper::VADisplayState> |
66 VaapiWrapper::va_display_state_ = LAZY_INSTANCE_INITIALIZER; | 97 VaapiWrapper::va_display_state_ = LAZY_INSTANCE_INITIALIZER; |
67 | 98 |
68 base::LazyInstance<VaapiWrapper::LazyProfileInfos> | 99 base::LazyInstance<VaapiWrapper::LazyProfileInfos> |
(...skipping 71 matching lines...) Loading... |
140 | 171 |
141 VaapiWrapper::~VaapiWrapper() { | 172 VaapiWrapper::~VaapiWrapper() { |
142 DestroyPendingBuffers(); | 173 DestroyPendingBuffers(); |
143 DestroyCodedBuffers(); | 174 DestroyCodedBuffers(); |
144 DestroySurfaces(); | 175 DestroySurfaces(); |
145 DeinitializeVpp(); | 176 DeinitializeVpp(); |
146 Deinitialize(); | 177 Deinitialize(); |
147 } | 178 } |
148 | 179 |
149 // static | 180 // static |
150 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 181 scoped_refptr<VaapiWrapper> VaapiWrapper::Create( |
151 CodecMode mode, | 182 CodecMode mode, |
152 VAProfile va_profile, | 183 VAProfile va_profile, |
153 const base::Closure& report_error_to_uma_cb) { | 184 const base::Closure& report_error_to_uma_cb) { |
154 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile)) { | 185 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile)) { |
155 DVLOG(1) << "Unsupported va_profile: " << va_profile; | 186 DVLOG(1) << "Unsupported va_profile: " << va_profile; |
156 return nullptr; | 187 return nullptr; |
157 } | 188 } |
158 | 189 |
159 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 190 scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
160 if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) { | 191 if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) { |
161 if (vaapi_wrapper->Initialize(mode, va_profile)) | 192 if (vaapi_wrapper->Initialize(mode, va_profile)) |
162 return vaapi_wrapper.Pass(); | 193 return vaapi_wrapper; |
163 } | 194 } |
164 LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " << va_profile; | 195 LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " << va_profile; |
165 return nullptr; | 196 return nullptr; |
166 } | 197 } |
167 | 198 |
168 // static | 199 // static |
169 scoped_ptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( | 200 scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( |
170 CodecMode mode, | 201 CodecMode mode, |
171 media::VideoCodecProfile profile, | 202 media::VideoCodecProfile profile, |
172 const base::Closure& report_error_to_uma_cb) { | 203 const base::Closure& report_error_to_uma_cb) { |
173 VAProfile va_profile = ProfileToVAProfile(profile, mode); | 204 VAProfile va_profile = ProfileToVAProfile(profile, mode); |
174 scoped_ptr<VaapiWrapper> vaapi_wrapper = | 205 scoped_refptr<VaapiWrapper> vaapi_wrapper = |
175 Create(mode, va_profile, report_error_to_uma_cb); | 206 Create(mode, va_profile, report_error_to_uma_cb); |
176 return vaapi_wrapper.Pass(); | 207 return vaapi_wrapper; |
177 } | 208 } |
178 | 209 |
179 // static | 210 // static |
180 media::VideoEncodeAccelerator::SupportedProfiles | 211 media::VideoEncodeAccelerator::SupportedProfiles |
181 VaapiWrapper::GetSupportedEncodeProfiles() { | 212 VaapiWrapper::GetSupportedEncodeProfiles() { |
182 media::VideoEncodeAccelerator::SupportedProfiles profiles; | 213 media::VideoEncodeAccelerator::SupportedProfiles profiles; |
183 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 214 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
184 if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode)) | 215 if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode)) |
185 return profiles; | 216 return profiles; |
186 | 217 |
(...skipping 399 matching lines...) Loading... |
586 // This is safe to use Unretained() here, because the VDA takes care | 617 // This is safe to use Unretained() here, because the VDA takes care |
587 // of the destruction order. All the surfaces will be destroyed | 618 // of the destruction order. All the surfaces will be destroyed |
588 // before VaapiWrapper. | 619 // before VaapiWrapper. |
589 va_surface = new VASurface( | 620 va_surface = new VASurface( |
590 va_surface_id, size, va_format, | 621 va_surface_id, size, va_format, |
591 base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this))); | 622 base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this))); |
592 | 623 |
593 return va_surface; | 624 return va_surface; |
594 } | 625 } |
595 | 626 |
| 627 #if defined(USE_OZONE) |
| 628 scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap( |
| 629 const scoped_refptr<ui::NativePixmap>& pixmap) { |
| 630 // Get the dmabuf of the created buffer. |
| 631 int dmabuf_fd = pixmap->GetDmaBufFd(); |
| 632 if (dmabuf_fd < 0) { |
| 633 LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap"; |
| 634 return nullptr; |
| 635 } |
| 636 int dmabuf_pitch = pixmap->GetDmaBufPitch(); |
| 637 gfx::Size pixmap_size = pixmap->GetBufferSize(); |
| 638 |
| 639 // Create a VASurface out of the created buffer using the dmabuf. |
| 640 VASurfaceAttribExternalBuffers va_attrib_extbuf; |
| 641 memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf)); |
| 642 va_attrib_extbuf.pixel_format = |
| 643 BufferFormatToVAFourCC(pixmap->GetBufferFormat()); |
| 644 va_attrib_extbuf.width = pixmap_size.width(); |
| 645 va_attrib_extbuf.height = pixmap_size.height(); |
| 646 va_attrib_extbuf.data_size = pixmap_size.height() * dmabuf_pitch; |
| 647 va_attrib_extbuf.num_planes = 1; |
| 648 va_attrib_extbuf.pitches[0] = dmabuf_pitch; |
| 649 va_attrib_extbuf.offsets[0] = 0; |
| 650 va_attrib_extbuf.buffers = reinterpret_cast<unsigned long*>(&dmabuf_fd); |
| 651 va_attrib_extbuf.num_buffers = 1; |
| 652 va_attrib_extbuf.flags = 0; |
| 653 va_attrib_extbuf.private_data = NULL; |
| 654 |
| 655 std::vector<VASurfaceAttrib> va_attribs; |
| 656 va_attribs.resize(2); |
| 657 |
| 658 va_attribs[0].type = VASurfaceAttribMemoryType; |
| 659 va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; |
| 660 va_attribs[0].value.type = VAGenericValueTypeInteger; |
| 661 va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; |
| 662 |
| 663 va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor; |
| 664 va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; |
| 665 va_attribs[1].value.type = VAGenericValueTypePointer; |
| 666 va_attribs[1].value.value.p = &va_attrib_extbuf; |
| 667 |
| 668 scoped_refptr<VASurface> va_surface = |
| 669 CreateUnownedSurface(BufferFormatToVARTFormat(pixmap->GetBufferFormat()), |
| 670 pixmap_size, va_attribs); |
| 671 if (!va_surface) { |
| 672 LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap"; |
| 673 return nullptr; |
| 674 } |
| 675 |
| 676 return va_surface; |
| 677 } |
| 678 |
| 679 bool VaapiWrapper::ProcessPixmap( |
| 680 const scoped_refptr<ui::NativePixmap>& source_pixmap, |
| 681 scoped_refptr<ui::NativePixmap> target_pixmap) { |
| 682 scoped_refptr<VASurface> va_surface = CreateVASurfaceForPixmap(source_pixmap); |
| 683 if (!va_surface) { |
| 684 LOG(ERROR) << "Failed creating VA Surface for source_pixmap"; |
| 685 return false; |
| 686 } |
| 687 |
| 688 scoped_refptr<VASurface> processed_va_surface = |
| 689 CreateVASurfaceForPixmap(target_pixmap); |
| 690 if (!processed_va_surface) { |
| 691 LOG(ERROR) << "Failed creating processed VA Surface for pixmap"; |
| 692 return false; |
| 693 } |
| 694 |
| 695 if (!BlitSurface(va_surface, processed_va_surface)) { |
| 696 LOG(ERROR) << "Failed scaling NativePixmap"; |
| 697 return false; |
| 698 } |
| 699 |
| 700 return true; |
| 701 } |
| 702 |
| 703 #endif |
| 704 |
596 void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { | 705 void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { |
597 base::AutoLock auto_lock(*va_lock_); | 706 base::AutoLock auto_lock(*va_lock_); |
598 | 707 |
599 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); | 708 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); |
600 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); | 709 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); |
601 } | 710 } |
602 | 711 |
603 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, | 712 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, |
604 size_t size, | 713 size_t size, |
605 void* buffer) { | 714 void* buffer) { |
(...skipping 458 matching lines...) Loading... |
1064 #elif defined(USE_OZONE) | 1173 #elif defined(USE_OZONE) |
1065 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | 1174 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
1066 #endif | 1175 #endif |
1067 | 1176 |
1068 return InitializeStubs(paths); | 1177 return InitializeStubs(paths); |
1069 } | 1178 } |
1070 | 1179 |
1071 VaapiWrapper::LazyProfileInfos::LazyProfileInfos() { | 1180 VaapiWrapper::LazyProfileInfos::LazyProfileInfos() { |
1072 static_assert(arraysize(supported_profiles_) == kCodecModeMax, | 1181 static_assert(arraysize(supported_profiles_) == kCodecModeMax, |
1073 "The array size of supported profile is incorrect."); | 1182 "The array size of supported profile is incorrect."); |
1074 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 1183 scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
1075 if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing))) | 1184 if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing))) |
1076 return; | 1185 return; |
1077 for (size_t i = 0; i < kCodecModeMax; ++i) { | 1186 for (size_t i = 0; i < kCodecModeMax; ++i) { |
1078 supported_profiles_[i] = | 1187 supported_profiles_[i] = |
1079 vaapi_wrapper->GetSupportedProfileInfosForCodecModeInternal( | 1188 vaapi_wrapper->GetSupportedProfileInfosForCodecModeInternal( |
1080 static_cast<CodecMode>(i)); | 1189 static_cast<CodecMode>(i)); |
1081 } | 1190 } |
1082 } | 1191 } |
1083 | 1192 |
1084 VaapiWrapper::LazyProfileInfos::~LazyProfileInfos() { | 1193 VaapiWrapper::LazyProfileInfos::~LazyProfileInfos() { |
(...skipping 74 matching lines...) Loading... |
1159 drm_fd_.reset(HANDLE_EINTR(dup(fd))); | 1268 drm_fd_.reset(HANDLE_EINTR(dup(fd))); |
1160 } | 1269 } |
1161 #endif // USE_OZONE | 1270 #endif // USE_OZONE |
1162 | 1271 |
1163 bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { | 1272 bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { |
1164 return (major_version_ < major) || | 1273 return (major_version_ < major) || |
1165 (major_version_ == major && minor_version_ < minor); | 1274 (major_version_ == major && minor_version_ < minor); |
1166 } | 1275 } |
1167 | 1276 |
1168 } // namespace content | 1277 } // namespace content |
OLD | NEW |