| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "media/gpu/gpu_video_decode_accelerator_factory.h" |
| |
| #include "base/memory/ptr_util.h" |
| #include "gpu/command_buffer/service/gpu_preferences.h" |
| #include "media/base/media_switches.h" |
| #include "media/gpu/gpu_video_accelerator_util.h" |
| #include "media/gpu/media_gpu_export.h" |
| |
| #if defined(OS_WIN) |
| #include "base/win/windows_version.h" |
| #include "media/gpu/d3d11_video_decode_accelerator_win.h" |
| #include "media/gpu/dxva_video_decode_accelerator_win.h" |
| #elif defined(OS_MACOSX) |
| #include "media/gpu/vt_video_decode_accelerator_mac.h" |
| #elif defined(OS_CHROMEOS) |
| #if defined(USE_V4L2_CODEC) |
| #include "media/gpu/v4l2_device.h" |
| #include "media/gpu/v4l2_slice_video_decode_accelerator.h" |
| #include "media/gpu/v4l2_video_decode_accelerator.h" |
| #include "ui/gl/gl_surface_egl.h" |
| #endif |
| #if defined(ARCH_CPU_X86_FAMILY) |
| #include "media/gpu/vaapi_video_decode_accelerator.h" |
| #include "ui/gl/gl_implementation.h" |
| #endif |
| #elif defined(OS_ANDROID) |
| #include "media/gpu/android_video_decode_accelerator.h" |
| #include "media/gpu/avda_codec_allocator.h" |
| #endif |
| |
| namespace media { |
| |
| // static |
| MEDIA_GPU_EXPORT std::unique_ptr<GpuVideoDecodeAcceleratorFactory> |
| GpuVideoDecodeAcceleratorFactory::Create( |
| const GetGLContextCallback& get_gl_context_cb, |
| const MakeGLContextCurrentCallback& make_context_current_cb, |
| const BindGLImageCallback& bind_image_cb) { |
| return base::WrapUnique(new GpuVideoDecodeAcceleratorFactory( |
| get_gl_context_cb, make_context_current_cb, bind_image_cb, |
| GetGLES2DecoderCallback())); |
| } |
| |
| // static |
| MEDIA_GPU_EXPORT std::unique_ptr<GpuVideoDecodeAcceleratorFactory> |
| GpuVideoDecodeAcceleratorFactory::CreateWithGLES2Decoder( |
| const GetGLContextCallback& get_gl_context_cb, |
| const MakeGLContextCurrentCallback& make_context_current_cb, |
| const BindGLImageCallback& bind_image_cb, |
| const GetGLES2DecoderCallback& get_gles2_decoder_cb) { |
| return base::WrapUnique(new GpuVideoDecodeAcceleratorFactory( |
| get_gl_context_cb, make_context_current_cb, bind_image_cb, |
| get_gles2_decoder_cb)); |
| } |
| |
| // static |
| MEDIA_GPU_EXPORT std::unique_ptr<GpuVideoDecodeAcceleratorFactory> |
| GpuVideoDecodeAcceleratorFactory::CreateWithNoGL() { |
| return Create(GetGLContextCallback(), MakeGLContextCurrentCallback(), |
| BindGLImageCallback()); |
| } |
| |
| // static |
| MEDIA_GPU_EXPORT gpu::VideoDecodeAcceleratorCapabilities |
| GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities( |
| const gpu::GpuPreferences& gpu_preferences) { |
| VideoDecodeAccelerator::Capabilities capabilities; |
| if (gpu_preferences.disable_accelerated_video_decode) |
| return gpu::VideoDecodeAcceleratorCapabilities(); |
| |
| // Query VDAs for their capabilities and construct a set of supported |
| // profiles for current platform. This must be done in the same order as in |
| // CreateVDA(), as we currently preserve additional capabilities (such as |
| // resolutions supported) only for the first VDA supporting the given codec |
| // profile (instead of calculating a superset). |
| // TODO(posciak,henryhsu): improve this so that we choose a superset of |
| // resolutions and other supported profile parameters. |
| #if defined(OS_WIN) |
| capabilities.supported_profiles = |
| DXVAVideoDecodeAccelerator::GetSupportedProfiles(gpu_preferences); |
| #elif defined(OS_CHROMEOS) |
| VideoDecodeAccelerator::SupportedProfiles vda_profiles; |
| #if defined(USE_V4L2_CODEC) |
| vda_profiles = V4L2VideoDecodeAccelerator::GetSupportedProfiles(); |
| GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles( |
| vda_profiles, &capabilities.supported_profiles); |
| vda_profiles = V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles(); |
| GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles( |
| vda_profiles, &capabilities.supported_profiles); |
| #endif |
| #if defined(ARCH_CPU_X86_FAMILY) |
| vda_profiles = VaapiVideoDecodeAccelerator::GetSupportedProfiles(); |
| GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles( |
| vda_profiles, &capabilities.supported_profiles); |
| #endif |
| #elif defined(OS_MACOSX) |
| capabilities.supported_profiles = |
| VTVideoDecodeAccelerator::GetSupportedProfiles(); |
| #elif defined(OS_ANDROID) |
| capabilities = |
| AndroidVideoDecodeAccelerator::GetCapabilities(gpu_preferences); |
| #endif |
| return GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeCapabilities( |
| capabilities); |
| } |
| |
| MEDIA_GPU_EXPORT std::unique_ptr<VideoDecodeAccelerator> |
| GpuVideoDecodeAcceleratorFactory::CreateVDA( |
| VideoDecodeAccelerator::Client* client, |
| const VideoDecodeAccelerator::Config& config, |
| const gpu::GpuDriverBugWorkarounds& workarounds, |
| const gpu::GpuPreferences& gpu_preferences) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| |
| if (gpu_preferences.disable_accelerated_video_decode) |
| return nullptr; |
| |
| // Array of Create..VDA() function pointers, potentially usable on current |
| // platform. This list is ordered by priority, from most to least preferred, |
| // if applicable. This list must be in the same order as the querying order |
| // in GetDecoderCapabilities() above. |
| using CreateVDAFp = std::unique_ptr<VideoDecodeAccelerator> ( |
| GpuVideoDecodeAcceleratorFactory::*)(const gpu::GpuDriverBugWorkarounds&, |
| const gpu::GpuPreferences&) const; |
| const CreateVDAFp create_vda_fps[] = { |
| #if defined(OS_WIN) |
| &GpuVideoDecodeAcceleratorFactory::CreateD3D11VDA, |
| &GpuVideoDecodeAcceleratorFactory::CreateDXVAVDA, |
| #endif |
| #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) |
| &GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA, |
| &GpuVideoDecodeAcceleratorFactory::CreateV4L2SVDA, |
| #endif |
| #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
| &GpuVideoDecodeAcceleratorFactory::CreateVaapiVDA, |
| #endif |
| #if defined(OS_MACOSX) |
| &GpuVideoDecodeAcceleratorFactory::CreateVTVDA, |
| #endif |
| #if defined(OS_ANDROID) |
| &GpuVideoDecodeAcceleratorFactory::CreateAndroidVDA, |
| #endif |
| }; |
| |
| std::unique_ptr<VideoDecodeAccelerator> vda; |
| |
| for (const auto& create_vda_function : create_vda_fps) { |
| vda = (this->*create_vda_function)(workarounds, gpu_preferences); |
| if (vda && vda->Initialize(config, client)) |
| return vda; |
| } |
| |
| return nullptr; |
| } |
| |
| #if defined(OS_WIN) |
| std::unique_ptr<VideoDecodeAccelerator> |
| GpuVideoDecodeAcceleratorFactory::CreateD3D11VDA( |
| const gpu::GpuDriverBugWorkarounds& workarounds, |
| const gpu::GpuPreferences& gpu_preferences) const { |
| std::unique_ptr<VideoDecodeAccelerator> decoder; |
| if (!base::FeatureList::IsEnabled(kD3D11VideoDecoding)) |
| return decoder; |
| if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| DVLOG(0) << "Initializing D3D11 HW decoder for windows."; |
| decoder.reset(new D3D11VideoDecodeAccelerator(get_gl_context_cb_, |
| make_context_current_cb_)); |
| } |
| return decoder; |
| } |
| |
| std::unique_ptr<VideoDecodeAccelerator> |
| GpuVideoDecodeAcceleratorFactory::CreateDXVAVDA( |
| const gpu::GpuDriverBugWorkarounds& workarounds, |
| const gpu::GpuPreferences& gpu_preferences) const { |
| std::unique_ptr<VideoDecodeAccelerator> decoder; |
| if (base::win::GetVersion() >= base::win::VERSION_WIN7) { |
| DVLOG(0) << "Initializing DXVA HW decoder for windows."; |
| decoder.reset(new DXVAVideoDecodeAccelerator( |
| get_gl_context_cb_, make_context_current_cb_, bind_image_cb_, |
| workarounds, gpu_preferences)); |
| } |
| return decoder; |
| } |
| #endif |
| |
| #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) |
| std::unique_ptr<VideoDecodeAccelerator> |
| GpuVideoDecodeAcceleratorFactory::CreateV4L2VDA( |
| const gpu::GpuDriverBugWorkarounds& workarounds, |
| const gpu::GpuPreferences& gpu_preferences) const { |
| std::unique_ptr<VideoDecodeAccelerator> decoder; |
| scoped_refptr<V4L2Device> device = V4L2Device::Create(); |
| if (device.get()) { |
| decoder.reset(new V4L2VideoDecodeAccelerator( |
| gl::GLSurfaceEGL::GetHardwareDisplay(), get_gl_context_cb_, |
| make_context_current_cb_, device)); |
| } |
| return decoder; |
| } |
| |
| std::unique_ptr<VideoDecodeAccelerator> |
| GpuVideoDecodeAcceleratorFactory::CreateV4L2SVDA( |
| const gpu::GpuDriverBugWorkarounds& workarounds, |
| const gpu::GpuPreferences& gpu_preferences) const { |
| std::unique_ptr<VideoDecodeAccelerator> decoder; |
| scoped_refptr<V4L2Device> device = V4L2Device::Create(); |
| if (device.get()) { |
| decoder.reset(new V4L2SliceVideoDecodeAccelerator( |
| device, gl::GLSurfaceEGL::GetHardwareDisplay(), get_gl_context_cb_, |
| make_context_current_cb_)); |
| } |
| return decoder; |
| } |
| #endif |
| |
| #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
| std::unique_ptr<VideoDecodeAccelerator> |
| GpuVideoDecodeAcceleratorFactory::CreateVaapiVDA( |
| const gpu::GpuDriverBugWorkarounds& workarounds, |
| const gpu::GpuPreferences& gpu_preferences) const { |
| std::unique_ptr<VideoDecodeAccelerator> decoder; |
| decoder.reset(new VaapiVideoDecodeAccelerator(make_context_current_cb_, |
| bind_image_cb_)); |
| return decoder; |
| } |
| #endif |
| |
| #if defined(OS_MACOSX) |
| std::unique_ptr<VideoDecodeAccelerator> |
| GpuVideoDecodeAcceleratorFactory::CreateVTVDA( |
| const gpu::GpuDriverBugWorkarounds& workarounds, |
| const gpu::GpuPreferences& gpu_preferences) const { |
| std::unique_ptr<VideoDecodeAccelerator> decoder; |
| decoder.reset( |
| new VTVideoDecodeAccelerator(make_context_current_cb_, bind_image_cb_)); |
| return decoder; |
| } |
| #endif |
| |
| #if defined(OS_ANDROID) |
| std::unique_ptr<VideoDecodeAccelerator> |
| GpuVideoDecodeAcceleratorFactory::CreateAndroidVDA( |
| const gpu::GpuDriverBugWorkarounds& workarounds, |
| const gpu::GpuPreferences& gpu_preferences) const { |
| std::unique_ptr<VideoDecodeAccelerator> decoder; |
| decoder.reset(new AndroidVideoDecodeAccelerator( |
| AVDACodecAllocator::GetInstance(), make_context_current_cb_, |
| get_gles2_decoder_cb_)); |
| return decoder; |
| } |
| #endif |
| |
| GpuVideoDecodeAcceleratorFactory::GpuVideoDecodeAcceleratorFactory( |
| const GetGLContextCallback& get_gl_context_cb, |
| const MakeGLContextCurrentCallback& make_context_current_cb, |
| const BindGLImageCallback& bind_image_cb, |
| const GetGLES2DecoderCallback& get_gles2_decoder_cb) |
| : get_gl_context_cb_(get_gl_context_cb), |
| make_context_current_cb_(make_context_current_cb), |
| bind_image_cb_(bind_image_cb), |
| get_gles2_decoder_cb_(get_gles2_decoder_cb) {} |
| |
| GpuVideoDecodeAcceleratorFactory::~GpuVideoDecodeAcceleratorFactory() {} |
| |
| } // namespace media |