Index: content/common/gpu/media/gpu_video_decode_accelerator.cc |
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc |
index b34092dc577dd522b0f0da6012f5d078b13a4967..cc50774fc8a4fd5aea7517e72617b6b4b4783064 100644 |
--- a/content/common/gpu/media/gpu_video_decode_accelerator.cc |
+++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc |
@@ -18,42 +18,32 @@ |
#include "content/common/gpu/gpu_channel.h" |
#include "content/common/gpu/gpu_channel_manager.h" |
#include "content/common/gpu/media/gpu_video_accelerator_util.h" |
+#include "content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h" |
#include "gpu/command_buffer/common/command_buffer.h" |
-#include "gpu/command_buffer/service/gpu_preferences.h" |
#include "ipc/ipc_message_macros.h" |
#include "ipc/ipc_message_utils.h" |
#include "ipc/message_filter.h" |
#include "media/base/limits.h" |
#include "media/gpu/ipc/common/media_messages.h" |
+#include "ui/gfx/geometry/size.h" |
#include "ui/gl/gl_context.h" |
#include "ui/gl/gl_image.h" |
-#include "ui/gl/gl_surface_egl.h" |
- |
-#if defined(OS_WIN) |
-#include "base/win/windows_version.h" |
-#include "content/common/gpu/media/dxva_video_decode_accelerator_win.h" |
-#elif defined(OS_MACOSX) |
-#include "content/common/gpu/media/vt_video_decode_accelerator_mac.h" |
-#elif defined(OS_CHROMEOS) |
-#if defined(USE_V4L2_CODEC) |
-#include "content/common/gpu/media/v4l2_device.h" |
-#include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h" |
-#include "content/common/gpu/media/v4l2_video_decode_accelerator.h" |
-#endif |
-#if defined(ARCH_CPU_X86_FAMILY) |
-#include "content/common/gpu/media/vaapi_video_decode_accelerator.h" |
-#include "ui/gl/gl_implementation.h" |
-#endif |
-#elif defined(OS_ANDROID) |
-#include "content/common/gpu/media/android_video_decode_accelerator.h" |
-#endif |
- |
-#include "ui/gfx/geometry/size.h" |
namespace content { |
+namespace { |
+static gfx::GLContext* GetGLContext( |
+ const base::WeakPtr<GpuCommandBufferStub>& stub) { |
+ if (!stub) { |
+ DLOG(ERROR) << "Stub is gone; no GLContext."; |
+ return nullptr; |
+ } |
+ |
+ return stub->decoder()->GetGLContext(); |
+} |
+ |
static bool MakeDecoderContextCurrent( |
- const base::WeakPtr<GpuCommandBufferStub> stub) { |
+ const base::WeakPtr<GpuCommandBufferStub>& stub) { |
if (!stub) { |
DLOG(ERROR) << "Stub is gone; won't MakeCurrent()."; |
return false; |
@@ -67,6 +57,43 @@ static bool MakeDecoderContextCurrent( |
return true; |
} |
+#if (defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)) || defined(OS_MACOSX) |
+static bool BindImage(const base::WeakPtr<GpuCommandBufferStub>& stub, |
+ uint32_t client_texture_id, |
+ uint32_t texture_target, |
+ const scoped_refptr<gl::GLImage>& image, |
+ bool can_bind_to_sampler) { |
+ if (!stub) { |
+ DLOG(ERROR) << "Stub is gone; won't BindImage()."; |
+ return false; |
+ } |
+ |
+ gpu::gles2::GLES2Decoder* command_decoder = stub->decoder(); |
+ gpu::gles2::TextureManager* texture_manager = |
+ command_decoder->GetContextGroup()->texture_manager(); |
+ gpu::gles2::TextureRef* ref = texture_manager->GetTexture(client_texture_id); |
+ if (ref) { |
+ texture_manager->SetLevelImage(ref, texture_target, 0, image.get(), |
+ can_bind_to_sampler |
+ ? gpu::gles2::Texture::BOUND |
+ : gpu::gles2::Texture::UNBOUND); |
+ } |
+ |
+ return true; |
+} |
+#endif |
+ |
+static base::WeakPtr<gpu::gles2::GLES2Decoder> GetGLES2Decoder( |
+ const base::WeakPtr<GpuCommandBufferStub>& stub) { |
+ if (!stub) { |
+ DLOG(ERROR) << "Stub is gone; no GLES2Decoder."; |
+ return base::WeakPtr<gpu::gles2::GLES2Decoder>(); |
+ } |
+ |
+ return stub->decoder()->AsWeakPtr(); |
+} |
+} // anonymous namespace |
+ |
// DebugAutoLock works like AutoLock but only acquires the lock when |
// DCHECK is on. |
#if DCHECK_IS_ON() |
@@ -139,8 +166,13 @@ GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator( |
weak_factory_for_io_(this) { |
DCHECK(stub_); |
stub_->AddDestructionObserver(this); |
- make_context_current_ = |
+ get_gl_context_cb_ = base::Bind(&GetGLContext, stub_->AsWeakPtr()); |
+ make_context_current_cb_ = |
base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); |
+#if (defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)) || defined(OS_MACOSX) |
+ bind_image_cb_ = base::Bind(&BindImage, stub_->AsWeakPtr()); |
+#endif |
+ get_gles2_decoder_cb_ = base::Bind(&GetGLES2Decoder, stub_->AsWeakPtr()); |
} |
GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { |
@@ -153,40 +185,8 @@ GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { |
gpu::VideoDecodeAcceleratorCapabilities |
GpuVideoDecodeAccelerator::GetCapabilities( |
const gpu::GpuPreferences& gpu_preferences) { |
- media::VideoDecodeAccelerator::Capabilities capabilities; |
- if (gpu_preferences.disable_accelerated_video_decode) |
- return gpu::VideoDecodeAcceleratorCapabilities(); |
- |
- // Query supported profiles for each VDA. The order of querying VDAs should |
- // be the same as the order of initializing VDAs. Then the returned profile |
- // can be initialized by corresponding VDA successfully. |
-#if defined(OS_WIN) |
- capabilities.supported_profiles = |
- DXVAVideoDecodeAccelerator::GetSupportedProfiles(); |
-#elif defined(OS_CHROMEOS) |
- media::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); |
+ return GpuVideoDecodeAcceleratorFactoryImpl::GetDecoderCapabilities( |
+ gpu_preferences); |
} |
bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { |
@@ -329,11 +329,6 @@ bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { |
bool GpuVideoDecodeAccelerator::Initialize( |
const media::VideoDecodeAccelerator::Config& config) { |
- const gpu::GpuPreferences& gpu_preferences = |
- stub_->channel()->gpu_channel_manager()->gpu_preferences(); |
- if (gpu_preferences.disable_accelerated_video_decode) |
- return false; |
- |
DCHECK(!video_decode_accelerator_); |
if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) { |
@@ -344,159 +339,48 @@ bool GpuVideoDecodeAccelerator::Initialize( |
#if !defined(OS_WIN) |
// Ensure we will be able to get a GL context at all before initializing |
// non-Windows VDAs. |
- if (!make_context_current_.Run()) { |
+ if (!make_context_current_cb_.Run()) |
return false; |
- } |
#endif |
- // Array of Create..VDA() function pointers, maybe applicable to the current |
- // platform. This list is ordered by priority of use and it should be the |
- // same as the order of querying supported profiles of VDAs. |
- const GpuVideoDecodeAccelerator::CreateVDAFp create_vda_fps[] = { |
-#if defined(OS_WIN) |
- &GpuVideoDecodeAccelerator::CreateDXVAVDA, |
-#endif |
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) |
- &GpuVideoDecodeAccelerator::CreateV4L2VDA, |
- &GpuVideoDecodeAccelerator::CreateV4L2SliceVDA, |
-#endif |
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
- &GpuVideoDecodeAccelerator::CreateVaapiVDA, |
-#endif |
-#if defined(OS_MACOSX) |
- &GpuVideoDecodeAccelerator::CreateVTVDA, |
-#endif |
-#if defined(OS_ANDROID) |
- &GpuVideoDecodeAccelerator::CreateAndroidVDA, |
-#endif |
- }; |
+ scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl> vda_factory = |
+ GpuVideoDecodeAcceleratorFactoryImpl::CreateWithGLES2Decoder( |
+ get_gl_context_cb_, make_context_current_cb_, bind_image_cb_, |
+ get_gles2_decoder_cb_); |
- for (const auto& create_vda_function : create_vda_fps) { |
- video_decode_accelerator_ = (this->*create_vda_function)(); |
- if (!video_decode_accelerator_ || |
- !video_decode_accelerator_->Initialize(config, this)) |
- continue; |
- |
- if (video_decode_accelerator_->CanDecodeOnIOThread()) { |
- filter_ = new MessageFilter(this, host_route_id_); |
- stub_->channel()->AddFilter(filter_.get()); |
- } |
- return true; |
+ if (!vda_factory) { |
+ LOG(ERROR) << "Failed creating the VDA factory"; |
+ return false; |
} |
- video_decode_accelerator_.reset(); |
- LOG(ERROR) << "HW video decode not available for profile " << config.profile |
- << (config.is_encrypted ? " with encryption" : ""); |
- return false; |
-} |
-#if defined(OS_WIN) |
-scoped_ptr<media::VideoDecodeAccelerator> |
-GpuVideoDecodeAccelerator::CreateDXVAVDA() { |
- scoped_ptr<media::VideoDecodeAccelerator> decoder; |
const gpu::GpuPreferences& gpu_preferences = |
stub_->channel()->gpu_channel_manager()->gpu_preferences(); |
- if (base::win::GetVersion() >= base::win::VERSION_WIN7) { |
- DVLOG(0) << "Initializing DXVA HW decoder for windows."; |
- decoder.reset(new DXVAVideoDecodeAccelerator( |
- make_context_current_, stub_->decoder()->GetGLContext(), |
- gpu_preferences.enable_accelerated_vpx_decode)); |
- } else { |
- NOTIMPLEMENTED() << "HW video decode acceleration not available."; |
- } |
- return decoder; |
-} |
-#endif |
- |
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) |
-scoped_ptr<media::VideoDecodeAccelerator> |
-GpuVideoDecodeAccelerator::CreateV4L2VDA() { |
- scoped_ptr<media::VideoDecodeAccelerator> decoder; |
- scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
- if (device.get()) { |
- decoder.reset(new V4L2VideoDecodeAccelerator( |
- gfx::GLSurfaceEGL::GetHardwareDisplay(), |
- stub_->decoder()->GetGLContext()->GetHandle(), |
- weak_factory_for_io_.GetWeakPtr(), |
- make_context_current_, |
- device, |
- io_task_runner_)); |
+ video_decode_accelerator_ = |
+ vda_factory->CreateVDA(this, config, gpu_preferences); |
+ if (!video_decode_accelerator_) { |
+ LOG(ERROR) << "HW video decode not available for profile " << config.profile |
+ << (config.is_encrypted ? " with encryption" : ""); |
+ return false; |
} |
- return decoder; |
-} |
-scoped_ptr<media::VideoDecodeAccelerator> |
-GpuVideoDecodeAccelerator::CreateV4L2SliceVDA() { |
- scoped_ptr<media::VideoDecodeAccelerator> decoder; |
- scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder); |
- if (device.get()) { |
- decoder.reset(new V4L2SliceVideoDecodeAccelerator( |
- device, |
- gfx::GLSurfaceEGL::GetHardwareDisplay(), |
- stub_->decoder()->GetGLContext()->GetHandle(), |
- weak_factory_for_io_.GetWeakPtr(), |
- make_context_current_, |
- io_task_runner_)); |
+ // Attempt to set up performing decoding tasks on IO thread, if supported by |
+ // the VDA. |
+ if (video_decode_accelerator_->TryToSetupDecodeOnSeparateThread( |
+ weak_factory_for_io_.GetWeakPtr(), io_task_runner_)) { |
+ filter_ = new MessageFilter(this, host_route_id_); |
+ stub_->channel()->AddFilter(filter_.get()); |
} |
- return decoder; |
-} |
-#endif |
-#if (defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)) || defined(OS_MACOSX) |
-void GpuVideoDecodeAccelerator::BindImage(uint32_t client_texture_id, |
- uint32_t texture_target, |
- scoped_refptr<gl::GLImage> image, |
- bool can_bind_to_sampler) { |
- gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder(); |
- gpu::gles2::TextureManager* texture_manager = |
- command_decoder->GetContextGroup()->texture_manager(); |
- gpu::gles2::TextureRef* ref = texture_manager->GetTexture(client_texture_id); |
- if (ref) { |
- texture_manager->SetLevelImage(ref, texture_target, 0, image.get(), |
- can_bind_to_sampler |
- ? gpu::gles2::Texture::BOUND |
- : gpu::gles2::Texture::UNBOUND); |
- } |
-} |
-#endif |
- |
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
-scoped_ptr<media::VideoDecodeAccelerator> |
-GpuVideoDecodeAccelerator::CreateVaapiVDA() { |
- return make_scoped_ptr<media::VideoDecodeAccelerator>( |
- new VaapiVideoDecodeAccelerator( |
- make_context_current_, |
- base::Bind(&GpuVideoDecodeAccelerator::BindImage, |
- base::Unretained(this)))); |
-} |
-#endif |
- |
-#if defined(OS_MACOSX) |
-scoped_ptr<media::VideoDecodeAccelerator> |
-GpuVideoDecodeAccelerator::CreateVTVDA() { |
- return make_scoped_ptr<media::VideoDecodeAccelerator>( |
- new VTVideoDecodeAccelerator( |
- make_context_current_, |
- base::Bind(&GpuVideoDecodeAccelerator::BindImage, |
- base::Unretained(this)))); |
-} |
-#endif |
- |
-#if defined(OS_ANDROID) |
-scoped_ptr<media::VideoDecodeAccelerator> |
-GpuVideoDecodeAccelerator::CreateAndroidVDA() { |
- return make_scoped_ptr<media::VideoDecodeAccelerator>( |
- new AndroidVideoDecodeAccelerator(stub_->decoder()->AsWeakPtr(), |
- make_context_current_)); |
+ return true; |
} |
-#endif |
void GpuVideoDecodeAccelerator::OnSetCdm(int cdm_id) { |
DCHECK(video_decode_accelerator_); |
video_decode_accelerator_->SetCdm(cdm_id); |
} |
-// Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is |
-// true, otherwise on the main thread. |
+// Runs on IO thread if VDA::TryToSetupDecodeOnSeparateThread() succeeded, |
+// otherwise on the main thread. |
void GpuVideoDecodeAccelerator::OnDecode( |
const media::BitstreamBuffer& bitstream_buffer) { |
DCHECK(video_decode_accelerator_); |