diff options
author | wuchengli@chromium.org <wuchengli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-29 11:20:28 +0000 |
---|---|---|
committer | wuchengli@chromium.org <wuchengli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-29 11:20:28 +0000 |
commit | ff6ab28a1aff88f80c69f79bf6f01c48ea36e001 (patch) | |
tree | 21bfbe8644accf005c5aa65bda0464a852277541 /content | |
parent | cfe43b2b2c0917646b68b9c09fb51790f2a76153 (diff) | |
download | chromium_src-ff6ab28a1aff88f80c69f79bf6f01c48ea36e001.zip chromium_src-ff6ab28a1aff88f80c69f79bf6f01c48ea36e001.tar.gz chromium_src-ff6ab28a1aff88f80c69f79bf6f01c48ea36e001.tar.bz2 |
Run VDA::Decode on GPU IO thread if VDA supports it.
Sometimes GPU main thread is very busy and VDA::Decode is not
run immediately on the main thread. Using MessageFilter to
run VDA::Decode directly on IO thread can reduce decode
latency by around 80ms on various CrOS devices.
BUG=170345
TEST=Try http://apprtc.appspot.com/?debug=loopback on Chromebook Daisy.
Run local hardware-accelerated video on Daisy and Link.
Run video_decode_accelerator_unittest on Daisy.
Review URL: https://chromiumcodereview.appspot.com/23125014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@220259 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
14 files changed, 191 insertions, 42 deletions
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc index 2b920d3..3078887 100644 --- a/content/common/gpu/gpu_channel.cc +++ b/content/common/gpu/gpu_channel.cc @@ -985,4 +985,12 @@ void GpuChannel::CacheShader(const std::string& key, new GpuHostMsg_CacheShader(client_id_, key, shader)); } +void GpuChannel::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { + channel_->AddFilter(filter); +} + +void GpuChannel::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) { + channel_->RemoveFilter(filter); +} + } // namespace content diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h index 0692b90..23c27e0 100644 --- a/content/common/gpu/gpu_channel.h +++ b/content/common/gpu/gpu_channel.h @@ -86,6 +86,10 @@ class GpuChannel : public IPC::Listener, base::ProcessId renderer_pid() const { return channel_->peer_pid(); } + scoped_refptr<base::MessageLoopProxy> io_message_loop() const { + return io_message_loop_; + } + // IPC::Listener implementation: virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; virtual void OnChannelError() OVERRIDE; @@ -156,6 +160,9 @@ class GpuChannel : public IPC::Listener, void CacheShader(const std::string& key, const std::string& shader); + void AddFilter(IPC::ChannelProxy::MessageFilter* filter); + void RemoveFilter(IPC::ChannelProxy::MessageFilter* filter); + protected: virtual ~GpuChannel(); diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 78c0a49..cdc4a6b 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -722,7 +722,7 @@ void GpuCommandBufferStub::OnCreateVideoDecoder( int decoder_route_id = channel_->GenerateRouteID(); GpuVideoDecodeAccelerator* decoder = new GpuVideoDecodeAccelerator(decoder_route_id, this); - decoder->Initialize(profile, reply_message); + decoder->Initialize(profile, reply_message, channel_->io_message_loop()); // decoder is registered as a DestructionObserver of this stub and will // self-delete during destruction of this stub. } diff --git a/content/common/gpu/media/android_video_decode_accelerator.h b/content/common/gpu/media/android_video_decode_accelerator.h index 3bc60c8..abcb1db 100644 --- a/content/common/gpu/media/android_video_decode_accelerator.h +++ b/content/common/gpu/media/android_video_decode_accelerator.h @@ -15,6 +15,7 @@ #include "base/compiler_specific.h" #include "base/threading/thread_checker.h" #include "content/common/content_export.h" +#include "content/common/gpu/media/video_decode_accelerator_impl.h" #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "media/base/android/media_codec_bridge.h" @@ -28,8 +29,8 @@ namespace content { // A VideoDecodeAccelerator implementation for Android. // This class decodes the input encoded stream by using Android's MediaCodec // class. http://developer.android.com/reference/android/media/MediaCodec.html -class CONTENT_EXPORT AndroidVideoDecodeAccelerator : - public media::VideoDecodeAccelerator { +class CONTENT_EXPORT AndroidVideoDecodeAccelerator + : public VideoDecodeAcceleratorImpl { public: // Does not take ownership of |client| which must outlive |*this|. AndroidVideoDecodeAccelerator( diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.h b/content/common/gpu/media/dxva_video_decode_accelerator.h index 26b1ba7..206099cf 100644 --- a/content/common/gpu/media/dxva_video_decode_accelerator.h +++ b/content/common/gpu/media/dxva_video_decode_accelerator.h @@ -17,6 +17,7 @@ #include "base/threading/non_thread_safe.h" #include "base/win/scoped_comptr.h" #include "content/common/content_export.h" +#include "content/common/gpu/media/video_decode_accelerator_impl.h" #include "media/video/video_decode_accelerator.h" interface IMFSample; @@ -29,7 +30,7 @@ namespace content { // This class lives on a single thread and DCHECKs that it is never accessed // from any other. class CONTENT_EXPORT DXVAVideoDecodeAccelerator - : public media::VideoDecodeAccelerator, + : public VideoDecodeAcceleratorImpl, NON_EXPORTED_BASE(public base::NonThreadSafe) { public: enum State { diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.cc b/content/common/gpu/media/exynos_video_decode_accelerator.cc index 677df9c..e643969 100644 --- a/content/common/gpu/media/exynos_video_decode_accelerator.cc +++ b/content/common/gpu/media/exynos_video_decode_accelerator.cc @@ -205,8 +205,10 @@ ExynosVideoDecodeAccelerator::ExynosVideoDecodeAccelerator( EGLDisplay egl_display, EGLContext egl_context, Client* client, - const base::Callback<bool(void)>& make_context_current) + const base::Callback<bool(void)>& make_context_current, + const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy) : child_message_loop_proxy_(base::MessageLoopProxy::current()), + io_message_loop_proxy_(io_message_loop_proxy), weak_this_(base::AsWeakPtr(this)), client_ptr_factory_(client), client_(client_ptr_factory_.GetWeakPtr()), @@ -415,23 +417,12 @@ void ExynosVideoDecodeAccelerator::Decode( const media::BitstreamBuffer& bitstream_buffer) { DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id() << ", size=" << bitstream_buffer.size(); - DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); - - scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( - client_, child_message_loop_proxy_, - new base::SharedMemory(bitstream_buffer.handle(), true), - bitstream_buffer.size(), bitstream_buffer.id())); - if (!bitstream_record->shm->Map(bitstream_buffer.size())) { - DLOG(ERROR) << "Decode(): could not map bitstream_buffer"; - NOTIFY_ERROR(UNREADABLE_INPUT); - return; - } - DVLOG(3) << "Decode(): mapped to addr=" << bitstream_record->shm->memory(); + DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); // DecodeTask() will take care of running a DecodeBufferTask(). decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( &ExynosVideoDecodeAccelerator::DecodeTask, base::Unretained(this), - base::Passed(&bitstream_record))); + bitstream_buffer)); } void ExynosVideoDecodeAccelerator::AssignPictureBuffers( @@ -576,6 +567,8 @@ void ExynosVideoDecodeAccelerator::Destroy() { delete this; } +bool ExynosVideoDecodeAccelerator::CanDecodeOnIOThread() { return true; } + // static void ExynosVideoDecodeAccelerator::PreSandboxInitialization() { DVLOG(3) << "PreSandboxInitialization()"; @@ -610,12 +603,23 @@ bool ExynosVideoDecodeAccelerator::PostSandboxInitialization() { } void ExynosVideoDecodeAccelerator::DecodeTask( - scoped_ptr<BitstreamBufferRef> bitstream_record) { - DVLOG(3) << "DecodeTask(): input_id=" << bitstream_record->input_id; + const media::BitstreamBuffer& bitstream_buffer) { + DVLOG(3) << "DecodeTask(): input_id=" << bitstream_buffer.id(); DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); DCHECK_NE(decoder_state_, kUninitialized); TRACE_EVENT1("Video Decoder", "EVDA::DecodeTask", "input_id", - bitstream_record->input_id); + bitstream_buffer.id()); + + scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( + client_, child_message_loop_proxy_, + new base::SharedMemory(bitstream_buffer.handle(), true), + bitstream_buffer.size(), bitstream_buffer.id())); + if (!bitstream_record->shm->Map(bitstream_buffer.size())) { + DLOG(ERROR) << "Decode(): could not map bitstream_buffer"; + NOTIFY_ERROR(UNREADABLE_INPUT); + return; + } + DVLOG(3) << "Decode(): mapped to addr=" << bitstream_record->shm->memory(); if (decoder_state_ == kResetting || decoder_flushing_) { // In the case that we're resetting or flushing, we need to delay decoding diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.h b/content/common/gpu/media/exynos_video_decode_accelerator.h index 77471402..09264b9 100644 --- a/content/common/gpu/media/exynos_video_decode_accelerator.h +++ b/content/common/gpu/media/exynos_video_decode_accelerator.h @@ -16,8 +16,8 @@ #include "base/memory/scoped_ptr.h" #include "base/threading/thread.h" #include "content/common/content_export.h" +#include "content/common/gpu/media/video_decode_accelerator_impl.h" #include "media/base/video_decoder_config.h" -#include "media/video/video_decode_accelerator.h" #include "ui/gfx/size.h" #include "ui/gl/gl_bindings.h" @@ -54,14 +54,15 @@ class H264Parser; // decoder_thread_, so there are no synchronization issues. // ... well, there are, but it's a matter of getting messages posted in the // right order, not fiddling with locks. -class CONTENT_EXPORT ExynosVideoDecodeAccelerator : - public media::VideoDecodeAccelerator { +class CONTENT_EXPORT ExynosVideoDecodeAccelerator + : public VideoDecodeAcceleratorImpl { public: ExynosVideoDecodeAccelerator( EGLDisplay egl_display, EGLContext egl_context, Client* client, - const base::Callback<bool(void)>& make_context_current); + const base::Callback<bool(void)>& make_context_current, + const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy); virtual ~ExynosVideoDecodeAccelerator(); // media::VideoDecodeAccelerator implementation. @@ -75,6 +76,9 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator : virtual void Reset() OVERRIDE; virtual void Destroy() OVERRIDE; + // VideoDecodeAcceleratorImpl implementation. + virtual bool CanDecodeOnIOThread() OVERRIDE; + // Do any necessary initialization before the sandbox is enabled. static void PreSandboxInitialization(); @@ -178,7 +182,7 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator : // Enqueue a BitstreamBuffer to decode. This will enqueue a buffer to the // decoder_input_queue_, then queue a DecodeBufferTask() to actually decode // the buffer. - void DecodeTask(scoped_ptr<BitstreamBufferRef> bitstream_record); + void DecodeTask(const media::BitstreamBuffer& bitstream_buffer); // Decode from the buffers queued in decoder_input_queue_. Calls // DecodeBufferInitial() or DecodeBufferContinue() as appropriate. @@ -311,6 +315,9 @@ class CONTENT_EXPORT ExynosVideoDecodeAccelerator : // Our original calling message loop for the child thread. scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_; + // Message loop of the IO thread. + scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_; + // WeakPtr<> pointing to |this| for use in posting tasks from the decoder or // device worker threads back to the child thread. Because the worker threads // are members of this class, any task running on those threads is guaranteed diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc index 2b0bb84..a1062e3 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.cc +++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/logging.h" +#include "base/message_loop/message_loop_proxy.h" #include "base/stl_util.h" #include "content/common/gpu/gpu_channel.h" @@ -54,6 +55,36 @@ static bool MakeDecoderContextCurrent( return true; } +class GpuVideoDecodeAccelerator::MessageFilter + : public IPC::ChannelProxy::MessageFilter { + public: + MessageFilter(GpuVideoDecodeAccelerator* owner, int32 host_route_id) + : owner_(owner), host_route_id_(host_route_id) {} + + virtual void OnFilterRemoved() OVERRIDE { + // This will delete |owner_| and |this|. + owner_->OnFilterRemoved(); + } + virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE { + if (msg.routing_id() != host_route_id_) + return false; + + IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg) + IPC_MESSAGE_FORWARD(AcceleratedVideoDecoderMsg_Decode, owner_, + GpuVideoDecodeAccelerator::OnDecode) + IPC_MESSAGE_UNHANDLED(return false;) + IPC_END_MESSAGE_MAP() + return true; + } + + protected: + virtual ~MessageFilter() {} + + private: + GpuVideoDecodeAccelerator* owner_; + int32 host_route_id_; +}; + GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(int32 host_route_id, GpuCommandBufferStub* stub) : init_done_msg_(NULL), @@ -63,17 +94,14 @@ GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(int32 host_route_id, DCHECK(stub_); stub_->AddDestructionObserver(this); stub_->channel()->AddRoute(host_route_id_, this); + child_message_loop_ = base::MessageLoopProxy::current(); make_context_current_ = base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); } GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() { - DCHECK(stub_); if (video_decode_accelerator_) video_decode_accelerator_.release()->Destroy(); - - stub_->channel()->RemoveRoute(host_route_id_); - stub_->RemoveDestructionObserver(this); } bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { @@ -149,7 +177,8 @@ void GpuVideoDecodeAccelerator::NotifyError( void GpuVideoDecodeAccelerator::Initialize( const media::VideoCodecProfile profile, - IPC::Message* init_done_msg) { + IPC::Message* init_done_msg, + const scoped_refptr<base::MessageLoopProxy>& io_message_loop) { DCHECK(stub_); DCHECK(!video_decode_accelerator_.get()); DCHECK(!init_done_msg_); @@ -179,7 +208,8 @@ void GpuVideoDecodeAccelerator::Initialize( gfx::GLSurfaceEGL::GetHardwareDisplay(), stub_->decoder()->GetGLContext()->GetHandle(), this, - make_context_current_)); + make_context_current_, + io_message_loop)); #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) gfx::GLContextGLX* glx_context = static_cast<gfx::GLContextGLX*>(stub_->decoder()->GetGLContext()); @@ -199,16 +229,31 @@ void GpuVideoDecodeAccelerator::Initialize( return; #endif + if (video_decode_accelerator_->CanDecodeOnIOThread()) { + filter_ = new MessageFilter(this, host_route_id_); + stub_->channel()->AddFilter(filter_.get()); + } + if (!video_decode_accelerator_->Initialize(profile)) NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE); } +// Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is +// true, otherwise on the main thread. void GpuVideoDecodeAccelerator::OnDecode( base::SharedMemoryHandle handle, int32 id, uint32 size) { DCHECK(video_decode_accelerator_.get()); if (id < 0) { DLOG(FATAL) << "BitstreamBuffer id " << id << " out of range"; - NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); + if (child_message_loop_->BelongsToCurrentThread()) { + NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT); + } else { + child_message_loop_->PostTask( + FROM_HERE, + base::Bind(&GpuVideoDecodeAccelerator::NotifyError, + base::Unretained(this), + media::VideoDecodeAccelerator::INVALID_ARGUMENT)); + } return; } video_decode_accelerator_->Decode(media::BitstreamBuffer(id, handle, size)); @@ -297,7 +342,20 @@ void GpuVideoDecodeAccelerator::OnReset() { void GpuVideoDecodeAccelerator::OnDestroy() { DCHECK(video_decode_accelerator_.get()); - delete this; + DCHECK(stub_); + stub_->channel()->RemoveRoute(host_route_id_); + stub_->RemoveDestructionObserver(this); + if (filter_.get()) { + // Remove the filter first because the member variables can be accessed on + // IO thread. When filter is removed, OnFilterRemoved will delete |this|. + stub_->channel()->RemoveFilter(filter_.get()); + } else { + delete this; + } +} + +void GpuVideoDecodeAccelerator::OnFilterRemoved() { + child_message_loop_->DeleteSoon(FROM_HERE, this); } void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( @@ -328,9 +386,7 @@ void GpuVideoDecodeAccelerator::NotifyResetDone() { DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ResetDone) failed"; } -void GpuVideoDecodeAccelerator::OnWillDestroyStub() { - delete this; -} +void GpuVideoDecodeAccelerator::OnWillDestroyStub() { OnDestroy(); } bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) { DCHECK(stub_); diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.h b/content/common/gpu/media/gpu_video_decode_accelerator.h index be09302..70d9a44 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.h +++ b/content/common/gpu/media/gpu_video_decode_accelerator.h @@ -11,10 +11,15 @@ #include "base/memory/ref_counted.h" #include "base/memory/shared_memory.h" #include "content/common/gpu/gpu_command_buffer_stub.h" +#include "content/common/gpu/media/video_decode_accelerator_impl.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" #include "media/video/video_decode_accelerator.h" +namespace base { +class MessageLoopProxy; +} + namespace content { class GpuVideoDecodeAccelerator @@ -55,9 +60,12 @@ class GpuVideoDecodeAccelerator // The renderer process handle is valid as long as we have a channel between // GPU process and the renderer. void Initialize(const media::VideoCodecProfile profile, - IPC::Message* init_done_msg); + IPC::Message* init_done_msg, + const scoped_refptr<base::MessageLoopProxy>& io_message_loop); private: + class MessageFilter; + // Handlers for IPC messages. void OnDecode(base::SharedMemoryHandle handle, int32 id, uint32 size); void OnAssignPictureBuffers( @@ -70,6 +78,9 @@ class GpuVideoDecodeAccelerator void OnReset(); void OnDestroy(); + // Called on IO thread when |filter_| has been removed. + void OnFilterRemoved(); + // Message to Send() when initialization is done. Is only non-NULL during // initialization and is owned by the IPC channel underlying the // GpuCommandBufferStub. @@ -82,7 +93,7 @@ class GpuVideoDecodeAccelerator GpuCommandBufferStub* stub_; // The underlying VideoDecodeAccelerator. - scoped_ptr<media::VideoDecodeAccelerator> video_decode_accelerator_; + scoped_ptr<VideoDecodeAcceleratorImpl> video_decode_accelerator_; // Callback for making the relevant context current for GL calls. // Returns false if failed. @@ -91,6 +102,12 @@ class GpuVideoDecodeAccelerator // The texture target as requested by ProvidePictureBuffers(). uint32 texture_target_; + // The message filter to run VDA::Decode on IO thread if VDA supports it. + scoped_refptr<MessageFilter> filter_; + + // GPU child message loop. + scoped_refptr<base::MessageLoopProxy> child_message_loop_; + DISALLOW_IMPLICIT_CONSTRUCTORS(GpuVideoDecodeAccelerator); }; diff --git a/content/common/gpu/media/vaapi_video_decode_accelerator.h b/content/common/gpu/media/vaapi_video_decode_accelerator.h index 9ac73da35..1755b98 100644 --- a/content/common/gpu/media/vaapi_video_decode_accelerator.h +++ b/content/common/gpu/media/vaapi_video_decode_accelerator.h @@ -25,6 +25,7 @@ #include "content/common/content_export.h" #include "content/common/gpu/media/vaapi_h264_decoder.h" #include "content/common/gpu/media/vaapi_wrapper.h" +#include "content/common/gpu/media/video_decode_accelerator_impl.h" #include "media/base/bitstream_buffer.h" #include "media/video/picture.h" #include "media/video/video_decode_accelerator.h" @@ -40,8 +41,8 @@ namespace content { // ChildThread. A few methods on it are called on the decoder thread which is // stopped during |this->Destroy()|, so any tasks posted to the decoder thread // can assume |*this| is still alive. See |weak_this_| below for more details. -class CONTENT_EXPORT VaapiVideoDecodeAccelerator : - public media::VideoDecodeAccelerator { +class CONTENT_EXPORT VaapiVideoDecodeAccelerator + : public VideoDecodeAcceleratorImpl { public: VaapiVideoDecodeAccelerator( Display* x_display, GLXContext glx_context, diff --git a/content/common/gpu/media/video_decode_accelerator_impl.cc b/content/common/gpu/media/video_decode_accelerator_impl.cc new file mode 100644 index 0000000..34f40ef --- /dev/null +++ b/content/common/gpu/media/video_decode_accelerator_impl.cc @@ -0,0 +1,15 @@ +// Copyright 2013 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 "content/common/gpu/media/video_decode_accelerator_impl.h" + +namespace content { + +VideoDecodeAcceleratorImpl::VideoDecodeAcceleratorImpl() {} + +VideoDecodeAcceleratorImpl::~VideoDecodeAcceleratorImpl() {} + +bool VideoDecodeAcceleratorImpl::CanDecodeOnIOThread() { return false; } + +} // namespace content diff --git a/content/common/gpu/media/video_decode_accelerator_impl.h b/content/common/gpu/media/video_decode_accelerator_impl.h new file mode 100644 index 0000000..146a8ef --- /dev/null +++ b/content/common/gpu/media/video_decode_accelerator_impl.h @@ -0,0 +1,28 @@ +// Copyright 2013 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. + +#ifndef CONTENT_COMMON_GPU_MEDIA_VIDEO_DECODE_ACCELERATOR_IMPL_H_ +#define CONTENT_COMMON_GPU_MEDIA_VIDEO_DECODE_ACCELERATOR_IMPL_H_ + +#include "content/common/content_export.h" +#include "media/video/video_decode_accelerator.h" + +namespace content { + +class CONTENT_EXPORT VideoDecodeAcceleratorImpl + : public media::VideoDecodeAccelerator { + public: + VideoDecodeAcceleratorImpl(); + virtual ~VideoDecodeAcceleratorImpl(); + + // Returns true if media::VideoDecodeAccelerator::Decode can run on the IO + // thread. Otherwise Decode will run on the GPU child thread. The purpose of + // running Decode on the IO thread is to reduce decode latency. Note Decode + // should return as soon as possible and not block on the IO thread. + virtual bool CanDecodeOnIOThread(); +}; + +} // namespace content + +#endif // CONTENT_COMMON_GPU_MEDIA_VIDEO_DECODE_ACCELERATOR_IMPL_H_ diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc index a180ff6..5b3e114 100644 --- a/content/common/gpu/media/video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc @@ -32,6 +32,7 @@ #include "base/file_util.h" #include "base/format_macros.h" #include "base/md5.h" +#include "base/message_loop/message_loop_proxy.h" #include "base/platform_file.h" #include "base/process/process.h" #include "base/stl_util.h" @@ -616,7 +617,8 @@ void GLRenderingVDAClient::CreateDecoder() { static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()), static_cast<EGLContext>(rendering_helper_->GetGLContext()), client, - base::Bind(&DoNothingReturnTrue))); + base::Bind(&DoNothingReturnTrue), + base::MessageLoopProxy::current())); #elif defined(ARCH_CPU_X86_FAMILY) decoder_.reset(new VaapiVideoDecodeAccelerator( static_cast<Display*>(rendering_helper_->GetGLDisplay()), diff --git a/content/content_common.gypi b/content/content_common.gypi index 3b04b88..31b2950 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -238,6 +238,8 @@ 'common/gpu/media/gpu_video_decode_accelerator.h', 'common/gpu/media/gpu_video_encode_accelerator.cc', 'common/gpu/media/gpu_video_encode_accelerator.h', + 'common/gpu/media/video_decode_accelerator_impl.cc', + 'common/gpu/media/video_decode_accelerator_impl.h', 'common/gpu/sync_point_manager.h', 'common/gpu/sync_point_manager.cc', 'common/gpu/texture_image_transport_surface.h', |