Chromium Code Reviews| 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 2b0bb848b69fba9b2acf8d68839441932af28917..fced412477db43e16277b4e96a7867eeca6fdf81 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,62 @@ static bool MakeDecoderContextCurrent( |
| return true; |
| } |
| +// A message filter to run VDA::Decode in IO thread to reduce decode latency. |
| +class GpuVideoDecodeAccelerator::GvdaMessageFilter |
| + : public IPC::ChannelProxy::MessageFilter { |
| + public: |
| + GvdaMessageFilter(GpuVideoDecodeAccelerator* gvda, |
|
Ami GONE FROM CHROMIUM
2013/08/26 17:20:03
virtual dtor please
Ami GONE FROM CHROMIUM
2013/08/26 17:20:03
s/gvda/owner/ here and in the member declaration a
wuchengli
2013/08/27 12:32:24
Done.
wuchengli
2013/08/27 12:32:24
Done.
|
| + int32 host_route_id, |
| + scoped_refptr<base::MessageLoopProxy> message_loop); |
|
Ami GONE FROM CHROMIUM
2013/08/26 17:20:03
"message_loop" is an uninformative name.
wuchengli
2013/08/27 12:32:24
Changed to child_message_loop.
|
| + virtual void OnFilterRemoved() OVERRIDE; |
| + virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; |
| + void OnDecode(base::SharedMemoryHandle handle, int32 id, uint32 size); |
|
Ami GONE FROM CHROMIUM
2013/08/26 17:20:03
private?
wuchengli
2013/08/27 12:32:24
Done.
|
| + |
| + private: |
| + GpuVideoDecodeAccelerator* gvda_; // GpuVideoDecodeAccelerator owns this. |
| + int32 host_route_id_; |
| + scoped_refptr<base::MessageLoopProxy> message_loop_; |
| +}; |
| + |
| +GpuVideoDecodeAccelerator::GvdaMessageFilter::GvdaMessageFilter( |
| + GpuVideoDecodeAccelerator* gvda, |
| + int32 host_route_id, |
| + scoped_refptr<base::MessageLoopProxy> message_loop) |
| + : gvda_(gvda), host_route_id_(host_route_id), message_loop_(message_loop) {} |
| + |
| +void GpuVideoDecodeAccelerator::GvdaMessageFilter::OnFilterRemoved() { |
| + message_loop_->DeleteSoon(FROM_HERE, gvda_); |
| +} |
| + |
| +bool GpuVideoDecodeAccelerator::GvdaMessageFilter::OnMessageReceived( |
| + const IPC::Message& msg) { |
| + if (msg.routing_id() != host_route_id_) |
| + return false; |
| + |
| + bool handled = true; |
| + IPC_BEGIN_MESSAGE_MAP(GvdaMessageFilter, msg) |
| + IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) |
| + IPC_MESSAGE_UNHANDLED(handled = false) |
| + IPC_END_MESSAGE_MAP() |
| + return handled; |
| +} |
| + |
| +void GpuVideoDecodeAccelerator::GvdaMessageFilter::OnDecode( |
| + base::SharedMemoryHandle handle, |
| + int32 id, |
| + uint32 size) { |
| + if (id < 0) { |
| + DLOG(FATAL) << "BitstreamBuffer id " << id << " out of range"; |
| + message_loop_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&GpuVideoDecodeAccelerator::NotifyError, |
| + base::Unretained(gvda_), |
| + media::VideoDecodeAccelerator::INVALID_ARGUMENT)); |
| + return; |
| + } |
| + gvda_->OnDecode(handle, id, size); |
| +} |
| + |
| GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(int32 host_route_id, |
| GpuCommandBufferStub* stub) |
| : init_done_msg_(NULL), |
| @@ -63,17 +120,16 @@ GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(int32 host_route_id, |
| DCHECK(stub_); |
| stub_->AddDestructionObserver(this); |
| stub_->channel()->AddRoute(host_route_id_, this); |
| + filter_.reset(new GvdaMessageFilter( |
| + this, host_route_id, base::MessageLoopProxy::current())); |
| + stub_->channel()->AddFilter(filter_.get()); |
| 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) { |
| @@ -82,7 +138,6 @@ bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) { |
| return false; |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg) |
| - IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode) |
| IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignPictureBuffers, |
| OnAssignPictureBuffers) |
| IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_ReusePictureBuffer, |
| @@ -149,7 +204,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 +235,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()); |
| @@ -187,7 +244,7 @@ void GpuVideoDecodeAccelerator::Initialize( |
| static_cast<GLXContext>(glx_context->GetHandle()); |
| video_decode_accelerator_.reset(new VaapiVideoDecodeAccelerator( |
| glx_context->display(), glx_context_handle, this, |
| - make_context_current_)); |
| + make_context_current_, io_message_loop)); |
| #elif defined(OS_ANDROID) |
| video_decode_accelerator_.reset(new AndroidVideoDecodeAccelerator( |
| this, |
| @@ -206,11 +263,6 @@ void GpuVideoDecodeAccelerator::Initialize( |
| 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); |
| - return; |
| - } |
| video_decode_accelerator_->Decode(media::BitstreamBuffer(id, handle, size)); |
| } |
| @@ -297,7 +349,12 @@ void GpuVideoDecodeAccelerator::OnReset() { |
| void GpuVideoDecodeAccelerator::OnDestroy() { |
| DCHECK(video_decode_accelerator_.get()); |
| - delete this; |
| + DCHECK(stub_); |
| + stub_->channel()->RemoveRoute(host_route_id_); |
| + stub_->RemoveDestructionObserver(this); |
| + // Remove the filter first because it can access the member variables on IO |
| + // thread. When filter is removed, OnFilterRemoved will delete |this|. |
| + stub_->channel()->RemoveFilter(filter_.get()); |
| } |
| void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer( |
| @@ -328,9 +385,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_); |