Add ICU message format support
[chromium-blink-merge.git] / content / common / gpu / client / gpu_jpeg_decode_accelerator_host.cc
blob647010170012f2cc9e9aa0d93f8a2084ac909730
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 if (receiver_) {
111 channel_->RemoveRoute(decoder_route_id_);
113 // Invalidate weak ptr of |receiver_|. After that, no more messages will be
114 // routed to |receiver_| on IO thread.
115 base::WaitableEvent event(false, false);
116 io_task_runner_->PostTask(FROM_HERE,
117 base::Bind(&Receiver::InvalidateWeakPtr,
118 base::Unretained(receiver_.get()),
119 base::Unretained(&event)));
120 event.Wait();
124 bool GpuJpegDecodeAcceleratorHost::Initialize(
125 media::JpegDecodeAccelerator::Client* client) {
126 DCHECK(CalledOnValidThread());
128 bool succeeded = false;
129 // This cannot be on IO thread because the msg is synchronous.
130 Send(new GpuMsg_CreateJpegDecoder(decoder_route_id_, &succeeded));
132 if (!succeeded) {
133 DLOG(ERROR) << "Send(GpuMsg_CreateJpegDecoder()) failed";
134 return false;
137 receiver_.reset(new Receiver(client, io_task_runner_));
139 return true;
142 void GpuJpegDecodeAcceleratorHost::Decode(
143 const media::BitstreamBuffer& bitstream_buffer,
144 const scoped_refptr<media::VideoFrame>& video_frame) {
145 DCHECK(CalledOnValidThread());
147 DCHECK(
148 base::SharedMemory::IsHandleValid(video_frame->shared_memory_handle()));
150 base::SharedMemoryHandle input_handle =
151 channel_->ShareToGpuProcess(bitstream_buffer.handle());
152 if (!base::SharedMemory::IsHandleValid(input_handle)) {
153 DLOG(ERROR) << "Failed to duplicate handle of BitstreamBuffer";
154 return;
156 base::SharedMemoryHandle output_handle =
157 channel_->ShareToGpuProcess(video_frame->shared_memory_handle());
158 if (!base::SharedMemory::IsHandleValid(output_handle)) {
159 DLOG(ERROR) << "Failed to duplicate handle of VideoFrame";
160 #if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
161 if (input_handle.auto_close) {
162 // Defer closing task to the ScopedFD.
163 base::ScopedFD(input_handle.fd);
165 #else
166 // TODO(kcwu) fix the handle leak after crbug.com/493414 resolved.
167 #endif
168 return;
171 size_t output_buffer_size = media::VideoFrame::AllocationSize(
172 video_frame->format(), video_frame->coded_size());
174 AcceleratedJpegDecoderMsg_Decode_Params decode_params;
175 decode_params.coded_size = video_frame->coded_size();
176 decode_params.input_buffer_id = bitstream_buffer.id();
177 decode_params.input_buffer_handle = input_handle;
178 decode_params.input_buffer_size = bitstream_buffer.size();
179 decode_params.output_video_frame_handle = output_handle;
180 decode_params.output_buffer_size = output_buffer_size;
181 Send(new AcceleratedJpegDecoderMsg_Decode(decoder_route_id_, decode_params));
184 bool GpuJpegDecodeAcceleratorHost::IsSupported() {
185 return channel_->gpu_info().jpeg_decode_accelerator_supported;
188 void GpuJpegDecodeAcceleratorHost::Send(IPC::Message* message) {
189 DCHECK(CalledOnValidThread());
191 if (!channel_->Send(message)) {
192 DLOG(ERROR) << "Send(" << message->type() << ") failed";
196 base::WeakPtr<IPC::Listener> GpuJpegDecodeAcceleratorHost::GetReceiver() {
197 return receiver_->AsWeakPtrForIO();
200 } // namespace content