| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/avda_codec_allocator.h" | 5 #include "media/gpu/avda_codec_allocator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 codec.reset(); | 42 codec.reset(); |
| 43 if (done_event) | 43 if (done_event) |
| 44 done_event->Signal(); | 44 done_event->Signal(); |
| 45 } | 45 } |
| 46 | 46 |
| 47 } // namespace | 47 } // namespace |
| 48 | 48 |
| 49 CodecConfig::CodecConfig() {} | 49 CodecConfig::CodecConfig() {} |
| 50 CodecConfig::~CodecConfig() {} | 50 CodecConfig::~CodecConfig() {} |
| 51 | 51 |
| 52 AVDACodecAllocator::TestInformation::TestInformation() {} | |
| 53 AVDACodecAllocator::TestInformation::~TestInformation() {} | |
| 54 | |
| 55 AVDACodecAllocator::HangDetector::HangDetector(base::TickClock* tick_clock) | 52 AVDACodecAllocator::HangDetector::HangDetector(base::TickClock* tick_clock) |
| 56 : tick_clock_(tick_clock) {} | 53 : tick_clock_(tick_clock) {} |
| 57 | 54 |
| 58 void AVDACodecAllocator::HangDetector::WillProcessTask( | 55 void AVDACodecAllocator::HangDetector::WillProcessTask( |
| 59 const base::PendingTask& pending_task) { | 56 const base::PendingTask& pending_task) { |
| 60 base::AutoLock l(lock_); | 57 base::AutoLock l(lock_); |
| 61 task_start_time_ = tick_clock_->NowTicks(); | 58 task_start_time_ = tick_clock_->NowTicks(); |
| 62 } | 59 } |
| 63 | 60 |
| 64 void AVDACodecAllocator::HangDetector::DidProcessTask( | 61 void AVDACodecAllocator::HangDetector::DidProcessTask( |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 return false; | 110 return false; |
| 114 | 111 |
| 115 clients_.insert(client); | 112 clients_.insert(client); |
| 116 return true; | 113 return true; |
| 117 } | 114 } |
| 118 | 115 |
| 119 void AVDACodecAllocator::StopThread(AVDACodecAllocatorClient* client) { | 116 void AVDACodecAllocator::StopThread(AVDACodecAllocatorClient* client) { |
| 120 DCHECK(thread_checker_.CalledOnValidThread()); | 117 DCHECK(thread_checker_.CalledOnValidThread()); |
| 121 | 118 |
| 122 clients_.erase(client); | 119 clients_.erase(client); |
| 120 if (!clients_.empty()) { |
| 121 // If we aren't stopping, then signal immediately. |
| 122 if (stop_event_for_testing_) |
| 123 stop_event_for_testing_->Signal(); |
| 124 return; |
| 125 } |
| 126 |
| 123 // Post a task to stop the thread through the thread's task runner and back | 127 // Post a task to stop the thread through the thread's task runner and back |
| 124 // to this thread. This ensures that all pending tasks are run first. If the | 128 // to this thread. This ensures that all pending tasks are run first. If the |
| 125 // thread is hung we don't post a task to avoid leaking an unbounded number | 129 // thread is hung we don't post a task to avoid leaking an unbounded number |
| 126 // of tasks on its queue. If the thread is not hung, but appears to be, it | 130 // of tasks on its queue. If the thread is not hung, but appears to be, it |
| 127 // will stay alive until next time an AVDA tries to stop it. We're | 131 // will stay alive until next time an AVDA tries to stop it. We're |
| 128 // guaranteed to not run StopThreadTask() when the thread is hung because if | 132 // guaranteed to not run StopThreadTask() when the thread is hung because if |
| 129 // an AVDA queues tasks after DoNothing(), the StopThreadTask() reply will | 133 // an AVDA queues tasks after DoNothing(), the StopThreadTask() reply will |
| 130 // be canceled by invalidating its weak pointer. | 134 // be canceled by invalidating its weak pointer. |
| 131 base::WaitableEvent* event = | |
| 132 (test_info_ ? test_info_->stop_event_.get() : nullptr); | |
| 133 if (!clients_.empty()) { | |
| 134 // If we aren't stopping, then signal immediately. | |
| 135 if (event) | |
| 136 event->Signal(); | |
| 137 return; | |
| 138 } | |
| 139 | |
| 140 for (size_t i = 0; i < threads_.size(); i++) { | 135 for (size_t i = 0; i < threads_.size(); i++) { |
| 141 if (threads_[i]->thread.IsRunning() && | 136 if (threads_[i]->thread.IsRunning() && |
| 142 !threads_[i]->hang_detector.IsThreadLikelyHung()) { | 137 !threads_[i]->hang_detector.IsThreadLikelyHung()) { |
| 143 threads_[i]->thread.task_runner()->PostTaskAndReply( | 138 threads_[i]->thread.task_runner()->PostTaskAndReply( |
| 144 FROM_HERE, base::Bind(&base::DoNothing), | 139 FROM_HERE, base::Bind(&base::DoNothing), |
| 145 base::Bind(&AVDACodecAllocator::StopThreadTask, | 140 base::Bind( |
| 146 weak_this_factory_.GetWeakPtr(), i, | 141 &AVDACodecAllocator::StopThreadTask, |
| 147 (i == TaskType::AUTO_CODEC ? event : nullptr))); | 142 weak_this_factory_.GetWeakPtr(), i, |
| 143 (i == TaskType::AUTO_CODEC ? stop_event_for_testing_ : nullptr))); |
| 148 } | 144 } |
| 149 } | 145 } |
| 150 } | 146 } |
| 151 | 147 |
| 152 // Return the task runner for tasks of type |type|. If that thread failed | 148 // Return the task runner for tasks of type |type|. If that thread failed |
| 153 // to start, then fall back to the GPU main thread. | 149 // to start, then fall back to the GPU main thread. |
| 154 scoped_refptr<base::SingleThreadTaskRunner> AVDACodecAllocator::TaskRunnerFor( | 150 scoped_refptr<base::SingleThreadTaskRunner> AVDACodecAllocator::TaskRunnerFor( |
| 155 TaskType task_type) { | 151 TaskType task_type) { |
| 156 DCHECK(thread_checker_.CalledOnValidThread()); | 152 DCHECK(thread_checker_.CalledOnValidThread()); |
| 157 base::Thread& thread = threads_[task_type]->thread; | 153 base::Thread& thread = threads_[task_type]->thread; |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 return TaskType::SW_CODEC; | 359 return TaskType::SW_CODEC; |
| 364 | 360 |
| 365 // If nothing is working, then we can't allocate anyway. | 361 // If nothing is working, then we can't allocate anyway. |
| 366 return TaskType::FAILED_CODEC; | 362 return TaskType::FAILED_CODEC; |
| 367 } | 363 } |
| 368 | 364 |
| 369 base::Thread& AVDACodecAllocator::GetThreadForTesting(TaskType task_type) { | 365 base::Thread& AVDACodecAllocator::GetThreadForTesting(TaskType task_type) { |
| 370 return threads_[task_type]->thread; | 366 return threads_[task_type]->thread; |
| 371 } | 367 } |
| 372 | 368 |
| 373 AVDACodecAllocator::AVDACodecAllocator(TestInformation* test_info) | 369 AVDACodecAllocator::AVDACodecAllocator(base::TickClock* tick_clock, |
| 374 : test_info_(test_info), weak_this_factory_(this) { | 370 base::WaitableEvent* stop_event) |
| 375 // If we're not provided with one, use real time. | 371 : stop_event_for_testing_(stop_event), weak_this_factory_(this) { |
| 376 // Note that we'll leak this, but that's okay since we're a singleton. | 372 // We leak the clock we create, but that's okay because we're a singleton. |
| 377 base::TickClock* tick_clock = nullptr; | 373 auto clock = tick_clock ? tick_clock : new base::DefaultTickClock(); |
| 378 if (!test_info_) | |
| 379 tick_clock = new base::DefaultTickClock(); | |
| 380 else | |
| 381 tick_clock = test_info_->tick_clock_.get(); | |
| 382 | 374 |
| 383 // Create threads with names / indices that match up with TaskType. | 375 // Create threads with names / indices that match up with TaskType. |
| 384 DCHECK_EQ(threads_.size(), TaskType::AUTO_CODEC); | 376 DCHECK_EQ(threads_.size(), TaskType::AUTO_CODEC); |
| 385 threads_.push_back(new ThreadAndHangDetector("AVDAAutoThread", tick_clock)); | 377 threads_.push_back(new ThreadAndHangDetector("AVDAAutoThread", clock)); |
| 386 DCHECK_EQ(threads_.size(), TaskType::SW_CODEC); | 378 DCHECK_EQ(threads_.size(), TaskType::SW_CODEC); |
| 387 threads_.push_back(new ThreadAndHangDetector("AVDASWThread", tick_clock)); | 379 threads_.push_back(new ThreadAndHangDetector("AVDASWThread", clock)); |
| 388 } | 380 } |
| 389 | 381 |
| 390 AVDACodecAllocator::~AVDACodecAllocator() { | 382 AVDACodecAllocator::~AVDACodecAllocator() { |
| 391 // Only tests should reach here. Shut down threads so that we guarantee that | 383 // Only tests should reach here. Shut down threads so that we guarantee that |
| 392 // nothing will use the threads. | 384 // nothing will use the threads. |
| 393 for (size_t i = 0; i < threads_.size(); i++) { | 385 for (size_t i = 0; i < threads_.size(); i++) { |
| 394 if (!threads_[i]->thread.IsRunning()) | 386 if (!threads_[i]->thread.IsRunning()) |
| 395 continue; | 387 continue; |
| 396 threads_[i]->thread.Stop(); | 388 threads_[i]->thread.Stop(); |
| 397 } | 389 } |
| 398 } | 390 } |
| 399 | 391 |
| 400 void AVDACodecAllocator::StopThreadTask(size_t index, | 392 void AVDACodecAllocator::StopThreadTask(size_t index, |
| 401 base::WaitableEvent* event) { | 393 base::WaitableEvent* event) { |
| 402 threads_[index]->thread.Stop(); | 394 threads_[index]->thread.Stop(); |
| 403 if (event) | 395 if (event) |
| 404 event->Signal(); | 396 event->Signal(); |
| 405 } | 397 } |
| 406 | 398 |
| 407 } // namespace media | 399 } // namespace media |
| OLD | NEW |