- add sources.
[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     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
38 void GpuVideoDecodeAcceleratorHost::OnChannelError() {
39   DLOG(ERROR) << "GpuVideoDecodeAcceleratorHost::OnChannelError()";
40   if (channel_) {
41     channel_->RemoveRoute(decoder_route_id_);
42     channel_ = NULL;
43   }
44   // See OnErrorNotification for why this needs to be the last thing in this
45   // function.
46   OnErrorNotification(PLATFORM_FAILURE);
47 }
48
49 bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
50   DCHECK(CalledOnValidThread());
51   bool handled = true;
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,
58                         OnPictureReady)
59     IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone,
60                         OnFlushDone)
61     IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone,
62                         OnResetDone)
63     IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification,
64                         OnErrorNotification)
65     IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
66                         OnDismissPictureBuffer)
67     IPC_MESSAGE_UNHANDLED(handled = false)
68   IPC_END_MESSAGE_MAP()
69   DCHECK(handled);
70   // See OnErrorNotification for why |this| mustn't be used after
71   // OnErrorNotification might have been called above.
72   return handled;
73 }
74
75 bool GpuVideoDecodeAcceleratorHost::Initialize(
76     media::VideoCodecProfile profile) {
77   NOTREACHED();
78   return true;
79 }
80
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.
85   if (!channel_)
86     return;
87
88   base::SharedMemoryHandle handle = channel_->ShareToGpuProcess(
89       bitstream_buffer.handle());
90   if (!base::SharedMemory::IsHandleValid(handle)) {
91     NOTREACHED() << "Failed to duplicate buffer handler";
92     return;
93   }
94
95   Send(new AcceleratedVideoDecoderMsg_Decode(
96       decoder_route_id_, handle, bitstream_buffer.id(),
97       bitstream_buffer.size()));
98 }
99
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);
110       return;
111     }
112     texture_ids.push_back(buffer.texture_id());
113     buffer_ids.push_back(buffer.id());
114   }
115   Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
116       decoder_route_id_, buffer_ids, texture_ids));
117 }
118
119 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
120     int32 picture_buffer_id) {
121   DCHECK(CalledOnValidThread());
122   Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
123       decoder_route_id_, picture_buffer_id));
124 }
125
126 void GpuVideoDecodeAcceleratorHost::Flush() {
127   DCHECK(CalledOnValidThread());
128   Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_));
129 }
130
131 void GpuVideoDecodeAcceleratorHost::Reset() {
132   DCHECK(CalledOnValidThread());
133   Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_));
134 }
135
136 void GpuVideoDecodeAcceleratorHost::Destroy() {
137   DCHECK(CalledOnValidThread());
138   client_ = NULL;
139   Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
140   delete this;
141 }
142
143 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
144   impl_ = NULL;
145
146   // The CommandBufferProxyImpl is going away; error out this VDA.
147   OnChannelError();
148 }
149
150 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
151   DCHECK(CalledOnValidThread());
152   DCHECK(!client_) << "destructor called without Destroy being called!";
153
154   if (channel_)
155     channel_->RemoveRoute(decoder_route_id_);
156   if (impl_)
157     impl_->RemoveDeletionObserver(this);
158 }
159
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.
164   bool error = false;
165   uint32 message_type = message->type();
166   if (!channel_) {
167     delete message;
168     DLOG(ERROR) << "Send(" << message_type << ") after error ignored";
169     error = true;
170   } else if (!channel_->Send(message)) {
171     DLOG(ERROR) << "Send(" << message_type << ") failed";
172     error = true;
173   }
174   // See OnErrorNotification for why this needs to be the last thing in this
175   // function.
176   if (error)
177     OnErrorNotification(PLATFORM_FAILURE);
178 }
179
180 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
181     int32 bitstream_buffer_id) {
182   DCHECK(CalledOnValidThread());
183   if (client_)
184     client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
185 }
186
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;
193   if (client_) {
194     client_->ProvidePictureBuffers(
195         num_requested_buffers, dimensions, texture_target);
196   }
197 }
198
199 void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
200     int32 picture_buffer_id) {
201   DCHECK(CalledOnValidThread());
202   if (client_)
203     client_->DismissPictureBuffer(picture_buffer_id);
204 }
205
206 void GpuVideoDecodeAcceleratorHost::OnPictureReady(
207     int32 picture_buffer_id, int32 bitstream_buffer_id) {
208   DCHECK(CalledOnValidThread());
209   if (!client_)
210     return;
211   media::Picture picture(picture_buffer_id, bitstream_buffer_id);
212   client_->PictureReady(picture);
213 }
214
215 void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
216   DCHECK(CalledOnValidThread());
217   if (client_)
218     client_->NotifyFlushDone();
219 }
220
221 void GpuVideoDecodeAcceleratorHost::OnResetDone() {
222   DCHECK(CalledOnValidThread());
223   if (client_)
224     client_->NotifyResetDone();
225 }
226
227 void GpuVideoDecodeAcceleratorHost::OnErrorNotification(uint32 error) {
228   DCHECK(CalledOnValidThread());
229   if (!client_)
230     return;
231
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_);
236   client->NotifyError(
237       static_cast<media::VideoDecodeAccelerator::Error>(error));
238 }
239
240 }  // namespace content