OLD | NEW |
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/service/gpu_jpeg_decode_accelerator.h" | 5 #include "media/gpu/ipc/service/gpu_jpeg_decode_accelerator.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/containers/hash_tables.h" | 13 #include "base/containers/hash_tables.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/ptr_util.h" |
15 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" |
16 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
17 #include "base/stl_util.h" | |
18 #include "base/threading/thread_task_runner_handle.h" | 18 #include "base/threading/thread_task_runner_handle.h" |
19 #include "base/trace_event/trace_event.h" | 19 #include "base/trace_event/trace_event.h" |
20 #include "build/build_config.h" | 20 #include "build/build_config.h" |
21 #include "gpu/ipc/service/gpu_channel.h" | 21 #include "gpu/ipc/service/gpu_channel.h" |
22 #include "ipc/ipc_message_macros.h" | 22 #include "ipc/ipc_message_macros.h" |
23 #include "ipc/message_filter.h" | 23 #include "ipc/message_filter.h" |
24 #include "media/filters/jpeg_parser.h" | 24 #include "media/filters/jpeg_parser.h" |
25 #include "media/gpu/ipc/common/media_messages.h" | 25 #include "media/gpu/ipc/common/media_messages.h" |
26 #include "ui/gfx/geometry/size.h" | 26 #include "ui/gfx/geometry/size.h" |
27 | 27 |
28 #if defined(OS_CHROMEOS) | 28 #if defined(OS_CHROMEOS) |
29 #if defined(ARCH_CPU_X86_FAMILY) | 29 #if defined(ARCH_CPU_X86_FAMILY) |
30 #include "media/gpu/vaapi_jpeg_decode_accelerator.h" | 30 #include "media/gpu/vaapi_jpeg_decode_accelerator.h" |
31 #endif | 31 #endif |
32 #if defined(USE_V4L2_CODEC) | 32 #if defined(USE_V4L2_CODEC) |
33 #include "media/gpu/v4l2_device.h" | 33 #include "media/gpu/v4l2_device.h" |
34 #include "media/gpu/v4l2_jpeg_decode_accelerator.h" | 34 #include "media/gpu/v4l2_jpeg_decode_accelerator.h" |
35 #endif | 35 #endif |
36 #endif | 36 #endif |
37 | 37 |
38 namespace { | 38 namespace { |
39 | 39 |
40 void DecodeFinished(std::unique_ptr<base::SharedMemory> shm) { | 40 void DecodeFinished(std::unique_ptr<base::SharedMemory> shm) { |
41 // Do nothing. Because VideoFrame is backed by |shm|, the purpose of this | 41 // Do nothing. Because VideoFrame is backed by |shm|, the purpose of this |
42 // function is to just keep reference of |shm| to make sure it lives util | 42 // function is to just keep reference of |shm| to make sure it lives until |
43 // decode finishes. | 43 // decode finishes. |
44 } | 44 } |
45 | 45 |
46 bool VerifyDecodeParams(const AcceleratedJpegDecoderMsg_Decode_Params& params) { | 46 bool VerifyDecodeParams(const AcceleratedJpegDecoderMsg_Decode_Params& params) { |
47 const int kJpegMaxDimension = UINT16_MAX; | 47 const int kJpegMaxDimension = UINT16_MAX; |
48 if (params.coded_size.IsEmpty() || | 48 if (params.coded_size.IsEmpty() || |
49 params.coded_size.width() > kJpegMaxDimension || | 49 params.coded_size.width() > kJpegMaxDimension || |
50 params.coded_size.height() > kJpegMaxDimension) { | 50 params.coded_size.height() > kJpegMaxDimension) { |
51 LOG(ERROR) << "invalid coded_size " << params.coded_size.ToString(); | 51 LOG(ERROR) << "invalid coded_size " << params.coded_size.ToString(); |
52 return false; | 52 return false; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 } | 151 } |
152 return sender_->Send(message); | 152 return sender_->Send(message); |
153 } | 153 } |
154 | 154 |
155 void AddClientOnIOThread(int32_t route_id, | 155 void AddClientOnIOThread(int32_t route_id, |
156 Client* client, | 156 Client* client, |
157 base::Callback<void(bool)> response) { | 157 base::Callback<void(bool)> response) { |
158 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 158 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
159 DCHECK(client_map_.count(route_id) == 0); | 159 DCHECK(client_map_.count(route_id) == 0); |
160 | 160 |
161 client_map_[route_id] = client; | 161 // See the comment on GpuJpegDecodeAccelerator::AddClient. |
| 162 client_map_[route_id] = base::WrapUnique(client); |
162 response.Run(true); | 163 response.Run(true); |
163 } | 164 } |
164 | 165 |
165 void OnDestroyOnIOThread(const int32_t* route_id) { | 166 void OnDestroyOnIOThread(const int32_t* route_id) { |
166 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 167 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
167 const auto& it = client_map_.find(*route_id); | 168 const auto& it = client_map_.find(*route_id); |
168 DCHECK(it != client_map_.end()); | 169 DCHECK(it != client_map_.end()); |
169 Client* client = it->second; | 170 std::unique_ptr<Client> client = std::move(it->second); |
170 DCHECK(client); | 171 DCHECK(client); |
171 client_map_.erase(it); | 172 client_map_.erase(it); |
172 | 173 |
173 child_task_runner_->PostTask( | 174 child_task_runner_->PostTask( |
174 FROM_HERE, base::Bind(&MessageFilter::DestroyClient, this, client)); | 175 FROM_HERE, |
| 176 base::Bind(&MessageFilter::DestroyClient, this, base::Passed(&client))); |
175 } | 177 } |
176 | 178 |
177 void DestroyClient(Client* client) { | 179 void DestroyClient(std::unique_ptr<Client> client) { |
178 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 180 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
179 delete client; | |
180 if (owner_) | 181 if (owner_) |
181 owner_->ClientRemoved(); | 182 owner_->ClientRemoved(); |
| 183 // |client| is destroyed when the scope of this function is left. |
182 } | 184 } |
183 | 185 |
184 void NotifyDecodeStatusOnIOThread(int32_t route_id, | 186 void NotifyDecodeStatusOnIOThread(int32_t route_id, |
185 int32_t buffer_id, | 187 int32_t buffer_id, |
186 JpegDecodeAccelerator::Error error) { | 188 JpegDecodeAccelerator::Error error) { |
187 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 189 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
188 SendOnIOThread(new AcceleratedJpegDecoderHostMsg_DecodeAck( | 190 SendOnIOThread(new AcceleratedJpegDecoderHostMsg_DecodeAck( |
189 route_id, buffer_id, error)); | 191 route_id, buffer_id, error)); |
190 } | 192 } |
191 | 193 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 << params.input_buffer.id(); | 236 << params.input_buffer.id(); |
235 NotifyDecodeStatusOnIOThread(*route_id, params.input_buffer.id(), | 237 NotifyDecodeStatusOnIOThread(*route_id, params.input_buffer.id(), |
236 JpegDecodeAccelerator::PLATFORM_FAILURE); | 238 JpegDecodeAccelerator::PLATFORM_FAILURE); |
237 base::SharedMemory::CloseHandle(params.input_buffer.handle()); | 239 base::SharedMemory::CloseHandle(params.input_buffer.handle()); |
238 return; | 240 return; |
239 } | 241 } |
240 frame->AddDestructionObserver( | 242 frame->AddDestructionObserver( |
241 base::Bind(DecodeFinished, base::Passed(&output_shm))); | 243 base::Bind(DecodeFinished, base::Passed(&output_shm))); |
242 | 244 |
243 DCHECK_GT(client_map_.count(*route_id), 0u); | 245 DCHECK_GT(client_map_.count(*route_id), 0u); |
244 Client* client = client_map_[*route_id]; | 246 Client* client = client_map_[*route_id].get(); |
245 client->Decode(params.input_buffer, frame); | 247 client->Decode(params.input_buffer, frame); |
246 } | 248 } |
247 | 249 |
248 protected: | 250 protected: |
249 ~MessageFilter() override { | 251 ~MessageFilter() override { |
250 if (client_map_.empty()) | 252 if (client_map_.empty()) |
251 return; | 253 return; |
252 | 254 |
253 if (child_task_runner_->BelongsToCurrentThread()) { | 255 if (child_task_runner_->BelongsToCurrentThread()) { |
254 base::STLDeleteValues(&client_map_); | 256 client_map_.clear(); |
255 } else { | 257 } else { |
256 // Make sure |Client| are deleted on child thread. | 258 // Make sure |Client| are deleted on child thread. |
257 std::unique_ptr<ClientMap> client_map(new ClientMap); | 259 std::unique_ptr<ClientMap> client_map(new ClientMap); |
258 client_map->swap(client_map_); | 260 client_map->swap(client_map_); |
259 | 261 |
260 child_task_runner_->PostTask( | 262 child_task_runner_->PostTask( |
261 FROM_HERE, | 263 FROM_HERE, |
262 base::Bind(&DeleteClientMapOnChildThread, base::Passed(&client_map))); | 264 base::Bind(&DeleteClientMapOnChildThread, base::Passed(&client_map))); |
263 } | 265 } |
264 } | 266 } |
265 | 267 |
266 private: | 268 private: |
267 using ClientMap = base::hash_map<int32_t, Client*>; | 269 using ClientMap = base::hash_map<int32_t, std::unique_ptr<Client>>; |
268 | 270 |
269 // Must be static because this method runs after destructor. | 271 // Must be static because this method runs after destructor. |
270 static void DeleteClientMapOnChildThread( | 272 static void DeleteClientMapOnChildThread( |
271 std::unique_ptr<ClientMap> client_map) { | 273 std::unique_ptr<ClientMap> client_map) { |
272 base::STLDeleteValues(client_map.get()); | 274 // |client_map| is cleared when the scope of this function is left. |
273 } | 275 } |
274 | 276 |
275 base::WeakPtr<GpuJpegDecodeAccelerator> owner_; | 277 base::WeakPtr<GpuJpegDecodeAccelerator> owner_; |
276 | 278 |
277 // GPU child task runner. | 279 // GPU child task runner. |
278 scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_; | 280 scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_; |
279 | 281 |
280 // GPU IO task runner. | 282 // GPU IO task runner. |
281 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; | 283 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
282 | 284 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 // This should be before AddClientOnIOThread. | 343 // This should be before AddClientOnIOThread. |
342 channel_->AddFilter(filter_.get()); | 344 channel_->AddFilter(filter_.get()); |
343 } | 345 } |
344 client_number_++; | 346 client_number_++; |
345 | 347 |
346 // In this PostTask, |client| may leak if |io_task_runner_| is destroyed | 348 // In this PostTask, |client| may leak if |io_task_runner_| is destroyed |
347 // before |client| reached AddClientOnIOThread. However we cannot use scoper | 349 // before |client| reached AddClientOnIOThread. However we cannot use scoper |
348 // to protect it because |client| can only be deleted on child thread. The IO | 350 // to protect it because |client| can only be deleted on child thread. The IO |
349 // thread is destroyed at termination, at which point it's ok to leak since | 351 // thread is destroyed at termination, at which point it's ok to leak since |
350 // we're going to tear down the process anyway. So we just crossed fingers | 352 // we're going to tear down the process anyway. So we just crossed fingers |
351 // here instead of making the code unnecessary complicated. | 353 // here instead of making the code unnecessarily complicated. |
352 io_task_runner_->PostTask( | 354 io_task_runner_->PostTask( |
353 FROM_HERE, base::Bind(&MessageFilter::AddClientOnIOThread, filter_, | 355 FROM_HERE, base::Bind(&MessageFilter::AddClientOnIOThread, filter_, |
354 route_id, client.release(), response)); | 356 route_id, client.release(), response)); |
355 } | 357 } |
356 | 358 |
357 void GpuJpegDecodeAccelerator::NotifyDecodeStatus( | 359 void GpuJpegDecodeAccelerator::NotifyDecodeStatus( |
358 int32_t route_id, | 360 int32_t route_id, |
359 int32_t buffer_id, | 361 int32_t buffer_id, |
360 JpegDecodeAccelerator::Error error) { | 362 JpegDecodeAccelerator::Error error) { |
361 DCHECK(CalledOnValidThread()); | 363 DCHECK(CalledOnValidThread()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 for (const auto& create_jda_function : create_jda_fps) { | 411 for (const auto& create_jda_function : create_jda_fps) { |
410 std::unique_ptr<JpegDecodeAccelerator> accelerator = | 412 std::unique_ptr<JpegDecodeAccelerator> accelerator = |
411 (*create_jda_function)(base::ThreadTaskRunnerHandle::Get()); | 413 (*create_jda_function)(base::ThreadTaskRunnerHandle::Get()); |
412 if (accelerator && accelerator->IsSupported()) | 414 if (accelerator && accelerator->IsSupported()) |
413 return true; | 415 return true; |
414 } | 416 } |
415 return false; | 417 return false; |
416 } | 418 } |
417 | 419 |
418 } // namespace media | 420 } // namespace media |
OLD | NEW |