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_); |