Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / content / common / gpu / client / gpu_video_decode_accelerator_host.cc
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
20 using media::VideoDecodeAccelerator;
21 namespace content {
22
23 GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
24     GpuChannelHost* channel,
25     int32 decoder_route_id,
26     CommandBufferProxyImpl* impl)
27     : channel_(channel),
28       decoder_route_id_(decoder_route_id),
29       client_(NULL),
30       impl_(impl) {
31   DCHECK(channel_);
32   channel_->AddRoute(decoder_route_id, base::AsWeakPtr(this));
33   impl_->AddDeletionObserver(this);
34 }
35
36 void GpuVideoDecodeAcceleratorHost::OnChannelError() {
37   DLOG(ERROR) << "GpuVideoDecodeAcceleratorHost::OnChannelError()";
38   if (channel_) {
39     channel_->RemoveRoute(decoder_route_id_);
40     channel_ = NULL;
41   }
42   // See OnErrorNotification for why this needs to be the last thing in this
43   // function.
44   OnErrorNotification(PLATFORM_FAILURE);
45 }
46
47 bool 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   // See OnErrorNotification for why |this| mustn't be used after
69   // OnErrorNotification might have been called above.
70   return handled;
71 }
72
73 bool GpuVideoDecodeAcceleratorHost::Initialize(media::VideoCodecProfile profile,
74                                                Client* client) {
75   client_ = client;
76   return true;
77 }
78
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.
83   if (!channel_)
84     return;
85
86   base::SharedMemoryHandle handle = channel_->ShareToGpuProcess(
87       bitstream_buffer.handle());
88   if (!base::SharedMemory::IsHandleValid(handle)) {
89     NOTREACHED() << "Failed to duplicate buffer handler";
90     return;
91   }
92
93   Send(new AcceleratedVideoDecoderMsg_Decode(
94       decoder_route_id_, handle, bitstream_buffer.id(),
95       bitstream_buffer.size()));
96 }
97
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);
108       return;
109     }
110     texture_ids.push_back(buffer.texture_id());
111     buffer_ids.push_back(buffer.id());
112   }
113   Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
114       decoder_route_id_, buffer_ids, texture_ids));
115 }
116
117 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
118     int32 picture_buffer_id) {
119   DCHECK(CalledOnValidThread());
120   Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
121       decoder_route_id_, picture_buffer_id));
122 }
123
124 void GpuVideoDecodeAcceleratorHost::Flush() {
125   DCHECK(CalledOnValidThread());
126   Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_));
127 }
128
129 void GpuVideoDecodeAcceleratorHost::Reset() {
130   DCHECK(CalledOnValidThread());
131   Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_));
132 }
133
134 void GpuVideoDecodeAcceleratorHost::Destroy() {
135   DCHECK(CalledOnValidThread());
136   client_ = NULL;
137   Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
138   delete this;
139 }
140
141 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
142   impl_ = NULL;
143
144   // The CommandBufferProxyImpl is going away; error out this VDA.
145   OnChannelError();
146 }
147
148 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
149   DCHECK(CalledOnValidThread());
150
151   if (channel_)
152     channel_->RemoveRoute(decoder_route_id_);
153   if (impl_)
154     impl_->RemoveDeletionObserver(this);
155 }
156
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.
161   bool error = false;
162   uint32 message_type = message->type();
163   if (!channel_) {
164     delete message;
165     DLOG(ERROR) << "Send(" << message_type << ") after error ignored";
166     error = true;
167   } else if (!channel_->Send(message)) {
168     DLOG(ERROR) << "Send(" << message_type << ") failed";
169     error = true;
170   }
171   // See OnErrorNotification for why this needs to be the last thing in this
172   // function.
173   if (error)
174     OnErrorNotification(PLATFORM_FAILURE);
175 }
176
177 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
178     int32 bitstream_buffer_id) {
179   DCHECK(CalledOnValidThread());
180   if (client_)
181     client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
182 }
183
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;
190   if (client_) {
191     client_->ProvidePictureBuffers(
192         num_requested_buffers, dimensions, texture_target);
193   }
194 }
195
196 void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
197     int32 picture_buffer_id) {
198   DCHECK(CalledOnValidThread());
199   if (client_)
200     client_->DismissPictureBuffer(picture_buffer_id);
201 }
202
203 void GpuVideoDecodeAcceleratorHost::OnPictureReady(
204     int32 picture_buffer_id, int32 bitstream_buffer_id) {
205   DCHECK(CalledOnValidThread());
206   if (!client_)
207     return;
208   media::Picture picture(picture_buffer_id, bitstream_buffer_id);
209   client_->PictureReady(picture);
210 }
211
212 void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
213   DCHECK(CalledOnValidThread());
214   if (client_)
215     client_->NotifyFlushDone();
216 }
217
218 void GpuVideoDecodeAcceleratorHost::OnResetDone() {
219   DCHECK(CalledOnValidThread());
220   if (client_)
221     client_->NotifyResetDone();
222 }
223
224 void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) {
225   DCHECK(CalledOnValidThread());
226   if (!client_)
227     return;
228
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_);
233   client->NotifyError(
234       static_cast<media::VideoDecodeAccelerator::Error>(error));
235 }
236
237 }  // namespace content