gpu_video_decode_accelerator_host.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
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.
4
5#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
6
7#include "base/bind.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"
15
16#if defined(OS_WIN)
17#include "content/public/common/sandbox_init.h"
18#endif  // OS_WIN
19
20using media::VideoDecodeAccelerator;
21namespace content {
22
23GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
24    GpuChannelHost* channel,
25    int32 decoder_route_id,
26    VideoDecodeAccelerator::Client* client,
27    CommandBufferProxyImpl* impl)
28    : channel_(channel),
29      decoder_route_id_(decoder_route_id),
30      client_(client),
31      impl_(impl) {
32  DCHECK(channel_);
33  DCHECK(client_);
34  channel_->AddRoute(decoder_route_id, base::AsWeakPtr(this));
35  impl_->AddDeletionObserver(this);
36}
37
38void GpuVideoDecodeAcceleratorHost::OnChannelError() {
39  DLOG(ERROR) << "GpuVideoDecodeAcceleratorHost::OnChannelError()";
40  OnErrorNotification(PLATFORM_FAILURE);
41  if (channel_) {
42    channel_->RemoveRoute(decoder_route_id_);
43    channel_ = NULL;
44  }
45}
46
47bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
48  DCHECK(CalledOnValidThread());
49  bool handled = true;
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,
56                        OnPictureReady)
57    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone,
58                        OnFlushDone)
59    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone,
60                        OnResetDone)
61    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification,
62                        OnErrorNotification)
63    IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
64                        OnDismissPictureBuffer)
65    IPC_MESSAGE_UNHANDLED(handled = false)
66  IPC_END_MESSAGE_MAP()
67  DCHECK(handled);
68  return handled;
69}
70
71bool GpuVideoDecodeAcceleratorHost::Initialize(
72    media::VideoCodecProfile profile) {
73  NOTREACHED();
74  return true;
75}
76
77void GpuVideoDecodeAcceleratorHost::Decode(
78    const media::BitstreamBuffer& bitstream_buffer) {
79  DCHECK(CalledOnValidThread());
80  // Can happen if a decode task was posted before an error was delivered.
81  if (!channel_)
82    return;
83
84  base::SharedMemoryHandle handle = channel_->ShareToGpuProcess(
85      bitstream_buffer.handle());
86  if (!base::SharedMemory::IsHandleValid(handle)) {
87    NOTREACHED() << "Failed to duplicate buffer handler";
88    return;
89  }
90
91  Send(new AcceleratedVideoDecoderMsg_Decode(
92      decoder_route_id_, handle, bitstream_buffer.id(),
93      bitstream_buffer.size()));
94}
95
96void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
97    const std::vector<media::PictureBuffer>& buffers) {
98  DCHECK(CalledOnValidThread());
99  // Rearrange data for IPC command.
100  std::vector<int32> buffer_ids;
101  std::vector<uint32> texture_ids;
102  std::vector<gfx::Size> sizes;
103  for (uint32 i = 0; i < buffers.size(); i++) {
104    const media::PictureBuffer& buffer = buffers[i];
105    texture_ids.push_back(buffer.texture_id());
106    buffer_ids.push_back(buffer.id());
107    sizes.push_back(buffer.size());
108  }
109  Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
110      decoder_route_id_, buffer_ids, texture_ids, sizes));
111}
112
113void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
114    int32 picture_buffer_id) {
115  DCHECK(CalledOnValidThread());
116  Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
117      decoder_route_id_, picture_buffer_id));
118}
119
120void GpuVideoDecodeAcceleratorHost::Flush() {
121  DCHECK(CalledOnValidThread());
122  Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_));
123}
124
125void GpuVideoDecodeAcceleratorHost::Reset() {
126  DCHECK(CalledOnValidThread());
127  Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_));
128}
129
130void GpuVideoDecodeAcceleratorHost::Destroy() {
131  DCHECK(CalledOnValidThread());
132  client_ = NULL;
133  Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
134  delete this;
135}
136
137void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
138  impl_ = NULL;
139
140  // The CommandBufferProxyImpl is going away; error out this VDA.
141  OnChannelError();
142}
143
144GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
145  DCHECK(CalledOnValidThread());
146  DCHECK(!client_) << "destructor called without Destroy being called!";
147
148  if (channel_)
149    channel_->RemoveRoute(decoder_route_id_);
150  if (impl_)
151    impl_->RemoveDeletionObserver(this);
152}
153
154void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) {
155  // After OnChannelError is called, the client should no longer send
156  // messages to the gpu channel through this object.  But queued posted tasks
157  // can still be draining, so we're forgiving and simply ignore them.
158  bool error = false;
159  uint32 message_type = message->type();
160  if (!channel_) {
161    delete message;
162    DLOG(ERROR) << "Send(" << message_type << ") after error ignored";
163    error = true;
164  } else if (!channel_->Send(message)) {
165    DLOG(ERROR) << "Send(" << message_type << ") failed";
166    error = true;
167  }
168  if (error)
169    OnErrorNotification(PLATFORM_FAILURE);
170}
171
172void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
173    int32 bitstream_buffer_id) {
174  DCHECK(CalledOnValidThread());
175  if (client_)
176    client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
177}
178
179void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
180    uint32 num_requested_buffers,
181    const gfx::Size& buffer_size,
182    uint32 texture_target) {
183  DCHECK(CalledOnValidThread());
184  if (client_) {
185    client_->ProvidePictureBuffers(
186        num_requested_buffers, buffer_size, texture_target);
187  }
188}
189
190void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
191    int32 picture_buffer_id) {
192  DCHECK(CalledOnValidThread());
193  if (client_)
194    client_->DismissPictureBuffer(picture_buffer_id);
195}
196
197void GpuVideoDecodeAcceleratorHost::OnPictureReady(
198    int32 picture_buffer_id, int32 bitstream_buffer_id) {
199  DCHECK(CalledOnValidThread());
200  if (!client_)
201    return;
202  media::Picture picture(picture_buffer_id, bitstream_buffer_id);
203  client_->PictureReady(picture);
204}
205
206void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
207  DCHECK(CalledOnValidThread());
208  if (client_)
209    client_->NotifyFlushDone();
210}
211
212void GpuVideoDecodeAcceleratorHost::OnResetDone() {
213  DCHECK(CalledOnValidThread());
214  if (client_)
215    client_->NotifyResetDone();
216}
217
218void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) {
219  DCHECK(CalledOnValidThread());
220  if (!client_)
221    return;
222  client_->NotifyError(
223      static_cast<media::VideoDecodeAccelerator::Error>(error));
224  client_ = NULL;
225}
226
227}  // namespace content
228