Chromium Code Reviews| 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 |
| (...skipping 123 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_) |
|
wolenetz
2016/09/27 22:01:12
nit: include a comment here like on l.273, too?
Avi (use Gerrit)
2016/09/28 15:41:46
Done.
| |
| 181 owner_->ClientRemoved(); | 182 owner_->ClientRemoved(); |
| 182 } | 183 } |
| 183 | 184 |
| 184 void NotifyDecodeStatusOnIOThread(int32_t route_id, | 185 void NotifyDecodeStatusOnIOThread(int32_t route_id, |
| 185 int32_t buffer_id, | 186 int32_t buffer_id, |
| 186 JpegDecodeAccelerator::Error error) { | 187 JpegDecodeAccelerator::Error error) { |
| 187 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 188 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 188 SendOnIOThread(new AcceleratedJpegDecoderHostMsg_DecodeAck( | 189 SendOnIOThread(new AcceleratedJpegDecoderHostMsg_DecodeAck( |
| 189 route_id, buffer_id, error)); | 190 route_id, buffer_id, error)); |
| 190 } | 191 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 << params.input_buffer.id(); | 235 << params.input_buffer.id(); |
| 235 NotifyDecodeStatusOnIOThread(*route_id, params.input_buffer.id(), | 236 NotifyDecodeStatusOnIOThread(*route_id, params.input_buffer.id(), |
| 236 JpegDecodeAccelerator::PLATFORM_FAILURE); | 237 JpegDecodeAccelerator::PLATFORM_FAILURE); |
| 237 base::SharedMemory::CloseHandle(params.input_buffer.handle()); | 238 base::SharedMemory::CloseHandle(params.input_buffer.handle()); |
| 238 return; | 239 return; |
| 239 } | 240 } |
| 240 frame->AddDestructionObserver( | 241 frame->AddDestructionObserver( |
| 241 base::Bind(DecodeFinished, base::Passed(&output_shm))); | 242 base::Bind(DecodeFinished, base::Passed(&output_shm))); |
| 242 | 243 |
| 243 DCHECK_GT(client_map_.count(*route_id), 0u); | 244 DCHECK_GT(client_map_.count(*route_id), 0u); |
| 244 Client* client = client_map_[*route_id]; | 245 Client* client = client_map_[*route_id].get(); |
| 245 client->Decode(params.input_buffer, frame); | 246 client->Decode(params.input_buffer, frame); |
| 246 } | 247 } |
| 247 | 248 |
| 248 protected: | 249 protected: |
| 249 ~MessageFilter() override { | 250 ~MessageFilter() override { |
| 250 if (client_map_.empty()) | 251 if (client_map_.empty()) |
| 251 return; | 252 return; |
| 252 | 253 |
| 253 if (child_task_runner_->BelongsToCurrentThread()) { | 254 if (child_task_runner_->BelongsToCurrentThread()) { |
| 254 base::STLDeleteValues(&client_map_); | 255 client_map_.clear(); |
| 255 } else { | 256 } else { |
| 256 // Make sure |Client| are deleted on child thread. | 257 // Make sure |Client| are deleted on child thread. |
| 257 std::unique_ptr<ClientMap> client_map(new ClientMap); | 258 std::unique_ptr<ClientMap> client_map(new ClientMap); |
| 258 client_map->swap(client_map_); | 259 client_map->swap(client_map_); |
| 259 | 260 |
| 260 child_task_runner_->PostTask( | 261 child_task_runner_->PostTask( |
| 261 FROM_HERE, | 262 FROM_HERE, |
| 262 base::Bind(&DeleteClientMapOnChildThread, base::Passed(&client_map))); | 263 base::Bind(&DeleteClientMapOnChildThread, base::Passed(&client_map))); |
| 263 } | 264 } |
| 264 } | 265 } |
| 265 | 266 |
| 266 private: | 267 private: |
| 267 using ClientMap = base::hash_map<int32_t, Client*>; | 268 using ClientMap = base::hash_map<int32_t, std::unique_ptr<Client>>; |
| 268 | 269 |
| 269 // Must be static because this method runs after destructor. | 270 // Must be static because this method runs after destructor. |
| 270 static void DeleteClientMapOnChildThread( | 271 static void DeleteClientMapOnChildThread( |
| 271 std::unique_ptr<ClientMap> client_map) { | 272 std::unique_ptr<ClientMap> client_map) { |
| 272 base::STLDeleteValues(client_map.get()); | 273 // |client_map| is cleared when the scope of this function is left. |
| 273 } | 274 } |
| 274 | 275 |
| 275 base::WeakPtr<GpuJpegDecodeAccelerator> owner_; | 276 base::WeakPtr<GpuJpegDecodeAccelerator> owner_; |
| 276 | 277 |
| 277 // GPU child task runner. | 278 // GPU child task runner. |
| 278 scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_; | 279 scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_; |
| 279 | 280 |
| 280 // GPU IO task runner. | 281 // GPU IO task runner. |
| 281 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; | 282 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; |
| 282 | 283 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 // This should be before AddClientOnIOThread. | 342 // This should be before AddClientOnIOThread. |
| 342 channel_->AddFilter(filter_.get()); | 343 channel_->AddFilter(filter_.get()); |
| 343 } | 344 } |
| 344 client_number_++; | 345 client_number_++; |
| 345 | 346 |
| 346 // In this PostTask, |client| may leak if |io_task_runner_| is destroyed | 347 // In this PostTask, |client| may leak if |io_task_runner_| is destroyed |
| 347 // before |client| reached AddClientOnIOThread. However we cannot use scoper | 348 // before |client| reached AddClientOnIOThread. However we cannot use scoper |
| 348 // to protect it because |client| can only be deleted on child thread. The IO | 349 // 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 | 350 // 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 | 351 // we're going to tear down the process anyway. So we just crossed fingers |
| 351 // here instead of making the code unnecessary complicated. | 352 // here instead of making the code unnecessary complicated. |
|
wolenetz
2016/09/27 22:01:12
drive-by nit: s/unnecessary/unnecessarily/
Avi (use Gerrit)
2016/09/28 15:41:46
I'll spell-check the whole file while I'm at it, t
| |
| 352 io_task_runner_->PostTask( | 353 io_task_runner_->PostTask( |
| 353 FROM_HERE, base::Bind(&MessageFilter::AddClientOnIOThread, filter_, | 354 FROM_HERE, base::Bind(&MessageFilter::AddClientOnIOThread, filter_, |
| 354 route_id, client.release(), response)); | 355 route_id, client.release(), response)); |
| 355 } | 356 } |
| 356 | 357 |
| 357 void GpuJpegDecodeAccelerator::NotifyDecodeStatus( | 358 void GpuJpegDecodeAccelerator::NotifyDecodeStatus( |
| 358 int32_t route_id, | 359 int32_t route_id, |
| 359 int32_t buffer_id, | 360 int32_t buffer_id, |
| 360 JpegDecodeAccelerator::Error error) { | 361 JpegDecodeAccelerator::Error error) { |
| 361 DCHECK(CalledOnValidThread()); | 362 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) { | 410 for (const auto& create_jda_function : create_jda_fps) { |
| 410 std::unique_ptr<JpegDecodeAccelerator> accelerator = | 411 std::unique_ptr<JpegDecodeAccelerator> accelerator = |
| 411 (*create_jda_function)(base::ThreadTaskRunnerHandle::Get()); | 412 (*create_jda_function)(base::ThreadTaskRunnerHandle::Get()); |
| 412 if (accelerator && accelerator->IsSupported()) | 413 if (accelerator && accelerator->IsSupported()) |
| 413 return true; | 414 return true; |
| 414 } | 415 } |
| 415 return false; | 416 return false; |
| 416 } | 417 } |
| 417 | 418 |
| 418 } // namespace media | 419 } // namespace media |
| OLD | NEW |