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 VideoDecodeAccelerator::Client* client,
27 CommandBufferProxyImpl* impl)
29 decoder_route_id_(decoder_route_id),
34 channel_->AddRoute(decoder_route_id, base::AsWeakPtr(this));
35 impl_->AddDeletionObserver(this);
38 void GpuVideoDecodeAcceleratorHost::OnChannelError() {
39 DLOG(ERROR) << "GpuVideoDecodeAcceleratorHost::OnChannelError()";
41 channel_->RemoveRoute(decoder_route_id_);
44 // See OnErrorNotification for why this needs to be the last thing in this
46 OnErrorNotification(PLATFORM_FAILURE);
49 bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
50 DCHECK(CalledOnValidThread());
52 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg)
53 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
54 OnBitstreamBufferProcessed)
55 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers,
56 OnProvidePictureBuffer)
57 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady,
59 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone,
61 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone,
63 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification,
65 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
66 OnDismissPictureBuffer)
67 IPC_MESSAGE_UNHANDLED(handled = false)
70 // See OnErrorNotification for why |this| mustn't be used after
71 // OnErrorNotification might have been called above.
75 bool GpuVideoDecodeAcceleratorHost::Initialize(
76 media::VideoCodecProfile profile) {
81 void GpuVideoDecodeAcceleratorHost::Decode(
82 const media::BitstreamBuffer& bitstream_buffer) {
83 DCHECK(CalledOnValidThread());
84 // Can happen if a decode task was posted before an error was delivered.
88 base::SharedMemoryHandle handle = channel_->ShareToGpuProcess(
89 bitstream_buffer.handle());
90 if (!base::SharedMemory::IsHandleValid(handle)) {
91 NOTREACHED() << "Failed to duplicate buffer handler";
95 Send(new AcceleratedVideoDecoderMsg_Decode(
96 decoder_route_id_, handle, bitstream_buffer.id(),
97 bitstream_buffer.size()));
100 void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
101 const std::vector<media::PictureBuffer>& buffers) {
102 DCHECK(CalledOnValidThread());
103 // Rearrange data for IPC command.
104 std::vector<int32> buffer_ids;
105 std::vector<uint32> texture_ids;
106 for (uint32 i = 0; i < buffers.size(); i++) {
107 const media::PictureBuffer& buffer = buffers[i];
108 if (buffer.size() != picture_buffer_dimensions_) {
109 OnErrorNotification(INVALID_ARGUMENT);
112 texture_ids.push_back(buffer.texture_id());
113 buffer_ids.push_back(buffer.id());
115 Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
116 decoder_route_id_, buffer_ids, texture_ids));
119 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
120 int32 picture_buffer_id) {
121 DCHECK(CalledOnValidThread());
122 Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
123 decoder_route_id_, picture_buffer_id));
126 void GpuVideoDecodeAcceleratorHost::Flush() {
127 DCHECK(CalledOnValidThread());
128 Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_));
131 void GpuVideoDecodeAcceleratorHost::Reset() {
132 DCHECK(CalledOnValidThread());
133 Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_));
136 void GpuVideoDecodeAcceleratorHost::Destroy() {
137 DCHECK(CalledOnValidThread());
139 Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
143 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
146 // The CommandBufferProxyImpl is going away; error out this VDA.
150 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
151 DCHECK(CalledOnValidThread());
152 DCHECK(!client_) << "destructor called without Destroy being called!";
155 channel_->RemoveRoute(decoder_route_id_);
157 impl_->RemoveDeletionObserver(this);
160 void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) {
161 // After OnChannelError is called, the client should no longer send
162 // messages to the gpu channel through this object. But queued posted tasks
163 // can still be draining, so we're forgiving and simply ignore them.
165 uint32 message_type = message->type();
168 DLOG(ERROR) << "Send(" << message_type << ") after error ignored";
170 } else if (!channel_->Send(message)) {
171 DLOG(ERROR) << "Send(" << message_type << ") failed";
174 // See OnErrorNotification for why this needs to be the last thing in this
177 OnErrorNotification(PLATFORM_FAILURE);
180 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
181 int32 bitstream_buffer_id) {
182 DCHECK(CalledOnValidThread());
184 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
187 void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
188 uint32 num_requested_buffers,
189 const gfx::Size& dimensions,
190 uint32 texture_target) {
191 DCHECK(CalledOnValidThread());
192 picture_buffer_dimensions_ = dimensions;
194 client_->ProvidePictureBuffers(
195 num_requested_buffers, dimensions, texture_target);
199 void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
200 int32 picture_buffer_id) {
201 DCHECK(CalledOnValidThread());
203 client_->DismissPictureBuffer(picture_buffer_id);
206 void GpuVideoDecodeAcceleratorHost::OnPictureReady(
207 int32 picture_buffer_id, int32 bitstream_buffer_id) {
208 DCHECK(CalledOnValidThread());
211 media::Picture picture(picture_buffer_id, bitstream_buffer_id);
212 client_->PictureReady(picture);
215 void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
216 DCHECK(CalledOnValidThread());
218 client_->NotifyFlushDone();
221 void GpuVideoDecodeAcceleratorHost::OnResetDone() {
222 DCHECK(CalledOnValidThread());
224 client_->NotifyResetDone();
227 void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) {
228 DCHECK(CalledOnValidThread());
232 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
233 // last thing done on this stack!
234 media::VideoDecodeAccelerator::Client* client = NULL;
235 std::swap(client, client_);
237 static_cast<media::VideoDecodeAccelerator::Error>(error));
240 } // namespace content