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 std::vector
<gfx::Size
> sizes
;
107 for (uint32 i
= 0; i
< buffers
.size(); i
++) {
108 const media::PictureBuffer
& buffer
= buffers
[i
];
109 texture_ids
.push_back(buffer
.texture_id());
110 buffer_ids
.push_back(buffer
.id());
111 sizes
.push_back(buffer
.size());
113 Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
114 decoder_route_id_
, buffer_ids
, texture_ids
, sizes
));
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());
150 DCHECK(!client_
) << "destructor called without Destroy being called!";
153 channel_
->RemoveRoute(decoder_route_id_
);
155 impl_
->RemoveDeletionObserver(this);
158 void GpuVideoDecodeAcceleratorHost::Send(IPC::Message
* message
) {
159 // After OnChannelError is called, the client should no longer send
160 // messages to the gpu channel through this object. But queued posted tasks
161 // can still be draining, so we're forgiving and simply ignore them.
163 uint32 message_type
= message
->type();
166 DLOG(ERROR
) << "Send(" << message_type
<< ") after error ignored";
168 } else if (!channel_
->Send(message
)) {
169 DLOG(ERROR
) << "Send(" << message_type
<< ") failed";
172 // See OnErrorNotification for why this needs to be the last thing in this
175 OnErrorNotification(PLATFORM_FAILURE
);
178 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
179 int32 bitstream_buffer_id
) {
180 DCHECK(CalledOnValidThread());
182 client_
->NotifyEndOfBitstreamBuffer(bitstream_buffer_id
);
185 void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
186 uint32 num_requested_buffers
,
187 const gfx::Size
& buffer_size
,
188 uint32 texture_target
) {
189 DCHECK(CalledOnValidThread());
191 client_
->ProvidePictureBuffers(
192 num_requested_buffers
, buffer_size
, 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