| 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 |