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/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...) Expand all 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 namespace { | |
| 61 | |
| 62 uint32_t BufferFormatToVAFourCC(gfx::BufferFormat fmt) { | |
| 63 switch (fmt) { | |
| 64 case gfx::BufferFormat::BGRX_8888: | |
| 65 return VA_FOURCC_BGRX; | |
| 66 case gfx::BufferFormat::UYVY_422: | |
| 67 return VA_FOURCC_UYVY; | |
| 68 default: | |
| 69 NOTREACHED(); | |
| 70 return 0; | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt) { | |
| 75 switch (fmt) { | |
| 76 case gfx::BufferFormat::UYVY_422: | |
| 77 return VA_RT_FORMAT_YUV422; | |
| 78 case gfx::BufferFormat::BGRX_8888: | |
| 79 return VA_RT_FORMAT_RGB32; | |
| 80 default: | |
| 81 NOTREACHED(); | |
| 82 return 0; | |
| 83 } | |
| 84 } | |
| 85 | |
| 86 } // namespace | |
| 87 | |
| 59 namespace content { | 88 namespace content { |
| 60 | 89 |
| 61 // Maximum framerate of encoded profile. This value is an arbitary limit | 90 // Maximum framerate of encoded profile. This value is an arbitary limit |
| 62 // and not taken from HW documentation. | 91 // and not taken from HW documentation. |
| 63 const int kMaxEncoderFramerate = 30; | 92 const int kMaxEncoderFramerate = 30; |
| 64 | 93 |
| 65 base::LazyInstance<VaapiWrapper::VADisplayState> | 94 base::LazyInstance<VaapiWrapper::VADisplayState> |
| 66 VaapiWrapper::va_display_state_ = LAZY_INSTANCE_INITIALIZER; | 95 VaapiWrapper::va_display_state_ = LAZY_INSTANCE_INITIALIZER; |
| 67 | 96 |
| 68 base::LazyInstance<VaapiWrapper::LazyProfileInfos> | 97 base::LazyInstance<VaapiWrapper::LazyProfileInfos> |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 | 169 |
| 141 VaapiWrapper::~VaapiWrapper() { | 170 VaapiWrapper::~VaapiWrapper() { |
| 142 DestroyPendingBuffers(); | 171 DestroyPendingBuffers(); |
| 143 DestroyCodedBuffers(); | 172 DestroyCodedBuffers(); |
| 144 DestroySurfaces(); | 173 DestroySurfaces(); |
| 145 DeinitializeVpp(); | 174 DeinitializeVpp(); |
| 146 Deinitialize(); | 175 Deinitialize(); |
| 147 } | 176 } |
| 148 | 177 |
| 149 // static | 178 // static |
| 150 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 179 scoped_refptr<VaapiWrapper> VaapiWrapper::Create( |
| 151 CodecMode mode, | 180 CodecMode mode, |
| 152 VAProfile va_profile, | 181 VAProfile va_profile, |
| 153 const base::Closure& report_error_to_uma_cb) { | 182 const base::Closure& report_error_to_uma_cb) { |
| 154 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile)) { | 183 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile)) { |
| 155 DVLOG(1) << "Unsupported va_profile: " << va_profile; | 184 DVLOG(1) << "Unsupported va_profile: " << va_profile; |
| 156 return nullptr; | 185 return nullptr; |
| 157 } | 186 } |
| 158 | 187 |
| 159 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 188 scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
| 160 if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) { | 189 if (vaapi_wrapper->VaInitialize(report_error_to_uma_cb)) { |
| 161 if (vaapi_wrapper->Initialize(mode, va_profile)) | 190 if (vaapi_wrapper->Initialize(mode, va_profile)) |
| 162 return vaapi_wrapper.Pass(); | 191 return vaapi_wrapper; |
| 163 } | 192 } |
| 164 LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " << va_profile; | 193 LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " << va_profile; |
| 165 return nullptr; | 194 return nullptr; |
| 166 } | 195 } |
| 167 | 196 |
| 168 // static | 197 // static |
| 169 scoped_ptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( | 198 scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( |
| 170 CodecMode mode, | 199 CodecMode mode, |
| 171 media::VideoCodecProfile profile, | 200 media::VideoCodecProfile profile, |
| 172 const base::Closure& report_error_to_uma_cb) { | 201 const base::Closure& report_error_to_uma_cb) { |
| 173 VAProfile va_profile = ProfileToVAProfile(profile, mode); | 202 VAProfile va_profile = ProfileToVAProfile(profile, mode); |
| 174 scoped_ptr<VaapiWrapper> vaapi_wrapper = | 203 scoped_refptr<VaapiWrapper> vaapi_wrapper = |
| 175 Create(mode, va_profile, report_error_to_uma_cb); | 204 Create(mode, va_profile, report_error_to_uma_cb); |
| 176 return vaapi_wrapper.Pass(); | 205 return vaapi_wrapper; |
| 177 } | 206 } |
| 178 | 207 |
| 179 // static | 208 // static |
| 180 media::VideoEncodeAccelerator::SupportedProfiles | 209 media::VideoEncodeAccelerator::SupportedProfiles |
| 181 VaapiWrapper::GetSupportedEncodeProfiles() { | 210 VaapiWrapper::GetSupportedEncodeProfiles() { |
| 182 media::VideoEncodeAccelerator::SupportedProfiles profiles; | 211 media::VideoEncodeAccelerator::SupportedProfiles profiles; |
| 183 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 212 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 184 if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode)) | 213 if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode)) |
| 185 return profiles; | 214 return profiles; |
| 186 | 215 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 // (which in practice is true for a great majority of cases). | 298 // (which in practice is true for a great majority of cases). |
| 270 if (profile_infos_.Get().IsProfileSupported( | 299 if (profile_infos_.Get().IsProfileSupported( |
| 271 mode, VAProfileH264ConstrainedBaseline)) { | 300 mode, VAProfileH264ConstrainedBaseline)) { |
| 272 va_profile = VAProfileH264ConstrainedBaseline; | 301 va_profile = VAProfileH264ConstrainedBaseline; |
| 273 DVLOG(1) << "Fall back to constrained baseline profile."; | 302 DVLOG(1) << "Fall back to constrained baseline profile."; |
| 274 } | 303 } |
| 275 } | 304 } |
| 276 return va_profile; | 305 return va_profile; |
| 277 } | 306 } |
| 278 | 307 |
| 308 scoped_refptr<ui::NativePixmap> VaapiWrapper::ProcessPixmap( | |
| 309 const scoped_refptr<ui::NativePixmap>& source_pixmap, | |
| 310 const gfx::Size& target_size, | |
| 311 gfx::BufferFormat target_format) { | |
| 312 scoped_refptr<VASurface> va_surface = | |
| 313 CreateVASurfaceForPixmap(source_pixmap, source_pixmap->size()); | |
|
kalyank
2015/11/23 17:51:07
Now, we create va surface of original pixmap, only
william.xie1
2015/11/24 06:19:39
Dear Kalyan, I measured the cost, it is quit light
kalyank
2015/11/24 23:00:24
MiniGBM doesn't use dri infrastructure internally
| |
| 314 if (!va_surface) { | |
| 315 LOG(ERROR) << "Failed creating VA Surface for source_pixmap"; | |
| 316 return nullptr; | |
| 317 } | |
| 318 | |
| 319 scoped_refptr<ui::NativePixmap> processed_pixmap = | |
| 320 CreateNativePixmap(target_size, target_format); | |
| 321 if (!processed_pixmap) { | |
| 322 LOG(ERROR) << "Failed creating an Ozone NativePixmap for processing"; | |
| 323 return nullptr; | |
| 324 } | |
| 325 | |
| 326 scoped_refptr<VASurface> processed_va_surface = | |
| 327 CreateVASurfaceForPixmap(processed_pixmap, target_size); | |
| 328 if (!processed_va_surface) { | |
| 329 LOG(ERROR) << "Failed creating processed VA Surface for pixmap"; | |
| 330 return nullptr; | |
| 331 } | |
| 332 | |
| 333 DCHECK(processed_pixmap); | |
| 334 if (!BlitSurface(va_surface, processed_va_surface)) { | |
| 335 LOG(ERROR) << "Failed scaling NativePixmap"; | |
| 336 return nullptr; | |
| 337 } | |
| 338 | |
| 339 return processed_pixmap; | |
| 340 } | |
| 341 | |
| 342 scoped_refptr<ui::NativePixmap> VaapiWrapper::CreateNativePixmap( | |
| 343 gfx::Size size, | |
| 344 gfx::BufferFormat format) { | |
| 345 ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); | |
| 346 ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); | |
| 347 | |
| 348 // Create a buffer from Ozone. | |
| 349 return factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, format, | |
| 350 gfx::BufferUsage::SCANOUT); | |
| 351 } | |
| 352 | |
| 279 std::vector<VaapiWrapper::ProfileInfo> | 353 std::vector<VaapiWrapper::ProfileInfo> |
| 280 VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) { | 354 VaapiWrapper::GetSupportedProfileInfosForCodecModeInternal(CodecMode mode) { |
| 281 std::vector<ProfileInfo> supported_profile_infos; | 355 std::vector<ProfileInfo> supported_profile_infos; |
| 282 std::vector<VAProfile> va_profiles; | 356 std::vector<VAProfile> va_profiles; |
| 283 if (!GetSupportedVaProfiles(&va_profiles)) | 357 if (!GetSupportedVaProfiles(&va_profiles)) |
| 284 return supported_profile_infos; | 358 return supported_profile_infos; |
| 285 | 359 |
| 286 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | 360 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); |
| 287 VAEntrypoint entrypoint = | 361 VAEntrypoint entrypoint = |
| 288 (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); | 362 (mode == kEncode ? VAEntrypointEncSlice: VAEntrypointVLD); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 586 // This is safe to use Unretained() here, because the VDA takes care | 660 // This is safe to use Unretained() here, because the VDA takes care |
| 587 // of the destruction order. All the surfaces will be destroyed | 661 // of the destruction order. All the surfaces will be destroyed |
| 588 // before VaapiWrapper. | 662 // before VaapiWrapper. |
| 589 va_surface = new VASurface( | 663 va_surface = new VASurface( |
| 590 va_surface_id, size, va_format, | 664 va_surface_id, size, va_format, |
| 591 base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this))); | 665 base::Bind(&VaapiWrapper::DestroyUnownedSurface, base::Unretained(this))); |
| 592 | 666 |
| 593 return va_surface; | 667 return va_surface; |
| 594 } | 668 } |
| 595 | 669 |
| 670 scoped_refptr<VASurface> VaapiWrapper::CreateVASurfaceForPixmap( | |
| 671 const scoped_refptr<ui::NativePixmap>& pixmap, | |
| 672 const gfx::Size& pixmap_size) { | |
| 673 // Get the dmabuf of the created buffer. | |
| 674 int dmabuf_fd = pixmap->GetDmaBufFd(); | |
| 675 if (dmabuf_fd < 0) { | |
| 676 LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap"; | |
| 677 return nullptr; | |
| 678 } | |
| 679 int dmabuf_pitch = pixmap->GetDmaBufPitch(); | |
| 680 | |
| 681 // Create a VASurface out of the created buffer using the dmabuf. | |
| 682 VASurfaceAttribExternalBuffers va_attrib_extbuf; | |
| 683 memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf)); | |
| 684 va_attrib_extbuf.pixel_format = | |
| 685 BufferFormatToVAFourCC(pixmap->GetBufferFormat()); | |
| 686 va_attrib_extbuf.width = pixmap_size.width(); | |
| 687 va_attrib_extbuf.height = pixmap_size.height(); | |
| 688 va_attrib_extbuf.data_size = pixmap_size.height() * dmabuf_pitch; | |
| 689 va_attrib_extbuf.num_planes = 1; | |
| 690 va_attrib_extbuf.pitches[0] = dmabuf_pitch; | |
| 691 va_attrib_extbuf.offsets[0] = 0; | |
| 692 va_attrib_extbuf.buffers = reinterpret_cast<unsigned long*>(&dmabuf_fd); | |
| 693 va_attrib_extbuf.num_buffers = 1; | |
| 694 va_attrib_extbuf.flags = 0; | |
| 695 va_attrib_extbuf.private_data = NULL; | |
| 696 | |
| 697 std::vector<VASurfaceAttrib> va_attribs; | |
| 698 va_attribs.resize(2); | |
| 699 | |
| 700 va_attribs[0].type = VASurfaceAttribMemoryType; | |
| 701 va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; | |
| 702 va_attribs[0].value.type = VAGenericValueTypeInteger; | |
| 703 va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; | |
| 704 | |
| 705 va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor; | |
| 706 va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; | |
| 707 va_attribs[1].value.type = VAGenericValueTypePointer; | |
| 708 va_attribs[1].value.value.p = &va_attrib_extbuf; | |
| 709 | |
| 710 scoped_refptr<VASurface> va_surface = | |
| 711 CreateUnownedSurface(BufferFormatToVARTFormat(pixmap->GetBufferFormat()), | |
| 712 pixmap_size, va_attribs); | |
| 713 if (!va_surface) { | |
| 714 LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap"; | |
| 715 return nullptr; | |
| 716 } | |
| 717 | |
| 718 return va_surface; | |
| 719 } | |
| 720 | |
| 596 void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { | 721 void VaapiWrapper::DestroyUnownedSurface(VASurfaceID va_surface_id) { |
| 597 base::AutoLock auto_lock(*va_lock_); | 722 base::AutoLock auto_lock(*va_lock_); |
| 598 | 723 |
| 599 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); | 724 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_id, 1); |
| 600 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); | 725 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces on surface failed"); |
| 601 } | 726 } |
| 602 | 727 |
| 603 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, | 728 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, |
| 604 size_t size, | 729 size_t size, |
| 605 void* buffer) { | 730 void* buffer) { |
| (...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1064 #elif defined(USE_OZONE) | 1189 #elif defined(USE_OZONE) |
| 1065 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | 1190 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
| 1066 #endif | 1191 #endif |
| 1067 | 1192 |
| 1068 return InitializeStubs(paths); | 1193 return InitializeStubs(paths); |
| 1069 } | 1194 } |
| 1070 | 1195 |
| 1071 VaapiWrapper::LazyProfileInfos::LazyProfileInfos() { | 1196 VaapiWrapper::LazyProfileInfos::LazyProfileInfos() { |
| 1072 static_assert(arraysize(supported_profiles_) == kCodecModeMax, | 1197 static_assert(arraysize(supported_profiles_) == kCodecModeMax, |
| 1073 "The array size of supported profile is incorrect."); | 1198 "The array size of supported profile is incorrect."); |
| 1074 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 1199 scoped_refptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
| 1075 if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing))) | 1200 if (!vaapi_wrapper->VaInitialize(base::Bind(&base::DoNothing))) |
| 1076 return; | 1201 return; |
| 1077 for (size_t i = 0; i < kCodecModeMax; ++i) { | 1202 for (size_t i = 0; i < kCodecModeMax; ++i) { |
| 1078 supported_profiles_[i] = | 1203 supported_profiles_[i] = |
| 1079 vaapi_wrapper->GetSupportedProfileInfosForCodecModeInternal( | 1204 vaapi_wrapper->GetSupportedProfileInfosForCodecModeInternal( |
| 1080 static_cast<CodecMode>(i)); | 1205 static_cast<CodecMode>(i)); |
| 1081 } | 1206 } |
| 1082 } | 1207 } |
| 1083 | 1208 |
| 1084 VaapiWrapper::LazyProfileInfos::~LazyProfileInfos() { | 1209 VaapiWrapper::LazyProfileInfos::~LazyProfileInfos() { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1159 drm_fd_.reset(HANDLE_EINTR(dup(fd))); | 1284 drm_fd_.reset(HANDLE_EINTR(dup(fd))); |
| 1160 } | 1285 } |
| 1161 #endif // USE_OZONE | 1286 #endif // USE_OZONE |
| 1162 | 1287 |
| 1163 bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { | 1288 bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { |
| 1164 return (major_version_ < major) || | 1289 return (major_version_ < major) || |
| 1165 (major_version_ == major && minor_version_ < minor); | 1290 (major_version_ == major && minor_version_ < minor); |
| 1166 } | 1291 } |
| 1167 | 1292 |
| 1168 } // namespace content | 1293 } // namespace content |
| OLD | NEW |