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 CommandBufferProxyImpl
* impl
)
27 decoder_route_id_(MSG_ROUTING_NONE
),
30 weak_this_factory_(this) {
33 impl_
->AddDeletionObserver(this);
36 GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
37 DCHECK(CalledOnValidThread());
39 if (channel_
&& decoder_route_id_
!= MSG_ROUTING_NONE
)
40 channel_
->RemoveRoute(decoder_route_id_
);
42 impl_
->RemoveDeletionObserver(this);
45 bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message
& msg
) {
46 DCHECK(CalledOnValidThread());
48 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost
, msg
)
49 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed
,
50 OnBitstreamBufferProcessed
)
51 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers
,
52 OnProvidePictureBuffer
)
53 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady
,
55 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone
,
57 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone
,
59 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification
,
61 IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer
,
62 OnDismissPictureBuffer
)
63 IPC_MESSAGE_UNHANDLED(handled
= false)
66 // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
67 // have been called above.
71 void GpuVideoDecodeAcceleratorHost::OnChannelError() {
72 DCHECK(CalledOnValidThread());
74 if (decoder_route_id_
!= MSG_ROUTING_NONE
)
75 channel_
->RemoveRoute(decoder_route_id_
);
78 DLOG(ERROR
) << "OnChannelError()";
79 PostNotifyError(PLATFORM_FAILURE
);
82 bool GpuVideoDecodeAcceleratorHost::Initialize(media::VideoCodecProfile profile
,
84 DCHECK(CalledOnValidThread());
90 int32 route_id
= channel_
->GenerateRouteID();
91 channel_
->AddRoute(route_id
, weak_this_factory_
.GetWeakPtr());
93 bool succeeded
= false;
94 Send(new GpuCommandBufferMsg_CreateVideoDecoder(impl_
->route_id(), profile
,
95 route_id
, &succeeded
));
98 DLOG(ERROR
) << "Send(GpuCommandBufferMsg_CreateVideoDecoder()) failed";
99 PostNotifyError(PLATFORM_FAILURE
);
100 channel_
->RemoveRoute(route_id
);
103 decoder_route_id_
= route_id
;
107 void GpuVideoDecodeAcceleratorHost::Decode(
108 const media::BitstreamBuffer
& bitstream_buffer
) {
109 DCHECK(CalledOnValidThread());
113 base::SharedMemoryHandle handle
= channel_
->ShareToGpuProcess(
114 bitstream_buffer
.handle());
115 if (!base::SharedMemory::IsHandleValid(handle
)) {
116 NOTREACHED() << "Failed to duplicate buffer handler";
120 Send(new AcceleratedVideoDecoderMsg_Decode(
121 decoder_route_id_
, handle
, bitstream_buffer
.id(),
122 bitstream_buffer
.size()));
125 void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
126 const std::vector
<media::PictureBuffer
>& buffers
) {
127 DCHECK(CalledOnValidThread());
130 // Rearrange data for IPC command.
131 std::vector
<int32
> buffer_ids
;
132 std::vector
<uint32
> texture_ids
;
133 for (uint32 i
= 0; i
< buffers
.size(); i
++) {
134 const media::PictureBuffer
& buffer
= buffers
[i
];
135 if (buffer
.size() != picture_buffer_dimensions_
) {
136 DLOG(ERROR
) << "buffer.size() invalid: expected "
137 << picture_buffer_dimensions_
.ToString()
138 << ", got " << buffer
.size().ToString();
139 PostNotifyError(INVALID_ARGUMENT
);
142 texture_ids
.push_back(buffer
.texture_id());
143 buffer_ids
.push_back(buffer
.id());
145 Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
146 decoder_route_id_
, buffer_ids
, texture_ids
));
149 void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
150 int32 picture_buffer_id
) {
151 DCHECK(CalledOnValidThread());
154 Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
155 decoder_route_id_
, picture_buffer_id
));
158 void GpuVideoDecodeAcceleratorHost::Flush() {
159 DCHECK(CalledOnValidThread());
162 Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_
));
165 void GpuVideoDecodeAcceleratorHost::Reset() {
166 DCHECK(CalledOnValidThread());
169 Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_
));
172 void GpuVideoDecodeAcceleratorHost::Destroy() {
173 DCHECK(CalledOnValidThread());
175 Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_
));
180 void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
181 DCHECK(CalledOnValidThread());
184 // The CommandBufferProxyImpl is going away; error out this VDA.
188 void GpuVideoDecodeAcceleratorHost::PostNotifyError(Error error
) {
189 DCHECK(CalledOnValidThread());
190 DVLOG(2) << "PostNotifyError(): error=" << error
;
191 base::ThreadTaskRunnerHandle::Get()->PostTask(
192 FROM_HERE
, base::Bind(&GpuVideoDecodeAcceleratorHost::OnNotifyError
,
193 weak_this_factory_
.GetWeakPtr(), error
));
196 void GpuVideoDecodeAcceleratorHost::Send(IPC::Message
* message
) {
197 DCHECK(CalledOnValidThread());
198 uint32 message_type
= message
->type();
199 if (!channel_
->Send(message
)) {
200 DLOG(ERROR
) << "Send(" << message_type
<< ") failed";
201 PostNotifyError(PLATFORM_FAILURE
);
205 void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
206 int32 bitstream_buffer_id
) {
207 DCHECK(CalledOnValidThread());
209 client_
->NotifyEndOfBitstreamBuffer(bitstream_buffer_id
);
212 void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
213 uint32 num_requested_buffers
,
214 const gfx::Size
& dimensions
,
215 uint32 texture_target
) {
216 DCHECK(CalledOnValidThread());
217 picture_buffer_dimensions_
= dimensions
;
219 client_
->ProvidePictureBuffers(
220 num_requested_buffers
, dimensions
, texture_target
);
224 void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
225 int32 picture_buffer_id
) {
226 DCHECK(CalledOnValidThread());
228 client_
->DismissPictureBuffer(picture_buffer_id
);
231 void GpuVideoDecodeAcceleratorHost::OnPictureReady(
232 int32 picture_buffer_id
,
233 int32 bitstream_buffer_id
,
234 const gfx::Rect
& visible_rect
,
235 bool allow_overlay
) {
236 DCHECK(CalledOnValidThread());
239 media::Picture
picture(picture_buffer_id
, bitstream_buffer_id
, visible_rect
,
241 client_
->PictureReady(picture
);
244 void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
245 DCHECK(CalledOnValidThread());
247 client_
->NotifyFlushDone();
250 void GpuVideoDecodeAcceleratorHost::OnResetDone() {
251 DCHECK(CalledOnValidThread());
253 client_
->NotifyResetDone();
256 void GpuVideoDecodeAcceleratorHost::OnNotifyError(uint32 error
) {
257 DCHECK(CalledOnValidThread());
260 weak_this_factory_
.InvalidateWeakPtrs();
262 // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
263 // last thing done on this stack!
264 media::VideoDecodeAccelerator::Client
* client
= NULL
;
265 std::swap(client
, client_
);
266 client
->NotifyError(static_cast<media::VideoDecodeAccelerator::Error
>(error
));
269 } // namespace content