1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "content/common/gpu/client/gpu_channel_host.h"
11 #include "content/common/gpu/gpu_messages.h"
12 #include "content/common/view_messages.h"
13 #include "ipc/ipc_message_macros.h"
14 #include "ipc/ipc_message_utils.h"
17 #include "content/public/common/sandbox_init.h"
20 using media::VideoDecodeAccelerator;
23 GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
24 GpuChannelHost* channel,
25 int32 decoder_route_id,
26 CommandBufferProxyImpl* impl)
28 decoder_route_id_(decoder_route_id),
32 channel_->AddRoute(decoder_route_id, base::AsWeakPtr(this));
33 impl_->AddDeletionObserver(this);
36 void GpuVideoDecodeAcceleratorHost::OnChannelError() {
37 DLOG(ERROR) << "GpuVideoDecodeAcceleratorHost::OnChannelError()";
39 channel_->RemoveRoute(decoder_route_id_);
42 // See OnErrorNotification for why this needs to be the last thing in this
44 OnErrorNotification(PLATFORM_FAILURE);
47 bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
48 DCHECK(CalledOnValidThread());
50 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg)
51 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
52 OnBitstreamBufferProcessed)
53 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers,
54 OnProvidePictureBuffer)
55 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady,
57 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone,
59 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone,
61 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification,
63 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
64 OnDismissPictureBuffer)
65 IPC_MESSAGE_UNHANDLED(handled = false)
68 // See OnErrorNotification for why |this| mustn't be used after
69 // OnErrorNotification might have been called above.
73 bool GpuVideoDecodeAcceleratorHost::Initialize(media::VideoCodecProfile profile,
79 void GpuVideoDecodeAcceleratorHost::Decode(
80 const media::BitstreamBuffer& bitstream_buffer) {
81 DCHECK(CalledOnValidThread());
82 // Can happen if a decode task was posted before an error was delivered.
86 base::SharedMemoryHandle handle = channel_->ShareToGpuProcess(
87 bitstream_buffer.handle());
88 if (!base::SharedMemory::IsHandleValid(handle)) {
89 NOTREACHED() << "Failed to duplicate buffer handler";
93 Send(new AcceleratedVideoDecoderMsg_Decode(
94 decoder_route_id_, handle, bitstream_buffer.id(),
95 bitstream_buffer.size()));
98 void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
99 const std::vector<media::PictureBuffer>& buffers) {
100 DCHECK(CalledOnValidThread());
101 // Rearrange data for IPC command.
102 std::vector<int32> buffer_ids;
103 std::vector<uint32> texture_ids;
104 for (uint32 i = 0; i < buffers.size(); i++) {
105 const media::PictureBuffer& buffer = buffers[i];
106 if (buffer.size() != picture_buffer_dimensions_) {
107 OnErrorNotification(INVALID_ARGUMENT);
110 texture_ids.push_back(buffer.texture_id());
111 buffer_ids.push_back(buffer.id());
113 Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
114 decoder_route_id_, buffer_ids, texture_ids));
117 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
118 int32 picture_buffer_id) {
119 DCHECK(CalledOnValidThread());
120 Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
121 decoder_route_id_, picture_buffer_id));
124 void GpuVideoDecodeAcceleratorHost::Flush() {
125 DCHECK(CalledOnValidThread());
126 Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_));
129 void GpuVideoDecodeAcceleratorHost::Reset() {
130 DCHECK(CalledOnValidThread());
131 Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_));
134 void GpuVideoDecodeAcceleratorHost::Destroy() {
135 DCHECK(CalledOnValidThread());
137 Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
141 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
144 // The CommandBufferProxyImpl is going away; error out this VDA.
148 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
149 DCHECK(CalledOnValidThread());
152 channel_->RemoveRoute(decoder_route_id_);
154 impl_->RemoveDeletionObserver(this);
157 void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) {
158 // After OnChannelError is called, the client should no longer send
159 // messages to the gpu channel through this object. But queued posted tasks
160 // can still be draining, so we're forgiving and simply ignore them.
162 uint32 message_type = message->type();
165 DLOG(ERROR) << "Send(" << message_type << ") after error ignored";
167 } else if (!channel_->Send(message)) {
168 DLOG(ERROR) << "Send(" << message_type << ") failed";
171 // See OnErrorNotification for why this needs to be the last thing in this
174 OnErrorNotification(PLATFORM_FAILURE);
177 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
178 int32 bitstream_buffer_id) {
179 DCHECK(CalledOnValidThread());
181 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
184 void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
185 uint32 num_requested_buffers,
186 const gfx::Size& dimensions,
187 uint32 texture_target) {
188 DCHECK(CalledOnValidThread());
189 picture_buffer_dimensions_ = dimensions;
191 client_->ProvidePictureBuffers(
192 num_requested_buffers, dimensions, texture_target);
196 void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
197 int32 picture_buffer_id) {
198 DCHECK(CalledOnValidThread());
200 client_->DismissPictureBuffer(picture_buffer_id);
203 void GpuVideoDecodeAcceleratorHost::OnPictureReady(
204 int32 picture_buffer_id, int32 bitstream_buffer_id) {
205 DCHECK(CalledOnValidThread());
208 media::Picture picture(picture_buffer_id, bitstream_buffer_id);
209 client_->PictureReady(picture);
212 void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
213 DCHECK(CalledOnValidThread());
215 client_->NotifyFlushDone();
218 void GpuVideoDecodeAcceleratorHost::OnResetDone() {
219 DCHECK(CalledOnValidThread());
221 client_->NotifyResetDone();
224 void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) {
225 DCHECK(CalledOnValidThread());
229 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
230 // last thing done on this stack!
231 media::VideoDecodeAccelerator::Client* client = NULL;
232 std::swap(client, client_);
234 static_cast<media::VideoDecodeAccelerator::Error>(error));
237 } // namespace content