Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: media/gpu/ipc/client/gpu_jpeg_decode_accelerator_host.cc

Issue 2924573002: [NotForReview] Convert accelerated JPEG Decoder IPC to Mojo
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/gpu/ipc/client/gpu_jpeg_decode_accelerator_host.h" 5 #include "media/gpu/ipc/client/gpu_jpeg_decode_accelerator_host.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/memory/shared_memory_handle.h" 12 #include "base/memory/shared_memory_handle.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "build/build_config.h" 13 #include "build/build_config.h"
16 #include "gpu/ipc/client/gpu_channel_host.h" 14 #include "content/public/browser/gpu_service_registry.h"
17 #include "ipc/ipc_listener.h" 15 #include "mojo/public/cpp/system/platform_handle.h"
18 #include "ipc/ipc_message_macros.h" 16
19 #include "ipc/ipc_message_utils.h" 17 namespace {
20 #include "media/gpu/ipc/common/media_messages.h" 18
19 void ConnectToGpuJpegDecodeAccelerator(
20 media::mojom::GpuJpegDecodeAcceleratorRequest request) {
21 content::BindInterfaceInGpuProcess(std::move(request));
22 }
23
24 } // namespace
21 25
22 namespace media { 26 namespace media {
23 27
24 // Class to receive AcceleratedJpegDecoderHostMsg_DecodeAck IPC message on IO
25 // thread. This does very similar what MessageFilter usually does. It is not
26 // MessageFilter because GpuChannelHost doesn't support AddFilter.
27 class GpuJpegDecodeAcceleratorHost::Receiver : public IPC::Listener {
28 public:
29 Receiver(Client* client,
30 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
31 : client_(client),
32 io_task_runner_(io_task_runner),
33 weak_factory_for_io_(
34 base::MakeUnique<base::WeakPtrFactory<Receiver>>(this)),
35 weak_ptr_for_io_(weak_factory_for_io_->GetWeakPtr()) {
36 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
37 }
38
39 ~Receiver() override {
40 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
41 // If |io_task_runner_| no longer accepts tasks, |weak_factory_for_io_|
42 // will leak. This is acceptable, because that should only happen on
43 // Browser shutdown.
44 io_task_runner_->DeleteSoon(FROM_HERE, weak_factory_for_io_.release());
45 }
46
47 void InvalidateWeakPtrOnIOThread(base::WaitableEvent* event) {
48 DCHECK(io_task_runner_->BelongsToCurrentThread());
49 weak_factory_for_io_->InvalidateWeakPtrs();
50 event->Signal();
51 }
52
53 // IPC::Listener implementation.
54 void OnChannelError() override {
55 DCHECK(io_task_runner_->BelongsToCurrentThread());
56
57 OnDecodeAck(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
58 }
59
60 bool OnMessageReceived(const IPC::Message& msg) override {
61 DCHECK(io_task_runner_->BelongsToCurrentThread());
62
63 bool handled = true;
64 IPC_BEGIN_MESSAGE_MAP(GpuJpegDecodeAcceleratorHost::Receiver, msg)
65 IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderHostMsg_DecodeAck, OnDecodeAck)
66 IPC_MESSAGE_UNHANDLED(handled = false)
67 IPC_END_MESSAGE_MAP()
68 DCHECK(handled);
69 return handled;
70 }
71
72 base::WeakPtr<IPC::Listener> AsWeakPtrForIO() { return weak_ptr_for_io_; }
73
74 private:
75 void OnDecodeAck(int32_t bitstream_buffer_id, Error error) {
76 DCHECK(io_task_runner_->BelongsToCurrentThread());
77
78 if (!client_)
79 return;
80
81 if (error == JpegDecodeAccelerator::NO_ERRORS) {
82 client_->VideoFrameReady(bitstream_buffer_id);
83 } else {
84 // Only NotifyError once.
85 // Client::NotifyError() may trigger deletion of |this| (on another
86 // thread), so calling it needs to be the last thing done on this stack!
87 JpegDecodeAccelerator::Client* client = nullptr;
88 std::swap(client, client_);
89 client->NotifyError(bitstream_buffer_id, error);
90 }
91 }
92
93 Client* client_;
94
95 // GPU IO task runner.
96 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
97
98 SEQUENCE_CHECKER(sequence_checker_);
99
100 // Weak pointers will be invalidated on IO thread.
101 std::unique_ptr<base::WeakPtrFactory<Receiver>> weak_factory_for_io_;
102 base::WeakPtr<Receiver> weak_ptr_for_io_;
103
104 DISALLOW_COPY_AND_ASSIGN(Receiver);
105 };
106
107 GpuJpegDecodeAcceleratorHost::GpuJpegDecodeAcceleratorHost( 28 GpuJpegDecodeAcceleratorHost::GpuJpegDecodeAcceleratorHost(
108 scoped_refptr<gpu::GpuChannelHost> channel, 29 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
109 int32_t route_id, 30 : io_task_runner_(io_task_runner) {
110 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 31 auto request = mojo::MakeRequest(&jpeg_decoder_);
111 : channel_(std::move(channel)), 32 io_task_runner_->PostTask(
112 decoder_route_id_(route_id), 33 FROM_HERE,
113 io_task_runner_(io_task_runner) { 34 base::Bind(&ConnectToGpuJpegDecodeAccelerator, base::Passed(&request)));
114 DCHECK(channel_);
115 DCHECK_NE(decoder_route_id_, MSG_ROUTING_NONE);
116 } 35 }
117 36
118 GpuJpegDecodeAcceleratorHost::~GpuJpegDecodeAcceleratorHost() { 37 GpuJpegDecodeAcceleratorHost::~GpuJpegDecodeAcceleratorHost() {
119 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 38 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
120 Send(new AcceleratedJpegDecoderMsg_Destroy(decoder_route_id_));
121
122 if (receiver_) {
123 channel_->RemoveRoute(decoder_route_id_);
124
125 // Invalidate weak ptr of |receiver_|. After that, no more messages will be
126 // routed to |receiver_| on IO thread.
127 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
128 base::WaitableEvent::InitialState::NOT_SIGNALED);
129 // Use of Unretained() is safe, because if the task executes, we block
130 // until it is finished by waiting on |event| below.
131 bool task_expected_to_run = io_task_runner_->PostTask(
132 FROM_HERE, base::Bind(&Receiver::InvalidateWeakPtrOnIOThread,
133 base::Unretained(receiver_.get()),
134 base::Unretained(&event)));
135 // If the current call is happening during the browser shutdown, the
136 // |io_task_runner_| may no longer be accepting tasks.
137 if (task_expected_to_run)
138 event.Wait();
139 }
140 } 39 }
141 40
142 bool GpuJpegDecodeAcceleratorHost::Initialize( 41 bool GpuJpegDecodeAcceleratorHost::Initialize(
143 JpegDecodeAccelerator::Client* client) { 42 JpegDecodeAccelerator::Client* client) {
144 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 43 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
145 44
146 bool succeeded = false; 45 bool succeeded = false;
147 // This cannot be on IO thread because the msg is synchronous. 46 jpeg_decoder_->Initialize(&succeeded);
148 Send(new GpuChannelMsg_CreateJpegDecoder(decoder_route_id_, &succeeded));
149 47
150 if (!succeeded) { 48 if (succeeded)
151 DLOG(ERROR) << "Send(GpuChannelMsg_CreateJpegDecoder()) failed"; 49 client_ = client;
152 return false; 50
51 return succeeded;
52 }
53
54 void GpuJpegDecodeAcceleratorHost::OnDecodeAckOnIOThread(
55 int32_t bitstream_buffer_id,
56 mojom::Error error) {
57 DCHECK(io_task_runner_->BelongsToCurrentThread());
58
59 if (!client_)
60 return;
61
62 if (error == mojom::Error::NO_ERRORS) {
63 client_->VideoFrameReady(bitstream_buffer_id);
64 } else {
65 // Only NotifyError once.
66 // Client::NotifyError() may trigger deletion of |this| (on another
67 // thread), so calling it needs to be the last thing done on this stack!
68 JpegDecodeAccelerator::Client* client = nullptr;
69 std::swap(client, client_);
70 client->NotifyError(bitstream_buffer_id,
71 static_cast<JpegDecodeAccelerator::Error>(error));
153 } 72 }
73 }
154 74
155 receiver_.reset(new Receiver(client, io_task_runner_)); 75 void GpuJpegDecodeAcceleratorHost::OnDecodeAck(int32_t bitstream_buffer_id,
76 mojom::Error error) {
77 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
156 78
157 return true; 79 io_task_runner_->PostTask(
80 FROM_HERE,
81 base::Bind(&GpuJpegDecodeAcceleratorHost::OnDecodeAckOnIOThread,
82 base::Unretained(this), bitstream_buffer_id, error));
158 } 83 }
159 84
160 void GpuJpegDecodeAcceleratorHost::Decode( 85 void GpuJpegDecodeAcceleratorHost::Decode(
161 const BitstreamBuffer& bitstream_buffer, 86 const BitstreamBuffer& bitstream_buffer,
162 const scoped_refptr<VideoFrame>& video_frame) { 87 const scoped_refptr<VideoFrame>& video_frame) {
163 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 88 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
164 89
165 DCHECK( 90 DCHECK(
166 base::SharedMemory::IsHandleValid(video_frame->shared_memory_handle())); 91 base::SharedMemory::IsHandleValid(video_frame->shared_memory_handle()));
167 92
168 AcceleratedJpegDecoderMsg_Decode_Params decode_params;
169 decode_params.input_buffer = bitstream_buffer;
170 base::SharedMemoryHandle input_handle = 93 base::SharedMemoryHandle input_handle =
171 channel_->ShareToGpuProcess(bitstream_buffer.handle()); 94 base::SharedMemory::DuplicateHandle(bitstream_buffer.handle());
172 if (!base::SharedMemory::IsHandleValid(input_handle)) { 95 if (!base::SharedMemory::IsHandleValid(input_handle)) {
173 DLOG(ERROR) << "Failed to duplicate handle of BitstreamBuffer"; 96 DLOG(ERROR) << "Failed to duplicate handle of BitstreamBuffer";
174 return; 97 return;
175 } 98 }
176 decode_params.input_buffer.set_handle(input_handle); 99
177 base::SharedMemoryHandle output_handle = 100 base::SharedMemoryHandle output_handle =
178 channel_->ShareToGpuProcess(video_frame->shared_memory_handle()); 101 base::SharedMemory::DuplicateHandle(video_frame->shared_memory_handle());
179 if (!base::SharedMemory::IsHandleValid(output_handle)) { 102 if (!base::SharedMemory::IsHandleValid(output_handle)) {
180 DLOG(ERROR) << "Failed to duplicate handle of VideoFrame"; 103 DLOG(ERROR) << "Failed to duplicate handle of VideoFrame";
181 #if defined(OS_POSIX) && !defined(OS_MACOSX) 104 #if defined(OS_POSIX) && !defined(OS_MACOSX)
182 if (input_handle.OwnershipPassesToIPC()) { 105 if (input_handle.OwnershipPassesToIPC()) {
183 input_handle.Close(); 106 input_handle.Close();
184 } 107 }
185 #else 108 #else
186 // TODO(kcwu) fix the handle leak after crbug.com/493414 resolved. 109 // TODO(kcwu) fix the handle leak after crbug.com/493414 resolved.
187 #endif 110 #endif
188 return; 111 return;
189 } 112 }
190 113
114 mojo::ScopedSharedBufferHandle input_buffer_handle =
115 mojo::WrapSharedMemoryHandle(input_handle, input_handle.GetSize(),
116 true /* read_only */);
117 mojom::BitstreamBufferPtr buffer = mojom::BitstreamBuffer::New();
118 buffer->id = bitstream_buffer.id();
119 buffer->memory_handle = std::move(input_buffer_handle);
120 buffer->size = bitstream_buffer.size();
121 buffer->offset = bitstream_buffer.offset();
122 buffer->timestamp = bitstream_buffer.presentation_timestamp();
123 buffer->key_id = bitstream_buffer.key_id();
124 buffer->iv = bitstream_buffer.iv();
125 buffer->subsamples = bitstream_buffer.subsamples();
126
127 mojo::ScopedSharedBufferHandle output_frame_handle =
128 mojo::WrapSharedMemoryHandle(output_handle, output_handle.GetSize(),
129 false /* read_only */);
130
191 size_t output_buffer_size = VideoFrame::AllocationSize( 131 size_t output_buffer_size = VideoFrame::AllocationSize(
192 video_frame->format(), video_frame->coded_size()); 132 video_frame->format(), video_frame->coded_size());
193 133
194 decode_params.coded_size = video_frame->coded_size(); 134 jpeg_decoder_->Decode(std::move(buffer), video_frame->coded_size(),
195 decode_params.output_video_frame_handle = output_handle; 135 std::move(output_frame_handle),
196 decode_params.output_buffer_size = 136 base::checked_cast<uint32_t>(output_buffer_size),
197 base::checked_cast<uint32_t>(output_buffer_size); 137 base::Bind(&GpuJpegDecodeAcceleratorHost::OnDecodeAck,
198 Send(new AcceleratedJpegDecoderMsg_Decode(decoder_route_id_, decode_params)); 138 base::Unretained(this)));
199 } 139 }
200 140
201 bool GpuJpegDecodeAcceleratorHost::IsSupported() { 141 bool GpuJpegDecodeAcceleratorHost::IsSupported() {
202 return channel_->gpu_info().jpeg_decode_accelerator_supported; 142 return true;
203 }
204
205 void GpuJpegDecodeAcceleratorHost::Send(IPC::Message* message) {
206 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
207
208 if (!channel_->Send(message)) {
209 DLOG(ERROR) << "Send(" << message->type() << ") failed";
210 }
211 }
212
213 base::WeakPtr<IPC::Listener> GpuJpegDecodeAcceleratorHost::GetReceiver() {
214 return receiver_->AsWeakPtrForIO();
215 } 143 }
216 144
217 } // namespace media 145 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698