summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/common/gpu/gpu_channel.cc27
-rw-r--r--content/common/gpu/gpu_channel.h5
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.cc13
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.h15
-rw-r--r--content/common/gpu/gpu_messages.h63
-rw-r--r--content/common/gpu/media/gpu_video_decode_accelerator.cc153
-rw-r--r--content/common/gpu/media/gpu_video_decode_accelerator.h65
-rw-r--r--content/common/gpu/media/gpu_video_service.cc37
-rw-r--r--content/common/gpu/media/gpu_video_service.h9
-rw-r--r--content/common/gpu/media/omx_video_decode_accelerator.cc20
-rw-r--r--content/common/gpu/media/omx_video_decode_accelerator.h6
-rw-r--r--content/common/gpu/media/omx_video_decode_accelerator_unittest.cc2
-rw-r--r--content/renderer/gpu/gpu_channel_host.cc6
-rw-r--r--content/renderer/gpu/gpu_video_decode_accelerator_host.cc81
-rw-r--r--content/renderer/gpu/gpu_video_decode_accelerator_host.h37
-rw-r--r--content/renderer/gpu/gpu_video_service_host.cc53
-rw-r--r--content/renderer/gpu/gpu_video_service_host.h32
-rw-r--r--content/renderer/pepper_platform_video_decoder_impl.cc104
-rw-r--r--content/renderer/pepper_platform_video_decoder_impl.h22
-rw-r--r--content/renderer/pepper_plugin_delegate_impl.cc6
-rw-r--r--content/renderer/pepper_plugin_delegate_impl.h7
-rw-r--r--gpu/command_buffer/common/command_buffer.cc31
-rw-r--r--gpu/command_buffer/common/command_buffer.h21
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.cc8
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.h6
-rw-r--r--gpu/gpu.gyp1
-rw-r--r--media/video/video_decode_accelerator.h12
-rw-r--r--ppapi/examples/gles2/gles2.cc18
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.cc3
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.h7
-rw-r--r--webkit/plugins/ppapi/plugin_delegate.h4
-rw-r--r--webkit/plugins/ppapi/ppb_video_decoder_impl.cc26
-rw-r--r--webkit/plugins/ppapi/ppb_video_decoder_impl.h4
-rw-r--r--webkit/plugins/ppapi/resource_tracker.h9
34 files changed, 579 insertions, 334 deletions
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
index ba4a74b..e28e14d 100644
--- a/content/common/gpu/gpu_channel.cc
+++ b/content/common/gpu/gpu_channel.cc
@@ -238,13 +238,11 @@ bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
OnCreateOffscreenSurface)
IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroySurface, OnDestroySurface)
IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateVideoDecoder,
- OnCreateVideoDecoder)
+ OnCreateVideoDecoder)
IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyVideoDecoder,
OnDestroyVideoDecoder)
IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateTransportTexture,
OnCreateTransportTexture)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_AssignTexturesToVideoDecoder,
- OnAssignTexturesToVideoDecoder)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled) << msg.type();
@@ -353,15 +351,13 @@ void GpuChannel::OnCreateVideoDecoder(int32 decoder_host_id,
int32 decoder_id = GenerateRouteID();
- // TODO(fischman): this is a BUG. We hand off stub->scheduler()->decoder()
- // to be baked into the resulting GpuVideoDecodeAccelerator, but we don't own
- // that GVDA, and we make no attempt to tear it down if/when
- // stub->scheduler()->decoder() is destroyed. GpuVideoService should be
- // subsumed into this class and GpuVideoDecodeAccelerator should be owned by
- // the GpuCommandBufferStub that owns the commandbuffer GVDA is using.
+ // TODO(fischman): this is a BUG. We hand off stub to be baked into the
+ // resulting GpuVideoDecodeAccelerator, but we don't own that GVDA, and we
+ // make no attempt to tear it down if/when stub is destroyed. GpuVideoService
+ // should be subsumed into this class and GpuVideoDecodeAccelerator should be
+ // owned by GpuCommandBufferStub.
bool ret = service->CreateVideoDecoder(
- this, &router_, decoder_host_id, decoder_id, stub->scheduler()->decoder(),
- configs);
+ this, &router_, decoder_host_id, decoder_id, stub, configs);
DCHECK(ret) << "Failed to create a GpuVideoDecodeAccelerator";
}
@@ -393,15 +389,6 @@ void GpuChannel::OnCreateTransportTexture(int32 context_route_id,
#endif
}
-void GpuChannel::OnAssignTexturesToVideoDecoder(
- int32 decoder_id,
- const std::vector<int32>& buffer_ids,
- const std::vector<uint32>& texture_ids,
- const std::vector<gfx::Size>& sizes) {
- GpuVideoService* service = GpuVideoService::GetInstance();
- service->AssignTexturesToDecoder(decoder_id, buffer_ids, texture_ids, sizes);
-}
-
bool GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
base::WaitableEvent* shutdown_event) {
// Check whether we're already initialized.
diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h
index 6c57a29..8477b92 100644
--- a/content/common/gpu/gpu_channel.h
+++ b/content/common/gpu/gpu_channel.h
@@ -151,11 +151,6 @@ class GpuChannel : public IPC::Channel::Listener,
void OnDestroyVideoDecoder(int32 decoder_id);
void OnCreateTransportTexture(int32 context_route_id, int32 host_id);
- void OnAssignTexturesToVideoDecoder(int32 decoder_id,
- const std::vector<int32>& buffer_ids,
- const std::vector<uint32>& texture_ids,
- const std::vector<gfx::Size>& sizes);
-
// The lifetime of objects of this class is managed by a GpuChannelManager.
// The GpuChannelManager destroy all the GpuChannels that they own when they
// are destroyed. So a raw pointer is safe.
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index a6b378e..0060831 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -5,6 +5,7 @@
#if defined(ENABLE_GPU)
#include "base/bind.h"
+#include "base/callback.h"
#include "base/debug/trace_event.h"
#include "base/process_util.h"
#include "base/shared_memory.h"
@@ -152,6 +153,8 @@ void GpuCommandBufferStub::OnInitialize(
&GpuChannel::OnLatchCallback, base::Unretained(channel_), route_id_));
scheduler_->SetScheduledCallback(
NewCallback(this, &GpuCommandBufferStub::OnScheduled));
+ scheduler_->SetTokenCallback(base::Bind(
+ &GpuCommandBufferStub::OnSetToken, base::Unretained(this)));
if (watchdog_)
scheduler_->SetCommandProcessedCallback(
NewCallback(this, &GpuCommandBufferStub::OnCommandProcessed));
@@ -488,6 +491,16 @@ void GpuCommandBufferStub::CommandBufferWasDestroyed() {
HandleDeferredMessages();
}
+void GpuCommandBufferStub::AddSetTokenCallback(
+ const base::Callback<void(int32)>& callback) {
+ set_token_callbacks_.push_back(callback);
+}
+
+void GpuCommandBufferStub::OnSetToken(int32 token) {
+ for (size_t i = 0; i < set_token_callbacks_.size(); ++i)
+ set_token_callbacks_[i].Run(token);
+}
+
void GpuCommandBufferStub::ResizeCallback(gfx::Size size) {
if (handle_ == gfx::kNullPluginWindow) {
scheduler_->decoder()->ResizeOffscreenFrameBuffer(size);
diff --git a/content/common/gpu/gpu_command_buffer_stub.h b/content/common/gpu/gpu_command_buffer_stub.h
index fa8d7ee..5fdb0e9 100644
--- a/content/common/gpu/gpu_command_buffer_stub.h
+++ b/content/common/gpu/gpu_command_buffer_stub.h
@@ -63,6 +63,12 @@ class GpuCommandBufferStub
// to the same renderer process.
int32 route_id() const { return route_id_; }
+ // Return the current token in the underlying command buffer, or 0 if not yet
+ // initialized.
+ int32 token() const {
+ return command_buffer_.get() ? command_buffer_->GetState().token : 0;
+ }
+
#if defined(OS_WIN)
// Called only by the compositor window's window proc
void OnCompositorWindowPainted();
@@ -84,6 +90,11 @@ class GpuCommandBufferStub
// unblock itself and handle pending messages.
void CommandBufferWasDestroyed();
+ // Register a callback to be Run() whenever the underlying scheduler receives
+ // a set_token() call. The callback will be Run() with the just-set token as
+ // its only parameter. Multiple callbacks may be registered.
+ void AddSetTokenCallback(const base::Callback<void(int32)>& callback);
+
private:
// Message handlers:
void OnInitialize(base::SharedMemoryHandle ring_buffer,
@@ -126,6 +137,9 @@ class GpuCommandBufferStub
void ResizeCallback(gfx::Size size);
void ReportState();
+ // Callback registered with GpuScheduler to receive set_token() notifications.
+ void OnSetToken(int32 token);
+
// The lifetime of objects of this class is managed by a GpuChannel. The
// GpuChannels destroy all the GpuCommandBufferStubs that they own when they
// are destroyed. So a raw pointer is safe.
@@ -147,6 +161,7 @@ class GpuCommandBufferStub
scoped_ptr<gpu::CommandBufferService> command_buffer_;
scoped_ptr<gpu::GpuScheduler> scheduler_;
std::queue<IPC::Message*> deferred_messages_;
+ std::vector<base::Callback<void(int32)> > set_token_callbacks_;
// SetParent may be called before Initialize, in which case we need to keep
// around the parent stub, so that Initialize can set the parent correctly.
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index f06f927..b17344b 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Multiply-included message file, hence no include guard here, but see below
+// for a much smaller-than-usual include guard section.
+
#include <vector>
#include <string>
-
#include "base/shared_memory.h"
#include "content/common/common_param_traits.h"
#include "content/common/gpu/gpu_info.h"
@@ -16,7 +18,6 @@
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
-// Multiply-included message file, hence no include guard.
#define IPC_MESSAGE_START GpuMsgStart
@@ -98,6 +99,11 @@ IPC_STRUCT_TRAITS_BEGIN(GPUInfo)
#endif
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(gpu::ReadWriteTokens)
+ IPC_STRUCT_TRAITS_MEMBER(last_token_read)
+ IPC_STRUCT_TRAITS_MEMBER(last_token_written)
+IPC_STRUCT_TRAITS_END()
+
IPC_ENUM_TRAITS(content::CauseForGpuLaunch)
//------------------------------------------------------------------------------
@@ -305,11 +311,12 @@ IPC_SYNC_MESSAGE_CONTROL1_1(GpuChannelMsg_CreateOffscreenSurface,
IPC_MESSAGE_CONTROL1(GpuChannelMsg_DestroySurface,
int /* route_id */)
-// Create hardware video decoder && associate it with the output |decoder_id|;
+// Create a hardware video decoder; the new route ID is returned through
+// AcceleratedVideoDecoderHostMsg_CreateDone.
// We need this to be control message because we had to map the GpuChannel and
// |decoder_id|.
IPC_MESSAGE_CONTROL3(GpuChannelMsg_CreateVideoDecoder,
- int32, /* decoder_id */
+ int32, /* decoder_host_id */
uint32, /* command buffer route id*/
std::vector<uint32>) /* configs */
@@ -324,13 +331,6 @@ IPC_MESSAGE_CONTROL2(GpuChannelMsg_CreateTransportTexture,
int32, /* context_route_id */
int32 /* host_id */)
-// Sent from Renderer process to the GPU process to give the texture IDs for
-// the textures the decoder will use for output.
-IPC_MESSAGE_CONTROL4(GpuChannelMsg_AssignTexturesToVideoDecoder,
- int32, /* Decoder ID */
- std::vector<int32>, /* Picture buffer ID */
- std::vector<uint32>, /* Texture ID */
- std::vector<gfx::Size>) /* Size */
//------------------------------------------------------------------------------
// GPU Command Buffer Messages
// These are messages between a renderer process to the GPU process relating to
@@ -463,45 +463,68 @@ IPC_MESSAGE_ROUTED1(GpuTransportTextureHostMsg_TextureUpdated,
//------------------------------------------------------------------------------
// Accelerated Video Decoder Messages
// These messages are sent from Renderer process to GPU process.
+//
+// These messages defer execution until |tokens.last_token_written| is
+// seen (using |tokens.last_token_read| as a wrap-around indicator). The
+// implementation REQUIRES that |tokens| be the first parameter of these
+// messages.
+
// Message to query configuration information from the GPU process.
-IPC_SYNC_MESSAGE_CONTROL1_1(AcceleratedVideoDecoderMsg_GetConfigs,
+IPC_SYNC_MESSAGE_CONTROL2_1(AcceleratedVideoDecoderMsg_GetConfigs,
+ gpu::ReadWriteTokens, /* tokens */
std::vector<uint32>, /* Proto config */
std::vector<uint32>) /* Matching configs */
// Message to initialize the accelerated video decoder.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_Initialize,
+IPC_MESSAGE_ROUTED2(AcceleratedVideoDecoderMsg_Initialize,
+ gpu::ReadWriteTokens, /* tokens */
std::vector<uint32>) /* Config */
// Send input buffer for decoding.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoDecoderMsg_Decode,
- int32, /* bitstream_buffer_id */
+IPC_MESSAGE_ROUTED4(AcceleratedVideoDecoderMsg_Decode,
+ gpu::ReadWriteTokens, /* tokens */
base::SharedMemoryHandle, /* input_buffer_handle */
+ int32, /* bitstream_buffer_id */
int32) /* size */
+// Sent from Renderer process to the GPU process to give the texture IDs for
+// the textures the decoder will use for output. Delays evaluation until
+// |token.second| is seen.
+IPC_MESSAGE_ROUTED4(AcceleratedVideoDecoderMsg_AssignTextures,
+ gpu::ReadWriteTokens, /* tokens */
+ std::vector<int32>, /* Picture buffer ID */
+ std::vector<uint32>, /* Texture ID */
+ std::vector<gfx::Size>) /* Size */
+
// Sent from Renderer process to the GPU process to give the system memory
// buffers that the decoder will use for output.
//
// The length of the list of SharedMemoryHandles cannot exceed
// FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE; see
// ipc/file_descriptor_set_posix.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoDecoderMsg_AssignSysmemBuffers,
+IPC_MESSAGE_ROUTED4(AcceleratedVideoDecoderMsg_AssignSysmemBuffers,
+ gpu::ReadWriteTokens, /* tokens */
std::vector<int32>, /* Picture buffer ID */
std::vector<base::SharedMemoryHandle>, /* Sysmem buffer */
std::vector<gfx::Size>) /* Size */
// Send from Renderer process to the GPU process to recycle the given picture
// buffer for further decoding.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_ReusePictureBuffer,
+IPC_MESSAGE_ROUTED2(AcceleratedVideoDecoderMsg_ReusePictureBuffer,
+ gpu::ReadWriteTokens, /* tokens */
int32) /* Picture buffer ID */
// Send flush request to the decoder.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Flush)
+IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_Flush,
+ gpu::ReadWriteTokens) /* tokens */
// Send abort request to the decoder.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Abort)
+IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_Abort,
+ gpu::ReadWriteTokens) /* tokens */
// Destroy and release decoder asynchronously.
-IPC_SYNC_MESSAGE_CONTROL0_0(AcceleratedVideoDecoderMsg_Destroy)
+IPC_SYNC_MESSAGE_CONTROL1_0(AcceleratedVideoDecoderMsg_Destroy,
+ gpu::ReadWriteTokens) /* tokens */
//------------------------------------------------------------------------------
// Accelerated Video Decoder Host Messages
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc
index ffe8096..3ca7235 100644
--- a/content/common/gpu/media/gpu_video_decode_accelerator.cc
+++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc
@@ -8,28 +8,89 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/stl_util-inl.h"
+#include "gpu/command_buffer/common/command_buffer.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"
#include "content/common/gpu/gpu_channel.h"
+#include "content/common/gpu/gpu_command_buffer_stub.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/media/gpu_video_service.h"
#include "ui/gfx/size.h"
GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
IPC::Message::Sender* sender,
- int32 host_route_id)
+ int32 host_route_id,
+ int32 decoder_route_id,
+ GpuCommandBufferStub* stub)
: sender_(sender),
- route_id_(host_route_id),
+ host_route_id_(host_route_id),
+ decoder_route_id_(decoder_route_id),
+ stub_(stub),
video_decode_accelerator_(NULL) {
+ stub_->AddSetTokenCallback(base::Bind(
+ &GpuVideoDecodeAccelerator::OnSetToken, this));
}
-GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {}
+GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
+ STLDeleteElements(&deferred_messages_);
+}
+
+void GpuVideoDecodeAccelerator::OnSetToken(int32 token) {
+ // Note: this always retries all deferred messages on every token arrival.
+ // There's an optimization to be done here by only trying messages which are
+ // waiting for tokens which are earlier than |token|.
+ std::vector<IPC::Message*> deferred_messages_copy;
+ std::swap(deferred_messages_copy, deferred_messages_);
+ for (size_t i = 0; i < deferred_messages_copy.size(); ++i)
+ OnMessageReceived(*deferred_messages_copy[i]);
+ STLDeleteElements(&deferred_messages_copy);
+}
+
+bool GpuVideoDecodeAccelerator::DeferMessageIfNeeded(
+ const IPC::Message& msg, bool* deferred) {
+ // Only consider deferring for message types that need it.
+ switch (msg.type()) {
+ case AcceleratedVideoDecoderMsg_GetConfigs::ID:
+ case AcceleratedVideoDecoderMsg_Initialize::ID:
+ case AcceleratedVideoDecoderMsg_Decode::ID:
+ case AcceleratedVideoDecoderMsg_AssignTextures::ID:
+ case AcceleratedVideoDecoderMsg_AssignSysmemBuffers::ID:
+ case AcceleratedVideoDecoderMsg_ReusePictureBuffer::ID:
+ case AcceleratedVideoDecoderMsg_Flush::ID:
+ case AcceleratedVideoDecoderMsg_Abort::ID:
+ break;
+ default:
+ return false;
+ }
+
+ gpu::ReadWriteTokens tokens;
+ void* iter = NULL;
+ if (!IPC::ParamTraits<gpu::ReadWriteTokens>::Read(&msg, &iter, &tokens))
+ return false;
+ if (tokens.InRange(stub_->token())) {
+ deferred_messages_.push_back(new IPC::Message(msg));
+ *deferred = true;
+ } else {
+ *deferred = false;
+ }
+ return true;
+}
bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
+ bool deferred = false;
+ if (!DeferMessageIfNeeded(msg, &deferred))
+ return false;
+ if (deferred)
+ return true;
+
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAccelerator, msg)
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_GetConfigs, OnGetConfigs)
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Initialize, OnInitialize)
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Decode, OnDecode)
+ IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignTextures,
+ OnAssignTextures)
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_AssignSysmemBuffers,
OnAssignSysmemBuffers)
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_ReusePictureBuffer,
@@ -54,7 +115,7 @@ void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
const gfx::Size& dimensions,
media::VideoDecodeAccelerator::MemoryType type) {
if (!Send(new AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers(
- route_id_, requested_num_of_buffers, dimensions, type))) {
+ host_route_id_, requested_num_of_buffers, dimensions, type))) {
LOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers) "
<< "failed";
}
@@ -64,7 +125,7 @@ void GpuVideoDecodeAccelerator::DismissPictureBuffer(
int32 picture_buffer_id) {
// Notify client that picture buffer is now unused.
if (!Send(new AcceleratedVideoDecoderHostMsg_DismissPictureBuffer(
- route_id_, picture_buffer_id))) {
+ host_route_id_, picture_buffer_id))) {
LOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) "
<< "failed";
}
@@ -73,7 +134,7 @@ void GpuVideoDecodeAccelerator::DismissPictureBuffer(
void GpuVideoDecodeAccelerator::PictureReady(
const media::Picture& picture) {
if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(
- route_id_,
+ host_route_id_,
picture.picture_buffer_id(),
picture.bitstream_buffer_id(),
picture.visible_size(),
@@ -83,84 +144,96 @@ void GpuVideoDecodeAccelerator::PictureReady(
}
void GpuVideoDecodeAccelerator::NotifyEndOfStream() {
- Send(new AcceleratedVideoDecoderHostMsg_EndOfStream(route_id_));
+ Send(new AcceleratedVideoDecoderHostMsg_EndOfStream(host_route_id_));
}
void GpuVideoDecodeAccelerator::NotifyError(
media::VideoDecodeAccelerator::Error error) {
if (!Send(new AcceleratedVideoDecoderHostMsg_ErrorNotification(
- route_id_, error))) {
+ host_route_id_, error))) {
LOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ErrorNotification) "
<< "failed";
}
}
void GpuVideoDecodeAccelerator::OnGetConfigs(
+ const gpu::ReadWriteTokens& /* tokens */,
const std::vector<uint32>& requested, std::vector<uint32>* matched) {
+ // TODO(fischman,vrk): this is borked; can't have a VDA before calling
+ // Initialize, but can't call Initialize until we have some configs!
if (!video_decode_accelerator_.get())
return;
video_decode_accelerator_->GetConfigs(requested, matched);
}
void GpuVideoDecodeAccelerator::OnInitialize(
+ const gpu::ReadWriteTokens& /* tokens */,
const std::vector<uint32>& configs) {
- if (!video_decode_accelerator_.get())
- return;
-
+ DCHECK(!video_decode_accelerator_.get());
+ GpuVideoService::GetInstance()->InitializeVideoDecoder(decoder_route_id_);
+ DCHECK(video_decode_accelerator_.get());
video_decode_accelerator_->Initialize(configs);
}
-void GpuVideoDecodeAccelerator::OnDecode(int32 id,
- base::SharedMemoryHandle handle,
- int32 size) {
- if (!video_decode_accelerator_.get())
- return;
+void GpuVideoDecodeAccelerator::OnDecode(
+ const gpu::ReadWriteTokens&, /* tokens */
+ base::SharedMemoryHandle handle, int32 id, int32 size) {
+ DCHECK(video_decode_accelerator_.get());
video_decode_accelerator_->Decode(media::BitstreamBuffer(id, handle, size));
}
void GpuVideoDecodeAccelerator::AssignGLESBuffers(
const std::vector<media::GLESBuffer>& buffers) {
- if (!video_decode_accelerator_.get())
- return;
+ // TODO(fischman,vrk): it's wonky that we handle the AssignTextures message by
+ // handing its contents to GpuVideoService which then turns around and calls
+ // this (public) method. Instead we should make GpuVideoService vend the
+ // translation method we need and use it directly.
+ DCHECK(video_decode_accelerator_.get());
video_decode_accelerator_->AssignGLESBuffers(buffers);
}
-void GpuVideoDecodeAccelerator::OnAssignSysmemBuffers(
+void GpuVideoDecodeAccelerator::OnAssignTextures(
+ const gpu::ReadWriteTokens& /* tokens */,
const std::vector<int32>& buffer_ids,
- const std::vector<base::SharedMemoryHandle>& data,
+ const std::vector<uint32>& texture_ids,
const std::vector<gfx::Size>& sizes) {
+ GpuVideoService* service = GpuVideoService::GetInstance();
+ service->AssignTexturesToDecoder(
+ decoder_route_id_, buffer_ids, texture_ids, sizes);
+}
+
+void GpuVideoDecodeAccelerator::OnAssignSysmemBuffers(
+ const gpu::ReadWriteTokens& /* tokens */,
+ const std::vector<int32> buffer_ids,
+ const std::vector<base::SharedMemoryHandle> data,
+ const std::vector<gfx::Size> sizes) {
// TODO(vrk): Implement.
NOTIMPLEMENTED();
}
-void GpuVideoDecodeAccelerator::OnReusePictureBuffer(int32 picture_buffer_id) {
- if (!video_decode_accelerator_.get())
- return;
-
+void GpuVideoDecodeAccelerator::OnReusePictureBuffer(
+ const gpu::ReadWriteTokens& /* tokens */,
+ int32 picture_buffer_id) {
+ DCHECK(video_decode_accelerator_.get());
video_decode_accelerator_->ReusePictureBuffer(picture_buffer_id);
}
-void GpuVideoDecodeAccelerator::OnFlush() {
- if (!video_decode_accelerator_.get())
- return;
-
- if (!video_decode_accelerator_->Flush()) {
- NotifyError(
- media::VideoDecodeAccelerator::VIDEODECODERERROR_UNEXPECTED_FLUSH);
- }
+void GpuVideoDecodeAccelerator::OnFlush(
+ const gpu::ReadWriteTokens& /* tokens */) {
+ DCHECK(video_decode_accelerator_.get());
+ video_decode_accelerator_->Flush();
}
-void GpuVideoDecodeAccelerator::OnAbort() {
- if (!video_decode_accelerator_.get())
- return;
-
+void GpuVideoDecodeAccelerator::OnAbort(
+ const gpu::ReadWriteTokens& /* tokens */) {
+ DCHECK(video_decode_accelerator_.get());
video_decode_accelerator_->Abort();
}
void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
int32 bitstream_buffer_id) {
if (!Send(new AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed(
- route_id_, bitstream_buffer_id))) {
+ host_route_id_, bitstream_buffer_id))) {
DLOG(ERROR)
<< "Send(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed) "
<< "failed";
@@ -168,17 +241,17 @@ void GpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
}
void GpuVideoDecodeAccelerator::NotifyInitializeDone() {
- if (!Send(new AcceleratedVideoDecoderHostMsg_InitializeDone(route_id_)))
+ if (!Send(new AcceleratedVideoDecoderHostMsg_InitializeDone(host_route_id_)))
LOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_InitializeDone) failed";
}
void GpuVideoDecodeAccelerator::NotifyFlushDone() {
- if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(route_id_)))
+ if (!Send(new AcceleratedVideoDecoderHostMsg_FlushDone(host_route_id_)))
LOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_FlushDone) failed";
}
void GpuVideoDecodeAccelerator::NotifyAbortDone() {
- if (!Send(new AcceleratedVideoDecoderHostMsg_AbortDone(route_id_)))
+ if (!Send(new AcceleratedVideoDecoderHostMsg_AbortDone(host_route_id_)))
LOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_AbortDone) failed";
}
diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.h b/content/common/gpu/media/gpu_video_decode_accelerator.h
index a7e5de3..96954ff 100644
--- a/content/common/gpu/media/gpu_video_decode_accelerator.h
+++ b/content/common/gpu/media/gpu_video_decode_accelerator.h
@@ -13,13 +13,22 @@
#include "ipc/ipc_message.h"
#include "media/video/video_decode_accelerator.h"
+namespace gpu {
+class ReadWriteTokens;
+}
+
+class GpuCommandBufferStub;
+
class GpuVideoDecodeAccelerator
: public base::RefCountedThreadSafe<GpuVideoDecodeAccelerator>,
public IPC::Channel::Listener,
public IPC::Message::Sender,
public media::VideoDecodeAccelerator::Client {
public:
- GpuVideoDecodeAccelerator(IPC::Message::Sender* sender, int32 host_route_id);
+ GpuVideoDecodeAccelerator(IPC::Message::Sender* sender,
+ int32 host_route_id,
+ int32 decoder_route_id,
+ GpuCommandBufferStub* stub);
virtual ~GpuVideoDecodeAccelerator();
// IPC::Channel::Listener implementation.
@@ -52,24 +61,56 @@ class GpuVideoDecodeAccelerator
void AssignGLESBuffers(const std::vector<media::GLESBuffer>& buffers);
+ // Callback to be fired when the underlying stub receives a new token.
+ void OnSetToken(int32 token);
+
private:
+ // Defers |msg| for later processing if it specifies a write token that hasn't
+ // come to pass yet, and set |*deferred| to true. Return false if the message
+ // failed to parse.
+ bool DeferMessageIfNeeded(const IPC::Message& msg, bool* deferred);
+
// Handlers for IPC messages.
- void OnGetConfigs(const std::vector<uint32>& config,
- std::vector<uint32>* configs);
- void OnInitialize(const std::vector<uint32>& configs);
- void OnDecode(int32 id, base::SharedMemoryHandle handle, int32 size);
- void OnAssignSysmemBuffers(const std::vector<int32>& buffer_ids,
- const std::vector<base::SharedMemoryHandle>& data,
- const std::vector<gfx::Size>& sizes);
- void OnReusePictureBuffer(int32 picture_buffer_id);
- void OnFlush();
- void OnAbort();
+ void OnGetConfigs(
+ const gpu::ReadWriteTokens& /* tokens */,
+ const std::vector<uint32>& config,
+ std::vector<uint32>* configs);
+ void OnInitialize(
+ const gpu::ReadWriteTokens& /* tokens */,
+ const std::vector<uint32>& configs);
+ void OnDecode(
+ const gpu::ReadWriteTokens& /* tokens */,
+ base::SharedMemoryHandle handle, int32 id, int32 size);
+ void OnAssignTextures(
+ const gpu::ReadWriteTokens& /* tokens */,
+ const std::vector<int32>& buffer_ids,
+ const std::vector<uint32>& texture_ids,
+ const std::vector<gfx::Size>& sizes);
+ void OnAssignSysmemBuffers(
+ const gpu::ReadWriteTokens& /* tokens */,
+ const std::vector<int32> buffer_ids,
+ const std::vector<base::SharedMemoryHandle> data,
+ const std::vector<gfx::Size> sizes);
+ void OnReusePictureBuffer(
+ const gpu::ReadWriteTokens& /* tokens */,
+ int32 picture_buffer_id);
+ void OnFlush(const gpu::ReadWriteTokens& /* tokens */);
+ void OnAbort(const gpu::ReadWriteTokens& /* tokens */);
// Pointer to the IPC message sender.
IPC::Message::Sender* sender_;
// Route ID to communicate with the host.
- int32 route_id_;
+ int32 host_route_id_;
+
+ // Route ID of the decoder.
+ int32 decoder_route_id_;
+
+ // Messages deferred for later processing when their tokens have come to pass.
+ std::vector<IPC::Message*> deferred_messages_;
+
+ // Unowned pointer to the underlying GpuCommandBufferStub.
+ GpuCommandBufferStub* stub_;
// Pointer to the underlying VideoDecodeAccelerator.
scoped_ptr<media::VideoDecodeAccelerator> video_decode_accelerator_;
diff --git a/content/common/gpu/media/gpu_video_service.cc b/content/common/gpu/media/gpu_video_service.cc
index ebad95bf..2a9562e 100644
--- a/content/common/gpu/media/gpu_video_service.cc
+++ b/content/common/gpu/media/gpu_video_service.cc
@@ -7,7 +7,6 @@
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
-#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
#include "content/common/gpu/media/omx_video_decode_accelerator.h"
@@ -59,22 +58,14 @@ bool GpuVideoService::CreateVideoDecoder(
MessageRouter* router,
int32 decoder_host_id,
int32 decoder_id,
- gpu::gles2::GLES2Decoder* command_decoder,
+ GpuCommandBufferStub* stub,
const std::vector<uint32>& configs) {
// Create GpuVideoDecodeAccelerator and add to map.
scoped_refptr<GpuVideoDecodeAccelerator> decoder =
- new GpuVideoDecodeAccelerator(channel, decoder_host_id);
-
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
- OmxVideoDecodeAccelerator* omx_decoder =
- new OmxVideoDecodeAccelerator(decoder, MessageLoop::current());
- omx_decoder->SetEglState(gfx::GLSurfaceEGL::GetDisplay(),
- command_decoder->GetGLContext()->GetHandle());
- decoder->set_video_decode_accelerator(omx_decoder);
-#endif // defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
+ new GpuVideoDecodeAccelerator(channel, decoder_host_id, decoder_id, stub);
bool result = decoder_map_.insert(std::make_pair(
- decoder_id, VideoDecoderInfo(decoder, command_decoder))).second;
+ decoder_id, VideoDecoderInfo(decoder, stub))).second;
// Decoder ID is a unique ID determined by GpuVideoServiceHost.
// We should always be adding entries here.
@@ -90,6 +81,24 @@ bool GpuVideoService::CreateVideoDecoder(
return true;
}
+void GpuVideoService::InitializeVideoDecoder(int32 decoder_id) {
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
+ DecoderMap::iterator it = decoder_map_.find(decoder_id);
+ DCHECK(it != decoder_map_.end());
+ GpuVideoDecodeAccelerator* decoder = it->second.video_decoder.get();
+ GpuCommandBufferStub* stub = it->second.stub;
+ DCHECK(stub->scheduler());
+ OmxVideoDecodeAccelerator* omx_decoder =
+ new OmxVideoDecodeAccelerator(decoder, MessageLoop::current());
+ omx_decoder->SetEglState(
+ gfx::GLSurfaceEGL::GetDisplay(),
+ stub->scheduler()->decoder()->GetGLContext()->GetHandle());
+ decoder->set_video_decode_accelerator(omx_decoder);
+#else
+ NOTIMPLEMENTED() << "HW video decode acceleration not available.";
+#endif // defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
+}
+
void GpuVideoService::DestroyVideoDecoder(
MessageRouter* router,
int32 decoder_id) {
@@ -106,7 +115,9 @@ void GpuVideoService::AssignTexturesToDecoder(
DCHECK(it != decoder_map_.end());
DCHECK_EQ(it->first, decoder_id);
GpuVideoDecodeAccelerator* video_decoder = it->second.video_decoder;
- gpu::gles2::GLES2Decoder* command_decoder = it->second.command_decoder;
+ DCHECK(it->second.stub->scheduler()); // Ensure already Initialize()'d.
+ gpu::gles2::GLES2Decoder* command_decoder =
+ it->second.stub->scheduler()->decoder();
std::vector<media::GLESBuffer> buffers;
for (uint32 i = 0; i < buffer_ids.size(); ++i) {
diff --git a/content/common/gpu/media/gpu_video_service.h b/content/common/gpu/media/gpu_video_service.h
index e7e9950..2700de8 100644
--- a/content/common/gpu/media/gpu_video_service.h
+++ b/content/common/gpu/media/gpu_video_service.h
@@ -35,8 +35,9 @@ class GpuVideoService : public IPC::Channel::Listener {
MessageRouter* router,
int32 decoder_host_id,
int32 decoder_id,
- gpu::gles2::GLES2Decoder* command_decoder,
+ GpuCommandBufferStub* stub,
const std::vector<uint32>& configs);
+ void InitializeVideoDecoder(int32 decoder_id);
void DestroyVideoDecoder(MessageRouter* router,
int32 decoder_id);
@@ -49,12 +50,12 @@ class GpuVideoService : public IPC::Channel::Listener {
private:
struct VideoDecoderInfo {
VideoDecoderInfo(scoped_refptr<GpuVideoDecodeAccelerator> g_v_d_a,
- gpu::gles2::GLES2Decoder* g_d)
+ GpuCommandBufferStub* s)
: video_decoder(g_v_d_a),
- command_decoder(g_d) {}
+ stub(s) {}
~VideoDecoderInfo() {}
scoped_refptr<GpuVideoDecodeAccelerator> video_decoder;
- gpu::gles2::GLES2Decoder* command_decoder;
+ GpuCommandBufferStub* stub;
};
// Map of video and command buffer decoders, indexed by video decoder id.
typedef std::map<int32, VideoDecoderInfo> DecoderMap;
diff --git a/content/common/gpu/media/omx_video_decode_accelerator.cc b/content/common/gpu/media/omx_video_decode_accelerator.cc
index 2dfc1da7..36df321 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator.cc
+++ b/content/common/gpu/media/omx_video_decode_accelerator.cc
@@ -335,12 +335,12 @@ bool OmxVideoDecodeAccelerator::CreateComponent() {
return true;
}
-bool OmxVideoDecodeAccelerator::Decode(
+void OmxVideoDecodeAccelerator::Decode(
const media::BitstreamBuffer& bitstream_buffer) {
DCHECK(!free_input_buffers_.empty());
if (!CanAcceptInput())
- return false;
+ return;
OMX_BUFFERHEADERTYPE* omx_buffer = free_input_buffers_.front();
free_input_buffers_.pop();
@@ -350,7 +350,7 @@ bool OmxVideoDecodeAccelerator::Decode(
new base::SharedMemory(bitstream_buffer.handle(), true));
if (!shm->Map(bitstream_buffer.size())) {
LOG(ERROR) << "Failed to SharedMemory::Map().";
- return false;
+ return;
}
SharedMemoryAndId* input_buffer_details = new SharedMemoryAndId();
input_buffer_details->first.reset(shm.release());
@@ -373,10 +373,9 @@ bool OmxVideoDecodeAccelerator::Decode(
if (result != OMX_ErrorNone) {
LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result;
StopOnError();
- return false;
+ return;
}
input_buffers_at_component_++;
- return true;
}
void OmxVideoDecodeAccelerator::AssignGLESBuffers(
@@ -440,14 +439,14 @@ void OmxVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
}
}
-bool OmxVideoDecodeAccelerator::Flush() {
+void OmxVideoDecodeAccelerator::Flush() {
OMX_STATETYPE il_state;
OMX_GetState(component_handle_, &il_state);
DCHECK_EQ(il_state, OMX_StateExecuting);
// Decode the pending data first. Then flush I/O ports.
if (il_state != OMX_StateExecuting) {
client_->NotifyFlushDone();
- return false;
+ return;
}
on_buffer_flag_event_func_ = &OmxVideoDecodeAccelerator::FlushBegin;
@@ -464,10 +463,9 @@ bool OmxVideoDecodeAccelerator::Flush() {
if (result != OMX_ErrorNone) {
LOG(ERROR) << "OMX_EmptyThisBuffer() failed with result " << result;
StopOnError();
- return false;
+ return;
}
input_buffers_at_component_++;
- return true;
}
void OmxVideoDecodeAccelerator::FlushBegin() {
@@ -525,12 +523,12 @@ void OmxVideoDecodeAccelerator::OutputPortFlushDone(int port) {
client_->NotifyFlushDone();
}
-bool OmxVideoDecodeAccelerator::Abort() {
+void OmxVideoDecodeAccelerator::Abort() {
CHECK_EQ(message_loop_, MessageLoop::current());
// Abort() implies immediacy but Flush() actually decodes pending data first.
// TODO(vhiremath@nvidia.com) Fix the Abort to handle this immediacy.
ShutDownOMXFromExecuting();
- return true;
+ return;
}
// Event callback during initialization to handle DoneStateSet to idle
diff --git a/content/common/gpu/media/omx_video_decode_accelerator.h b/content/common/gpu/media/omx_video_decode_accelerator.h
index 36d9f78..c5d35f7 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator.h
+++ b/content/common/gpu/media/omx_video_decode_accelerator.h
@@ -37,14 +37,14 @@ class OmxVideoDecodeAccelerator : public media::VideoDecodeAccelerator {
bool GetConfigs(const std::vector<uint32>& requested_configs,
std::vector<uint32>* matched_configs) OVERRIDE;
bool Initialize(const std::vector<uint32>& config) OVERRIDE;
- bool Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
+ void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
virtual void AssignGLESBuffers(
const std::vector<media::GLESBuffer>& buffers) OVERRIDE;
virtual void AssignSysmemBuffers(
const std::vector<media::SysmemBuffer>& buffers) OVERRIDE;
void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
- bool Flush() OVERRIDE;
- bool Abort() OVERRIDE;
+ void Flush() OVERRIDE;
+ void Abort() OVERRIDE;
void SetEglState(EGLDisplay egl_display, EGLContext egl_context);
diff --git a/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc b/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc
index 9b55913..28d1d7c 100644
--- a/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc
+++ b/content/common/gpu/media/omx_video_decode_accelerator_unittest.cc
@@ -610,7 +610,7 @@ void EglRenderingVDAClient::DecodeNextNALUs() {
CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle));
media::BitstreamBuffer bitstream_buffer(
next_bitstream_buffer_id_++, dup_handle, end_pos - start_pos);
- CHECK(decoder_->Decode(bitstream_buffer));
+ decoder_->Decode(bitstream_buffer);
encoded_data_next_pos_to_decode_ = end_pos;
}
diff --git a/content/renderer/gpu/gpu_channel_host.cc b/content/renderer/gpu/gpu_channel_host.cc
index eeb7d62..7bbae72 100644
--- a/content/renderer/gpu/gpu_channel_host.cc
+++ b/content/renderer/gpu/gpu_channel_host.cc
@@ -60,14 +60,14 @@ bool GpuChannelHost::OnMessageReceived(const IPC::Message& message) {
// This is expected, for example an asynchronous SwapBuffers notification
// to a command buffer proxy that has since been destroyed. This function
// fails silently in that case.
+ if (gpu_video_service_host_->OnMessageReceived(message))
+ return true;
return router_.RouteMessage(message);
}
void GpuChannelHost::OnChannelConnected(int32 peer_pid) {
- // When the channel is connected we create a GpuVideoServiceHost and add it
- // as a message filter.
- channel_->AddFilter(gpu_video_service_host_.get());
channel_->AddFilter(transport_texture_service_.get());
+ gpu_video_service_host_->set_channel(channel_.get());
}
void GpuChannelHost::OnChannelError() {
diff --git a/content/renderer/gpu/gpu_video_decode_accelerator_host.cc b/content/renderer/gpu/gpu_video_decode_accelerator_host.cc
index 4f08dab..6aed720 100644
--- a/content/renderer/gpu/gpu_video_decode_accelerator_host.cc
+++ b/content/renderer/gpu/gpu_video_decode_accelerator_host.cc
@@ -4,14 +4,19 @@
#include "content/renderer/gpu/gpu_video_decode_accelerator_host.h"
+#include "base/bind.h"
#include "base/logging.h"
+#include "base/message_loop.h"
#include "base/shared_memory.h"
#include "base/task.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_thread.h"
+#include "gpu/command_buffer/client/cmd_buffer_helper.h"
+#include "gpu/command_buffer/common/command_buffer.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_platform_file.h"
using media::VideoDecodeAccelerator;
@@ -19,14 +24,18 @@ GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
MessageRouter* router,
IPC::Message::Sender* ipc_sender,
int32 decoder_host_id,
- uint32 command_buffer_route_id,
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper,
VideoDecodeAccelerator::Client* client)
: router_(router),
ipc_sender_(ipc_sender),
decoder_host_id_(decoder_host_id),
- decoder_id_(0),
+ decoder_id_(-1),
command_buffer_route_id_(command_buffer_route_id),
+ cmd_buffer_helper_(cmd_buffer_helper),
client_(client) {
+ DCHECK(RenderThread::current());
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
}
GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {}
@@ -39,6 +48,7 @@ void GpuVideoDecodeAcceleratorHost::OnChannelError() {
}
bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
+ DCHECK(CalledOnValidThread());
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg)
IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
@@ -65,6 +75,16 @@ bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
+gpu::ReadWriteTokens GpuVideoDecodeAcceleratorHost::SyncTokens() {
+ DCHECK(CalledOnValidThread());
+ // Note that the order below matters. InsertToken() must happen before
+ // Flush() and last_token_read() should be read before InsertToken().
+ int32 read = cmd_buffer_helper_->last_token_read();
+ int32 written = cmd_buffer_helper_->InsertToken();
+ cmd_buffer_helper_->Flush();
+ return gpu::ReadWriteTokens(read, written);
+}
+
bool GpuVideoDecodeAcceleratorHost::GetConfigs(
const std::vector<uint32>& requested_configs,
std::vector<uint32>* matched_configs) {
@@ -75,34 +95,35 @@ bool GpuVideoDecodeAcceleratorHost::GetConfigs(
bool GpuVideoDecodeAcceleratorHost::Initialize(
const std::vector<uint32>& configs) {
+ DCHECK(CalledOnValidThread());
router_->AddRoute(decoder_host_id_, this);
// Temporarily save configs for after create is done and we're
// ready to initialize.
configs_ = configs;
-
if (!ipc_sender_->Send(new GpuChannelMsg_CreateVideoDecoder(
- decoder_id_, command_buffer_route_id_, configs))) {
+ decoder_host_id_, command_buffer_route_id_, configs))) {
LOG(ERROR) << "Send(GpuChannelMsg_CreateVideoDecoder) failed";
return false;
}
return true;
}
-bool GpuVideoDecodeAcceleratorHost::Decode(
+void GpuVideoDecodeAcceleratorHost::Decode(
const media::BitstreamBuffer& bitstream_buffer) {
+ DCHECK(CalledOnValidThread());
if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_Decode(
- decoder_id_, bitstream_buffer.id(),
- bitstream_buffer.handle(), bitstream_buffer.size()))) {
+ decoder_id_, SyncTokens(), bitstream_buffer.handle(),
+ bitstream_buffer.id(), bitstream_buffer.size()))) {
DLOG(ERROR) << "Send(AcceleratedVideoDecoderMsg_Decode) failed";
- return false;
+ // TODO(fischman/vrk): signal error to client.
+ return;
}
-
- return true;
}
void GpuVideoDecodeAcceleratorHost::AssignGLESBuffers(
const std::vector<media::GLESBuffer>& buffers) {
+ DCHECK(CalledOnValidThread());
// Rearrange data for IPC command.
std::vector<int32> buffer_ids;
std::vector<uint32> texture_ids;
@@ -113,44 +134,51 @@ void GpuVideoDecodeAcceleratorHost::AssignGLESBuffers(
buffer_ids.push_back(buffer.id());
sizes.push_back(buffer.size());
}
- if (!ipc_sender_->Send(new GpuChannelMsg_AssignTexturesToVideoDecoder(
- decoder_id_, buffer_ids, texture_ids, sizes))) {
+ if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_AssignTextures(
+ decoder_id_, SyncTokens(), buffer_ids, texture_ids, sizes))) {
LOG(ERROR) << "Send(AcceleratedVideoDecoderMsg_AssignGLESBuffers) failed";
}
}
void GpuVideoDecodeAcceleratorHost::AssignSysmemBuffers(
const std::vector<media::SysmemBuffer>& buffers) {
+ DCHECK(CalledOnValidThread());
// TODO(vrk): Implement.
NOTIMPLEMENTED();
}
void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
int32 picture_buffer_id) {
+ DCHECK(CalledOnValidThread());
if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
- decoder_id_, picture_buffer_id))) {
+ decoder_id_, SyncTokens(), picture_buffer_id))) {
LOG(ERROR) << "Send(AcceleratedVideoDecoderMsg_ReusePictureBuffer) failed";
}
}
-bool GpuVideoDecodeAcceleratorHost::Flush() {
- if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_Flush(decoder_id_))) {
+void GpuVideoDecodeAcceleratorHost::Flush() {
+ DCHECK(CalledOnValidThread());
+ if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_Flush(
+ decoder_id_, SyncTokens()))) {
LOG(ERROR) << "Send(AcceleratedVideoDecoderMsg_Flush) failed";
- return false;
+ // TODO(fischman/vrk): signal error to client.
+ return;
}
- return true;
}
-bool GpuVideoDecodeAcceleratorHost::Abort() {
- if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_Abort(decoder_id_))) {
+void GpuVideoDecodeAcceleratorHost::Abort() {
+ DCHECK(CalledOnValidThread());
+ if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_Abort(
+ decoder_id_, SyncTokens()))) {
LOG(ERROR) << "Send(AcceleratedVideoDecoderMsg_Abort) failed";
- return false;
+ // TODO(fischman/vrk): signal error to client.
+ return;
}
- return true;
}
void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
int32 bitstream_buffer_id) {
+ DCHECK(CalledOnValidThread());
client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
}
@@ -158,6 +186,7 @@ void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
uint32 num_requested_buffers,
const gfx::Size& buffer_size,
int32 mem_type) {
+ DCHECK(CalledOnValidThread());
media::VideoDecodeAccelerator::MemoryType converted_mem_type =
static_cast<media::VideoDecodeAccelerator::MemoryType>(mem_type);
client_->ProvidePictureBuffers(
@@ -166,42 +195,50 @@ void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
int32 picture_buffer_id) {
+ DCHECK(CalledOnValidThread());
client_->DismissPictureBuffer(picture_buffer_id);
}
void GpuVideoDecodeAcceleratorHost::OnCreateDone(int32 decoder_id) {
+ DCHECK(CalledOnValidThread());
decoder_id_ = decoder_id;
if (!ipc_sender_->Send(new AcceleratedVideoDecoderMsg_Initialize(
- decoder_id_, configs_))) {
+ decoder_id_, SyncTokens(), configs_))) {
LOG(ERROR) << "Send(AcceleratedVideoDecoderMsg_Initialize) failed";
}
}
void GpuVideoDecodeAcceleratorHost::OnInitializeDone() {
+ DCHECK(CalledOnValidThread());
client_->NotifyInitializeDone();
}
void GpuVideoDecodeAcceleratorHost::OnPictureReady(
int32 picture_buffer_id, int32 bitstream_buffer_id,
const gfx::Size& visible_size, const gfx::Size& decoded_size) {
+ DCHECK(CalledOnValidThread());
media::Picture picture(
picture_buffer_id, bitstream_buffer_id, visible_size, decoded_size);
client_->PictureReady(picture);
}
void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
+ DCHECK(CalledOnValidThread());
client_->NotifyFlushDone();
}
void GpuVideoDecodeAcceleratorHost::OnAbortDone() {
+ DCHECK(CalledOnValidThread());
client_->NotifyAbortDone();
}
void GpuVideoDecodeAcceleratorHost::OnEndOfStream() {
+ DCHECK(CalledOnValidThread());
client_->NotifyEndOfStream();
}
void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) {
+ DCHECK(CalledOnValidThread());
client_->NotifyError(
static_cast<media::VideoDecodeAccelerator::Error>(error));
}
diff --git a/content/renderer/gpu/gpu_video_decode_accelerator_host.h b/content/renderer/gpu/gpu_video_decode_accelerator_host.h
index ea73da0..9012168 100644
--- a/content/renderer/gpu/gpu_video_decode_accelerator_host.h
+++ b/content/renderer/gpu/gpu_video_decode_accelerator_host.h
@@ -9,23 +9,31 @@
#include "base/memory/scoped_ptr.h"
#include "base/shared_memory.h"
+#include "base/threading/non_thread_safe.h"
#include "ipc/ipc_channel.h"
#include "media/video/video_decode_accelerator.h"
class MessageLoop;
class MessageRouter;
+namespace gpu {
+class CommandBufferHelper;
+class ReadWriteTokens;
+}
// This class is used to talk to VideoDecodeAccelerator in the Gpu process
// through IPC messages.
-class GpuVideoDecodeAcceleratorHost : public IPC::Channel::Listener,
- public media::VideoDecodeAccelerator {
+class GpuVideoDecodeAcceleratorHost
+ : public IPC::Channel::Listener,
+ public media::VideoDecodeAccelerator,
+ public base::NonThreadSafe {
public:
// |router| is used to dispatch IPC messages to this object.
// |ipc_sender| is used to send IPC messages to Gpu process.
GpuVideoDecodeAcceleratorHost(MessageRouter* router,
IPC::Message::Sender* ipc_sender,
int32 decoder_host_id,
- uint32 command_buffer_route_id,
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper,
media::VideoDecodeAccelerator::Client* client);
virtual ~GpuVideoDecodeAcceleratorHost();
@@ -39,16 +47,20 @@ class GpuVideoDecodeAcceleratorHost : public IPC::Channel::Listener,
const std::vector<uint32>& requested_configs,
std::vector<uint32>* matched_configs) OVERRIDE;
virtual bool Initialize(const std::vector<uint32>& configs) OVERRIDE;
- virtual bool Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
+ virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
virtual void AssignGLESBuffers(
const std::vector<media::GLESBuffer>& buffers) OVERRIDE;
virtual void AssignSysmemBuffers(
const std::vector<media::SysmemBuffer>& buffers) OVERRIDE;
virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual bool Flush() OVERRIDE;
- virtual bool Abort() OVERRIDE;
+ virtual void Flush() OVERRIDE;
+ virtual void Abort() OVERRIDE;
private:
+ // Insert a token into the command buffer and return a token-pair suitable for
+ // sending over IPC for synchronization with the command buffer.
+ gpu::ReadWriteTokens SyncTokens();
+
void OnBitstreamBufferProcessed(int32 bitstream_buffer_id);
void OnProvidePictureBuffer(
uint32 num_requested_buffers, const gfx::Size& buffer_size, int32 mem_type);
@@ -78,7 +90,18 @@ class GpuVideoDecodeAcceleratorHost : public IPC::Channel::Listener,
// Route ID for the command buffer associated with the context the GPU Video
// Decoder uses.
- uint32 command_buffer_route_id_;
+ // TODO(fischman): storing route_id's for GPU process entities in the renderer
+ // process is vulnerable to GPU process crashing & being respawned, and
+ // attempting to use an outdated or reused route id.
+ int32 command_buffer_route_id_;
+
+ // Helper for the command buffer associated with the context the GPU Video
+ // Decoder uses.
+ // TODO(fischman): in the out-of-process case, this won't work
+ // (context3d->gles2_impl() will be NULL), and will have to be replaced with a
+ // dedicated message such as WaitForToken, which will serialize subsequent
+ // message processing behind it.
+ gpu::CommandBufferHelper* cmd_buffer_helper_;
// Temporarily store configs here in between Create and Initialize phase.
std::vector<uint32> configs_;
diff --git a/content/renderer/gpu/gpu_video_service_host.cc b/content/renderer/gpu/gpu_video_service_host.cc
index 9b3fe22..2a39476 100644
--- a/content/renderer/gpu/gpu_video_service_host.cc
+++ b/content/renderer/gpu/gpu_video_service_host.cc
@@ -12,32 +12,25 @@
GpuVideoServiceHost::GpuVideoServiceHost()
: channel_(NULL),
next_decoder_host_id_(0) {
+ DCHECK(RenderThread::current());
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
}
GpuVideoServiceHost::~GpuVideoServiceHost() {
}
-void GpuVideoServiceHost::OnFilterAdded(IPC::Channel* channel) {
- base::Closure on_initialized;
- {
- base::AutoLock auto_lock(lock_);
- DCHECK(!channel_);
- channel_ = channel;
- on_initialized = on_initialized_;
- }
- if (!on_initialized.is_null())
- on_initialized.Run();
-}
-
-void GpuVideoServiceHost::OnFilterRemoved() {
- // TODO(hclam): Implement.
-}
-
-void GpuVideoServiceHost::OnChannelClosing() {
- // TODO(hclam): Implement.
+void GpuVideoServiceHost::set_channel(IPC::SyncChannel* channel) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!channel_);
+ channel_ = channel;
+ if (!on_initialized_.is_null())
+ on_initialized_.Run();
}
bool GpuVideoServiceHost::OnMessageReceived(const IPC::Message& msg) {
+ DCHECK(CalledOnValidThread());
+ if (!channel_)
+ return false;
switch (msg.type()) {
case AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed::ID:
case AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers::ID:
@@ -57,25 +50,27 @@ bool GpuVideoServiceHost::OnMessageReceived(const IPC::Message& msg) {
}
}
+void GpuVideoServiceHost::OnChannelError() {
+ DCHECK(CalledOnValidThread());
+ channel_ = NULL;
+}
+
void GpuVideoServiceHost::SetOnInitialized(
const base::Closure& on_initialized) {
- IPC::Channel* channel;
- {
- base::AutoLock auto_lock(lock_);
- DCHECK(on_initialized_.is_null());
- on_initialized_ = on_initialized;
- channel = channel_;
- }
- if (channel)
+ DCHECK(CalledOnValidThread());
+ DCHECK(on_initialized_.is_null());
+ on_initialized_ = on_initialized;
+ if (channel_)
on_initialized.Run();
}
GpuVideoDecodeAcceleratorHost* GpuVideoServiceHost::CreateVideoAccelerator(
media::VideoDecodeAccelerator::Client* client,
- int command_buffer_route_id) {
- base::AutoLock auto_lock(lock_);
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper) {
+ DCHECK(CalledOnValidThread());
DCHECK(channel_);
return new GpuVideoDecodeAcceleratorHost(
&router_, channel_, next_decoder_host_id_++,
- command_buffer_route_id, client);
+ command_buffer_route_id, cmd_buffer_helper, client);
}
diff --git a/content/renderer/gpu/gpu_video_service_host.h b/content/renderer/gpu/gpu_video_service_host.h
index 83028c11..db519ef 100644
--- a/content/renderer/gpu/gpu_video_service_host.h
+++ b/content/renderer/gpu/gpu_video_service_host.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_GPU_GPU_VIDEO_SERVICE_HOST_H_
#include "base/memory/singleton.h"
+#include "base/threading/non_thread_safe.h"
#include "content/renderer/gpu/gpu_channel_host.h"
#include "ipc/ipc_channel.h"
#include "media/base/buffers.h"
@@ -13,19 +14,26 @@
#include "media/video/video_decode_accelerator.h"
class GpuVideoDecodeAcceleratorHost;
+namespace gpu {
+class CommandBufferHelper;
+}
-// GpuVideoServiceHost lives on IO thread and is used to dispatch IPC messages
-// to GpuVideoDecoderHost objects.
-class GpuVideoServiceHost : public IPC::ChannelProxy::MessageFilter {
+// GpuVideoServiceHost lives on renderer thread and is used to dispatch IPC
+// messages to GpuVideoDecodeAcceleratorHost objects.
+class GpuVideoServiceHost
+ : public IPC::Channel::Listener,
+ public base::NonThreadSafe,
+ public base::RefCountedThreadSafe<GpuVideoServiceHost> {
public:
GpuVideoServiceHost();
virtual ~GpuVideoServiceHost();
- // IPC::ChannelProxy::MessageFilter implementations, called on IO thread.
- virtual bool OnMessageReceived(const IPC::Message& message);
- virtual void OnFilterAdded(IPC::Channel* channel);
- virtual void OnFilterRemoved();
- virtual void OnChannelClosing();
+ void set_channel(IPC::SyncChannel* channel);
+
+ // IPC::Channel::Listener implementation; called on render thread because of
+ // GpuChannelHost's use of a ChannelProxy/SyncChannel.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void OnChannelError() OVERRIDE;
// Register a callback to be notified when |*this| can be used to
// CreateVideo{Decoder,Accelerator} below. Called on RenderThread.
@@ -38,14 +46,12 @@ class GpuVideoServiceHost : public IPC::ChannelProxy::MessageFilter {
// in the GPU process.
GpuVideoDecodeAcceleratorHost* CreateVideoAccelerator(
media::VideoDecodeAccelerator::Client* client,
- int command_buffer_route_id);
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper);
private:
- // Guards all members other than |router_|.
- base::Lock lock_;
-
// Reference to the channel that the service listens to.
- IPC::Channel* channel_;
+ IPC::SyncChannel* channel_;
// Router to send messages to a GpuVideoDecoderHost.
MessageRouter router_;
diff --git a/content/renderer/pepper_platform_video_decoder_impl.cc b/content/renderer/pepper_platform_video_decoder_impl.cc
index 1217bb9..8e186c8 100644
--- a/content/renderer/pepper_platform_video_decoder_impl.cc
+++ b/content/renderer/pepper_platform_video_decoder_impl.cc
@@ -17,11 +17,13 @@
using media::BitstreamBuffer;
PlatformVideoDecoderImpl::PlatformVideoDecoderImpl(
- VideoDecodeAccelerator::Client* client, uint32 command_buffer_route_id)
+ VideoDecodeAccelerator::Client* client,
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper)
: client_(client),
command_buffer_route_id_(command_buffer_route_id),
- decoder_(NULL),
- message_loop_(NULL) {
+ cmd_buffer_helper_(cmd_buffer_helper),
+ decoder_(NULL) {
DCHECK(client);
}
@@ -42,8 +44,6 @@ bool PlatformVideoDecoderImpl::Initialize(const std::vector<uint32>& config) {
RenderThread* render_thread = RenderThread::current();
DCHECK(render_thread);
- message_loop_ = MessageLoop::current();
- DCHECK(message_loop_);
channel_ = render_thread->EstablishGpuChannelSync(
content::CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE);
@@ -67,26 +67,18 @@ bool PlatformVideoDecoderImpl::Initialize(const std::vector<uint32>& config) {
void PlatformVideoDecoderImpl::InitializeDecoder(
const std::vector<uint32>& configs) {
- // Only create GpuVideoDecodeAcceleratorHost on IO thread.
- if (ChildProcess::current()->io_message_loop() != MessageLoop::current() ) {
- ChildProcess::current()->io_message_loop()->
- PostTask(FROM_HERE, base::Bind(
- &PlatformVideoDecoderImpl::InitializeDecoder,
- base::Unretained(this),
- configs));
- return;
- }
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
GpuVideoServiceHost* video_service = channel_->gpu_video_service_host();
decoder_.reset(video_service->CreateVideoAccelerator(
- this, command_buffer_route_id_));
+ this, command_buffer_route_id_, cmd_buffer_helper_));
// Send IPC message to initialize decoder in GPU process.
decoder_->Initialize(configs);
}
-bool PlatformVideoDecoderImpl::Decode(const BitstreamBuffer& bitstream_buffer) {
+void PlatformVideoDecoderImpl::Decode(const BitstreamBuffer& bitstream_buffer) {
DCHECK(decoder_.get());
- return decoder_->Decode(bitstream_buffer);
+ decoder_->Decode(bitstream_buffer);
}
void PlatformVideoDecoderImpl::AssignGLESBuffers(
@@ -107,96 +99,62 @@ void PlatformVideoDecoderImpl::ReusePictureBuffer(
decoder_->ReusePictureBuffer(picture_buffer_id);
}
-bool PlatformVideoDecoderImpl::Flush() {
+void PlatformVideoDecoderImpl::Flush() {
DCHECK(decoder_.get());
- return decoder_->Flush();
+ decoder_->Flush();
}
-bool PlatformVideoDecoderImpl::Abort() {
+void PlatformVideoDecoderImpl::Abort() {
DCHECK(decoder_.get());
- return decoder_->Abort();
+ decoder_->Abort();
}
void PlatformVideoDecoderImpl::NotifyEndOfStream() {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::NotifyEndOfStream,
- base::Unretained(client_)));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->NotifyEndOfStream();
}
void PlatformVideoDecoderImpl::NotifyError(
VideoDecodeAccelerator::Error error) {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::NotifyError,
- base::Unretained(client_),
- error));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->NotifyError(error);
}
void PlatformVideoDecoderImpl::ProvidePictureBuffers(
uint32 requested_num_of_buffers,
const gfx::Size& dimensions,
media::VideoDecodeAccelerator::MemoryType type) {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::ProvidePictureBuffers,
- base::Unretained(client_),
- requested_num_of_buffers,
- dimensions,
- type));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->ProvidePictureBuffers(requested_num_of_buffers, dimensions, type);
}
void PlatformVideoDecoderImpl::DismissPictureBuffer(int32 picture_buffer_id) {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::DismissPictureBuffer,
- base::Unretained(client_),
- picture_buffer_id));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->DismissPictureBuffer(picture_buffer_id);
}
void PlatformVideoDecoderImpl::PictureReady(const media::Picture& picture) {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::PictureReady,
- base::Unretained(client_),
- picture));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->PictureReady(picture);
}
void PlatformVideoDecoderImpl::NotifyInitializeDone() {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::NotifyInitializeDone,
- base::Unretained(client_)));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->NotifyInitializeDone();
}
void PlatformVideoDecoderImpl::NotifyEndOfBitstreamBuffer(
int32 bitstream_buffer_id) {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::NotifyEndOfBitstreamBuffer,
- base::Unretained(client_),
- bitstream_buffer_id));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
}
void PlatformVideoDecoderImpl::NotifyFlushDone() {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::NotifyFlushDone,
- base::Unretained(client_)));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->NotifyFlushDone();
}
void PlatformVideoDecoderImpl::NotifyAbortDone() {
- DCHECK(message_loop_);
- message_loop_->
- PostTask(FROM_HERE, base::Bind(
- &VideoDecodeAccelerator::Client::NotifyAbortDone,
- base::Unretained(client_)));
+ DCHECK_EQ(RenderThread::current()->message_loop(), MessageLoop::current());
+ client_->NotifyAbortDone();
}
diff --git a/content/renderer/pepper_platform_video_decoder_impl.h b/content/renderer/pepper_platform_video_decoder_impl.h
index 4f10db6..703bc91 100644
--- a/content/renderer/pepper_platform_video_decoder_impl.h
+++ b/content/renderer/pepper_platform_video_decoder_impl.h
@@ -14,15 +14,19 @@
#include "webkit/plugins/ppapi/plugin_delegate.h"
class GpuChannelHost;
+namespace gpu {
+class CommandBufferHelper;
+}
class PlatformVideoDecoderImpl
: public webkit::ppapi::PluginDelegate::PlatformVideoDecoder,
public media::VideoDecodeAccelerator::Client,
public base::RefCountedThreadSafe<PlatformVideoDecoderImpl> {
public:
- explicit PlatformVideoDecoderImpl(
+ PlatformVideoDecoderImpl(
media::VideoDecodeAccelerator::Client* client,
- uint32 command_buffer_route_id);
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper);
virtual ~PlatformVideoDecoderImpl();
// PlatformVideoDecoder implementation.
@@ -30,15 +34,15 @@ class PlatformVideoDecoderImpl
const std::vector<uint32>& requested_configs,
std::vector<uint32>* matched_configs) OVERRIDE;
virtual bool Initialize(const std::vector<uint32>& config) OVERRIDE;
- virtual bool Decode(
+ virtual void Decode(
const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
virtual void AssignGLESBuffers(
const std::vector<media::GLESBuffer>& buffers) OVERRIDE;
virtual void AssignSysmemBuffers(
const std::vector<media::SysmemBuffer>& buffers) OVERRIDE;
virtual void ReusePictureBuffer(int32 picture_buffer_id);
- virtual bool Flush() OVERRIDE;
- virtual bool Abort() OVERRIDE;
+ virtual void Flush() OVERRIDE;
+ virtual void Abort() OVERRIDE;
// VideoDecodeAccelerator::Client implementation.
virtual void ProvidePictureBuffers(
@@ -65,7 +69,10 @@ class PlatformVideoDecoderImpl
media::VideoDecodeAccelerator::Client* client_;
// Route ID for the command buffer associated with video decoder's context.
- uint32 command_buffer_route_id_;
+ int32 command_buffer_route_id_;
+
+ // Helper for the command buffer associated with video decoder's context.
+ gpu::CommandBufferHelper* cmd_buffer_helper_;
// Host for GpuVideoDecodeAccelerator.
scoped_ptr<media::VideoDecodeAccelerator> decoder_;
@@ -73,9 +80,6 @@ class PlatformVideoDecoderImpl
// Host for Gpu Channel.
scoped_refptr<GpuChannelHost> channel_;
- // Message loop on which plugin is initialized.
- MessageLoop* message_loop_;
-
DISALLOW_COPY_AND_ASSIGN(PlatformVideoDecoderImpl);
};
diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc
index 4adc7b0..087e292 100644
--- a/content/renderer/pepper_plugin_delegate_impl.cc
+++ b/content/renderer/pepper_plugin_delegate_impl.cc
@@ -829,8 +829,10 @@ webkit::ppapi::PluginDelegate::PlatformContext3D*
webkit::ppapi::PluginDelegate::PlatformVideoDecoder*
PepperPluginDelegateImpl::CreateVideoDecoder(
media::VideoDecodeAccelerator::Client* client,
- int command_buffer_route_id) {
- return new PlatformVideoDecoderImpl(client, command_buffer_route_id);
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper) {
+ return new PlatformVideoDecoderImpl(
+ client, command_buffer_route_id, cmd_buffer_helper);
}
void PepperPluginDelegateImpl::NumberOfFindResultsChanged(int identifier,
diff --git a/content/renderer/pepper_plugin_delegate_impl.h b/content/renderer/pepper_plugin_delegate_impl.h
index 2c7bf47..e920c46 100644
--- a/content/renderer/pepper_plugin_delegate_impl.h
+++ b/content/renderer/pepper_plugin_delegate_impl.h
@@ -29,6 +29,10 @@ class Point;
class Rect;
}
+namespace gpu {
+class CommandBufferHelper;
+}
+
namespace IPC {
struct ChannelHandle;
}
@@ -180,7 +184,8 @@ class PepperPluginDelegateImpl
virtual PlatformContext3D* CreateContext3D();
virtual PlatformVideoDecoder* CreateVideoDecoder(
media::VideoDecodeAccelerator::Client* client,
- int command_buffer_route_id);
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper);
virtual PpapiBroker* ConnectToPpapiBroker(
webkit::ppapi::PPB_Broker_Impl* client);
virtual void NumberOfFindResultsChanged(int identifier,
diff --git a/gpu/command_buffer/common/command_buffer.cc b/gpu/command_buffer/common/command_buffer.cc
new file mode 100644
index 0000000..5a12ed1
--- /dev/null
+++ b/gpu/command_buffer/common/command_buffer.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2011 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 "../common/command_buffer.h"
+#include "../common/logging.h"
+
+namespace gpu {
+
+ReadWriteTokens::ReadWriteTokens()
+ : last_token_read(-1), last_token_written(-1) {
+}
+
+ReadWriteTokens::ReadWriteTokens(int32 read, int32 written)
+ : last_token_read(read), last_token_written(written) {
+}
+
+bool ReadWriteTokens::InRange(int32 token) const {
+ int32 min = last_token_read;
+ int32 max = last_token_written;
+ GPU_DCHECK_GE(min, 0);
+ GPU_DCHECK_GE(max, 0);
+ if (min <= max) {
+ // token should be in [min .. max)
+ return (token >= min) && (token < max);
+ }
+ // token should be in [0 .. max) or [min .. wrap token)
+ return (token >= min) || (token < max);
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
index d438f72..d5fb24d 100644
--- a/gpu/command_buffer/common/command_buffer.h
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -123,6 +123,27 @@ class CommandBuffer {
DISALLOW_COPY_AND_ASSIGN(CommandBuffer);
};
+// Synchronizing other mechanisms (such as IPC) with the CommandBuffer requires
+// inserting (writing) a token into the buffer and knowing what the last token
+// read at that point was. ReadWriteTokens is a convenience struct for passing
+// these pairs around. Expected usage is to compare a current token to
+// [last_token_read,last_token_written).
+class ReadWriteTokens {
+ public:
+ ReadWriteTokens(int32 read, int32 written);
+ // Required to support pickling. Use by anything else will DCHECK in InRange.
+ ReadWriteTokens();
+
+ // Return true iff |value| is in the range described by |tokens|, accounting
+ // for (up to) one wrap-around.
+ bool InRange(int32 token) const;
+
+ // These want to be private (and const) but can't in order to support
+ // pickling.
+ int32 last_token_read;
+ int32 last_token_written;
+};
+
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_COMMON_COMMAND_BUFFER_H_
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index a67fd3a..1ff60d4 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -273,6 +273,8 @@ Buffer GpuScheduler::GetSharedMemoryBuffer(int32 shm_id) {
void GpuScheduler::set_token(int32 token) {
command_buffer_->SetToken(token);
+ if (!set_token_callback_.is_null())
+ set_token_callback_.Run(token);
}
bool GpuScheduler::SetGetOffset(int32 offset) {
@@ -311,6 +313,12 @@ void GpuScheduler::SetCommandProcessedCallback(
command_processed_callback_.reset(callback);
}
+void GpuScheduler::SetTokenCallback(
+ const base::Callback<void(int32)>& callback) {
+ DCHECK(set_token_callback_.is_null());
+ set_token_callback_ = callback;
+}
+
void GpuScheduler::ScheduleProcessCommands() {
MessageLoop::current()->PostTask(
FROM_HERE,
diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h
index a5d10ae..eedae30 100644
--- a/gpu/command_buffer/service/gpu_scheduler.h
+++ b/gpu/command_buffer/service/gpu_scheduler.h
@@ -158,6 +158,11 @@ class GpuScheduler : public CommandBufferEngine {
decoder_->SetLatchCallback(callback);
}
+ // Sets a callback which is called when set_token() is called, and passes the
+ // just-set token to the callback. DCHECKs that no callback has previously
+ // been registered for this notification.
+ void SetTokenCallback(const base::Callback<void(int32)>& callback);
+
// Get the GLES2Decoder associated with this scheduler.
gles2::GLES2Decoder* decoder() const { return decoder_.get(); }
@@ -218,6 +223,7 @@ class GpuScheduler : public CommandBufferEngine {
scoped_ptr<Callback1<gfx::Size>::Type> wrapped_resize_callback_;
scoped_ptr<Callback0::Type> wrapped_swap_buffers_callback_;
scoped_ptr<Callback0::Type> command_processed_callback_;
+ base::Callback<void(int32)> set_token_callback_;
};
} // namespace gpu
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 6e4a2c3a0..d9f0efa 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -46,6 +46,7 @@
'command_buffer/common/buffer.h',
'command_buffer/common/cmd_buffer_common.h',
'command_buffer/common/cmd_buffer_common.cc',
+ 'command_buffer/common/command_buffer.cc',
'command_buffer/common/command_buffer.h',
'command_buffer/common/constants.h',
'command_buffer/common/gles2_cmd_ids_autogen.h',
diff --git a/media/video/video_decode_accelerator.h b/media/video/video_decode_accelerator.h
index c50da97..ab0d471 100644
--- a/media/video/video_decode_accelerator.h
+++ b/media/video/video_decode_accelerator.h
@@ -255,9 +255,7 @@ class VideoDecodeAccelerator {
// bitstream buffer id.
// Parameters:
// |bitstream_buffer| is the input bitstream that is sent for decoding.
- //
- // Returns true when command successfully accepted. Otherwise false.
- virtual bool Decode(const BitstreamBuffer& bitstream_buffer) = 0;
+ virtual void Decode(const BitstreamBuffer& bitstream_buffer) = 0;
// Assigns a set of picture buffers to the video decoder.
// AssignGLESBuffers assigns texture-backed buffers.
@@ -285,17 +283,13 @@ class VideoDecodeAccelerator {
// pictures and buffers held inside the decoder and returning of bitstream
// buffers using the callbacks implemented by the plug-in. Once done with
// flushing, the decode will call NotifyFlushDone().
- //
- // Returns true when command successfully accepted. Otherwise false.
- virtual bool Flush() = 0;
+ virtual void Flush() = 0;
// Aborts the decoder. Decode will abort the decoding as soon as possible and
// will not output anything. NotifyAbortDone() is called as soon as abort has
// been finished. After abort all buffers can be considered dismissed, even
// when there has not been callbacks to dismiss them.
- //
- // Returns true when command successfully accepted. Otherwise false.
- virtual bool Abort() = 0;
+ virtual void Abort() = 0;
};
} // namespace media
diff --git a/ppapi/examples/gles2/gles2.cc b/ppapi/examples/gles2/gles2.cc
index 0499958..657159b 100644
--- a/ppapi/examples/gles2/gles2.cc
+++ b/ppapi/examples/gles2/gles2.cc
@@ -73,14 +73,6 @@ class GLES2DemoInstance : public pp::Instance, public pp::Graphics3DClient_Dev,
GLuint vertex_buffers[2];
};
- // Serialize PPB_Video_Decoder_Dev operations w.r.t. GPU command buffer.
- // TODO(fischman): figure out how much of this is actually necessary.
- // Probably any necessary serialization ought to be happening in the
- // PPAPI implementation, not in the plugin!
- void FinishGL() {
- gles2_if_->Finish(context_->pp_resource());
- }
-
// Initialize Video Decoder.
void InitializeDecoder();
@@ -272,7 +264,6 @@ void GLES2DemoInstance::ProvidePictureBuffers(
buffers.push_back(buffer);
assert(buffers_by_id_.insert(std::make_pair(id, buffer)).second);
}
- FinishGL();
video_decoder_->AssignGLESBuffers(buffers);
}
@@ -282,8 +273,6 @@ void GLES2DemoInstance::DismissPictureBuffer(
assert(it != buffers_by_id_.end());
DeleteTexture(it->second.texture_id);
buffers_by_id_.erase(it);
-
- FinishGL();
}
void GLES2DemoInstance::PictureReady(
@@ -340,18 +329,14 @@ void GLES2DemoInstance::InitGL() {
assertNoGLError();
CreateGLObjects();
-
- FinishGL();
}
void GLES2DemoInstance::Render(const PP_GLESBuffer_Dev& buffer) {
if (is_painting_) {
// We are dropping frames if we don't render fast enough -
// that is why sometimes the last frame rendered is < 249.
- if (video_decoder_) {
- FinishGL();
+ if (video_decoder_)
video_decoder_->ReusePictureBuffer(buffer.info.id);
- }
return;
}
is_painting_ = true;
@@ -369,7 +354,6 @@ void GLES2DemoInstance::Render(const PP_GLESBuffer_Dev& buffer) {
void GLES2DemoInstance::PaintFinished(int32_t result, int picture_buffer_id) {
is_painting_ = false;
- FinishGL();
if (video_decoder_)
video_decoder_->ReusePictureBuffer(picture_buffer_id);
}
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.cc b/webkit/plugins/ppapi/mock_plugin_delegate.cc
index 476d4c9..1270504 100644
--- a/webkit/plugins/ppapi/mock_plugin_delegate.cc
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.cc
@@ -46,7 +46,8 @@ MockPluginDelegate::PlatformContext3D* MockPluginDelegate::CreateContext3D() {
MockPluginDelegate::PlatformVideoDecoder*
MockPluginDelegate::CreateVideoDecoder(
media::VideoDecodeAccelerator::Client* client,
- int command_buffer_route_id) {
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper) {
return NULL;
}
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.h b/webkit/plugins/ppapi/mock_plugin_delegate.h
index 0b91348..c58d4fd 100644
--- a/webkit/plugins/ppapi/mock_plugin_delegate.h
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.h
@@ -7,6 +7,10 @@
#include "webkit/plugins/ppapi/plugin_delegate.h"
+namespace gpu {
+class CommandBufferHelper;
+}
+
namespace webkit {
namespace ppapi {
@@ -24,7 +28,8 @@ class MockPluginDelegate : public PluginDelegate {
virtual PlatformContext3D* CreateContext3D();
virtual PlatformVideoDecoder* CreateVideoDecoder(
media::VideoDecodeAccelerator::Client* client,
- int command_buffer_route_id);
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper);
virtual PlatformAudio* CreateAudio(uint32_t sample_rate,
uint32_t sample_count,
PlatformAudio::Client* client);
diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h
index c72eaaa..dae68a8 100644
--- a/webkit/plugins/ppapi/plugin_delegate.h
+++ b/webkit/plugins/ppapi/plugin_delegate.h
@@ -46,6 +46,7 @@ class Rect;
namespace gpu {
class CommandBuffer;
+class CommandBufferHelper;
}
namespace ppapi {
@@ -263,7 +264,8 @@ class PluginDelegate {
// The caller will own the pointer returned from this.
virtual PlatformVideoDecoder* CreateVideoDecoder(
media::VideoDecodeAccelerator::Client* client,
- int command_buffer_route_id) = 0;
+ int32 command_buffer_route_id,
+ gpu::CommandBufferHelper* cmd_buffer_helper) = 0;
// The caller is responsible for calling Shutdown() on the returned pointer
// to clean up the corresponding resources allocated during this call.
diff --git a/webkit/plugins/ppapi/ppb_video_decoder_impl.cc b/webkit/plugins/ppapi/ppb_video_decoder_impl.cc
index d1e41d4..f5f6126 100644
--- a/webkit/plugins/ppapi/ppb_video_decoder_impl.cc
+++ b/webkit/plugins/ppapi/ppb_video_decoder_impl.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/message_loop.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
#include "media/video/picture.h"
#include "ppapi/c/dev/pp_video_dev.h"
#include "ppapi/c/dev/ppb_video_decoder_dev.h"
@@ -65,6 +66,7 @@ void CopyToConfigList(
PPB_VideoDecoder_Impl::PPB_VideoDecoder_Impl(PluginInstance* instance)
: Resource(instance),
callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+ context3d_id_(0),
abort_callback_(PP_BlockUntilComplete()),
flush_callback_(PP_BlockUntilComplete()) {
ppp_videodecoder_ =
@@ -73,6 +75,8 @@ PPB_VideoDecoder_Impl::PPB_VideoDecoder_Impl(PluginInstance* instance)
}
PPB_VideoDecoder_Impl::~PPB_VideoDecoder_Impl() {
+ if (context3d_id_)
+ ResourceTracker::Get()->UnrefResource(context3d_id_);
}
PPB_VideoDecoder_API* PPB_VideoDecoder_Impl::AsPPB_VideoDecoder_API() {
@@ -120,6 +124,8 @@ int32_t PPB_VideoDecoder_Impl::Initialize(
PPB_Context3D_Impl* context3d =
static_cast<PPB_Context3D_Impl*>(enter.object());
+ context3d_id_ = context_id;
+ ResourceTracker::Get()->AddRefResource(context3d_id_);
int command_buffer_route_id =
context3d->platform_context()->GetCommandBufferRouteId();
if (command_buffer_route_id == 0)
@@ -127,7 +133,7 @@ int32_t PPB_VideoDecoder_Impl::Initialize(
platform_video_decoder_.reset(
instance()->delegate()->CreateVideoDecoder(
- this, command_buffer_route_id));
+ this, command_buffer_route_id, context3d->gles2_impl()->helper()));
if (!platform_video_decoder_.get())
return PP_ERROR_FAILED;
@@ -160,10 +166,8 @@ int32_t PPB_VideoDecoder_Impl::Decode(
CHECK(bitstream_buffer_callbacks_.insert(std::make_pair(
bitstream_buffer->id, callback)).second);
- if (platform_video_decoder_->Decode(decode_buffer))
- return PP_OK_COMPLETIONPENDING;
- else
- return PP_ERROR_FAILED;
+ platform_video_decoder_->Decode(decode_buffer);
+ return PP_OK_COMPLETIONPENDING;
}
void PPB_VideoDecoder_Impl::AssignGLESBuffers(
@@ -223,10 +227,8 @@ int32_t PPB_VideoDecoder_Impl::Flush(PP_CompletionCallback callback) {
// TODO(vmr): Check for current flush/abort operations.
flush_callback_ = callback;
- if (platform_video_decoder_->Flush())
- return PP_OK_COMPLETIONPENDING;
- else
- return PP_ERROR_FAILED;
+ platform_video_decoder_->Flush();
+ return PP_OK_COMPLETIONPENDING;
}
int32_t PPB_VideoDecoder_Impl::Abort(PP_CompletionCallback callback) {
@@ -237,10 +239,8 @@ int32_t PPB_VideoDecoder_Impl::Abort(PP_CompletionCallback callback) {
// TODO(vmr): Check for current flush/abort operations.
abort_callback_ = callback;
- if (platform_video_decoder_->Abort())
- return PP_OK_COMPLETIONPENDING;
- else
- return PP_ERROR_FAILED;
+ platform_video_decoder_->Abort();
+ return PP_OK_COMPLETIONPENDING;
}
void PPB_VideoDecoder_Impl::ProvidePictureBuffers(
diff --git a/webkit/plugins/ppapi/ppb_video_decoder_impl.h b/webkit/plugins/ppapi/ppb_video_decoder_impl.h
index 5b4a326..75db896 100644
--- a/webkit/plugins/ppapi/ppb_video_decoder_impl.h
+++ b/webkit/plugins/ppapi/ppb_video_decoder_impl.h
@@ -84,6 +84,10 @@ class PPB_VideoDecoder_Impl : public Resource,
// Factory to produce our callbacks.
base::ScopedCallbackFactory<PPB_VideoDecoder_Impl> callback_factory_;
+ // The resource ID of the underlying Context3d object being used. Used only
+ // for reference counting to keep it alive for the lifetime of |*this|.
+ PP_Resource context3d_id_;
+
PP_CompletionCallback initialization_callback_;
PP_CompletionCallback abort_callback_;
PP_CompletionCallback flush_callback_;
diff --git a/webkit/plugins/ppapi/resource_tracker.h b/webkit/plugins/ppapi/resource_tracker.h
index b728895..84669e1 100644
--- a/webkit/plugins/ppapi/resource_tracker.h
+++ b/webkit/plugins/ppapi/resource_tracker.h
@@ -175,10 +175,11 @@ class ResourceTracker : public ::ppapi::TrackerBase {
// For each PP_Resource, keep the Resource* (as refptr) and plugin use count.
// This use count is different then Resource's RefCount, and is manipulated
- // using this RefResource/UnrefResource. When it drops to zero, we just remove
- // the resource from this resource tracker, but the resource object will be
- // alive so long as some scoped_refptr still holds it's reference. This
- // prevents plugins from forcing destruction of Resource objects.
+ // using this AddRefResource/UnrefResource. When it drops to zero, we just
+ // remove the resource from this resource tracker, but the resource object
+ // will be alive so long as some scoped_refptr still holds it's
+ // reference. This prevents plugins from forcing destruction of Resource
+ // objects.
typedef std::pair<scoped_refptr<Resource>, size_t> ResourceAndRefCount;
typedef base::hash_map<PP_Resource, ResourceAndRefCount> ResourceMap;
ResourceMap live_resources_;