Update UnusedResources lint suppressions.
[chromium-blink-merge.git] / content / common / gpu / client / gpu_jpeg_decode_accelerator_host.cc
blob22114e5154575c78bf5ed435b25ebaa30cc17a03
1 // Copyright 2015 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_jpeg_decode_accelerator_host.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/memory/shared_memory_handle.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "content/common/gpu/client/gpu_channel_host.h"
13 #include "content/common/gpu/gpu_messages.h"
14 #include "ipc/ipc_listener.h"
15 #include "ipc/ipc_message_macros.h"
16 #include "ipc/ipc_message_utils.h"
18 namespace content {
20 // Class to receive AcceleratedJpegDecoderHostMsg_DecodeAck IPC message on IO
21 // thread. This does very similar what MessageFilter usually does. It is not
22 // MessageFilter because GpuChannelHost doesn't support AddFilter.
23 class GpuJpegDecodeAcceleratorHost::Receiver : public IPC::Listener,
24 public base::NonThreadSafe {
25 public:
26 Receiver(Client* client,
27 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
28 : client_(client),
29 io_task_runner_(io_task_runner),
30 weak_factory_for_io_(this) {
31 DCHECK(CalledOnValidThread());
34 ~Receiver() override { DCHECK(CalledOnValidThread()); }
36 void InvalidateWeakPtr(base::WaitableEvent* event) {
37 DCHECK(io_task_runner_->BelongsToCurrentThread());
38 weak_factory_for_io_.InvalidateWeakPtrs();
39 event->Signal();
42 // IPC::Listener implementation.
43 void OnChannelError() override {
44 DCHECK(io_task_runner_->BelongsToCurrentThread());
46 OnDecodeAck(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
49 bool OnMessageReceived(const IPC::Message& msg) override {
50 DCHECK(io_task_runner_->BelongsToCurrentThread());
52 bool handled = true;
53 IPC_BEGIN_MESSAGE_MAP(GpuJpegDecodeAcceleratorHost::Receiver, msg)
54 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderHostMsg_DecodeAck, OnDecodeAck)
55 IPC_MESSAGE_UNHANDLED(handled = false)
56 IPC_END_MESSAGE_MAP()
57 DCHECK(handled);
58 return handled;
61 base::WeakPtr<IPC::Listener> AsWeakPtrForIO() {
62 return weak_factory_for_io_.GetWeakPtr();
65 private:
66 void OnDecodeAck(int32_t bitstream_buffer_id, Error error) {
67 DCHECK(io_task_runner_->BelongsToCurrentThread());
69 if (!client_)
70 return;
72 if (error == media::JpegDecodeAccelerator::NO_ERRORS) {
73 client_->VideoFrameReady(bitstream_buffer_id);
74 } else {
75 // Only NotifyError once.
76 // Client::NotifyError() may trigger deletion of |this| (on another
77 // thread), so calling it needs to be the last thing done on this stack!
78 media::JpegDecodeAccelerator::Client* client = nullptr;
79 std::swap(client, client_);
80 client->NotifyError(bitstream_buffer_id, error);
84 Client* client_;
86 // GPU IO task runner.
87 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
89 // Weak pointers will be invalidated on IO thread.
90 base::WeakPtrFactory<Receiver> weak_factory_for_io_;
92 DISALLOW_COPY_AND_ASSIGN(Receiver);
95 GpuJpegDecodeAcceleratorHost::GpuJpegDecodeAcceleratorHost(
96 GpuChannelHost* channel,
97 int32 route_id,
98 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
99 : channel_(channel),
100 decoder_route_id_(route_id),
101 io_task_runner_(io_task_runner) {
102 DCHECK(channel_);
103 DCHECK_NE(decoder_route_id_, MSG_ROUTING_NONE);
106 GpuJpegDecodeAcceleratorHost::~GpuJpegDecodeAcceleratorHost() {
107 DCHECK(CalledOnValidThread());
108 Send(new AcceleratedJpegDecoderMsg_Destroy(decoder_route_id_));
110 channel_->RemoveRoute(decoder_route_id_);
112 // Invalidate weak ptr of |receiver_|. After that, no more messages will be
113 // routed to |receiver_| on IO thread.
114 base::WaitableEvent event(false, false);
115 io_task_runner_->PostTask(
116 FROM_HERE,
117 base::Bind(&Receiver::InvalidateWeakPtr,
118 base::Unretained(receiver_.get()), base::Unretained(&event)));
119 event.Wait();
122 bool GpuJpegDecodeAcceleratorHost::Initialize(
123 media::JpegDecodeAccelerator::Client* client) {
124 DCHECK(CalledOnValidThread());
126 bool succeeded = false;
127 // This cannot be on IO thread because the msg is synchronous.
128 Send(new GpuMsg_CreateJpegDecoder(decoder_route_id_, &succeeded));
130 if (!succeeded) {
131 DLOG(ERROR) << "Send(GpuMsg_CreateJpegDecoder()) failed";
132 return false;
135 receiver_.reset(new Receiver(client, io_task_runner_));
137 return true;
140 void GpuJpegDecodeAcceleratorHost::Decode(
141 const media::BitstreamBuffer& bitstream_buffer,
142 const scoped_refptr<media::VideoFrame>& video_frame) {
143 DCHECK(CalledOnValidThread());
145 DCHECK(
146 base::SharedMemory::IsHandleValid(video_frame->shared_memory_handle()));
148 base::SharedMemoryHandle input_handle =
149 channel_->ShareToGpuProcess(bitstream_buffer.handle());
150 if (!base::SharedMemory::IsHandleValid(input_handle)) {
151 DLOG(ERROR) << "Failed to duplicate handle of BitstreamBuffer";
152 return;
154 base::SharedMemoryHandle output_handle =
155 channel_->ShareToGpuProcess(video_frame->shared_memory_handle());
156 if (!base::SharedMemory::IsHandleValid(output_handle)) {
157 DLOG(ERROR) << "Failed to duplicate handle of VideoFrame";
158 #if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
159 if (input_handle.auto_close) {
160 // Defer closing task to the ScopedFD.
161 base::ScopedFD(input_handle.fd);
163 #else
164 // TODO(kcwu) fix the handle leak after crbug.com/493414 resolved.
165 #endif
166 return;
169 size_t output_buffer_size = media::VideoFrame::AllocationSize(
170 video_frame->format(), video_frame->coded_size());
172 AcceleratedJpegDecoderMsg_Decode_Params decode_params;
173 decode_params.coded_size = video_frame->coded_size();
174 decode_params.input_buffer_id = bitstream_buffer.id();
175 decode_params.input_buffer_handle = input_handle;
176 decode_params.input_buffer_size = bitstream_buffer.size();
177 decode_params.output_video_frame_handle = output_handle;
178 decode_params.output_buffer_size = output_buffer_size;
179 Send(new AcceleratedJpegDecoderMsg_Decode(decoder_route_id_, decode_params));
182 void GpuJpegDecodeAcceleratorHost::Send(IPC::Message* message) {
183 DCHECK(CalledOnValidThread());
185 if (!channel_->Send(message)) {
186 DLOG(ERROR) << "Send(" << message->type() << ") failed";
190 base::WeakPtr<IPC::Listener> GpuJpegDecodeAcceleratorHost::GetReceiver() {
191 return receiver_->AsWeakPtrForIO();
194 } // namespace content