Chromium Code Reviews| Index: media/gpu/android_video_decode_accelerator.cc |
| diff --git a/media/gpu/android_video_decode_accelerator.cc b/media/gpu/android_video_decode_accelerator.cc |
| index 41d3f550768b03219f98c57608a678c0e74ca8ad..2d88fd050d6a564576c1a9b62925ed8b09862eb2 100644 |
| --- a/media/gpu/android_video_decode_accelerator.cc |
| +++ b/media/gpu/android_video_decode_accelerator.cc |
| @@ -172,6 +172,63 @@ class AndroidVideoDecodeAccelerator::OnFrameAvailableHandler |
| DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler); |
| }; |
| +class TaskCountingTaskRunner : public base::SingleThreadTaskRunner { |
| + public: |
| + TaskCountingTaskRunner( |
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| + : task_runner_(task_runner), pending_tasks_(0) {} |
| + |
| + bool PostDelayedTask(const tracked_objects::Location& from_here, |
| + const base::Closure& task, |
| + base::TimeDelta delay) override { |
| + IncrementPendingTasks(); |
| + return task_runner_->PostDelayedTask( |
| + from_here, |
| + base::Bind(&TaskCountingTaskRunner::RunClosureAndDecrementPendingTasks, |
| + base::Unretained(this), task), |
|
liberato (no reviews please)
2016/08/16 23:08:36
not sure if this should be unretained. seems like
|
| + delay); |
| + } |
| + |
| + bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
| + const base::Closure& task, |
| + base::TimeDelta delay) override { |
| + IncrementPendingTasks(); |
| + return task_runner_->PostNonNestableDelayedTask( |
| + from_here, |
| + base::Bind(&TaskCountingTaskRunner::RunClosureAndDecrementPendingTasks, |
| + base::Unretained(this), task), |
|
liberato (no reviews please)
2016/08/16 23:08:36
same question.
|
| + delay); |
| + } |
| + |
| + bool RunsTasksOnCurrentThread() const override { |
| + return task_runner_->RunsTasksOnCurrentThread(); |
| + } |
| + |
| + int PendingTaskCount() { |
| + base::AutoLock l(lock_); |
| + return pending_tasks_; |
| + } |
| + |
| + private: |
| + void IncrementPendingTasks() { |
| + base::AutoLock l(lock_); |
| + pending_tasks_++; |
| + } |
| + |
| + void RunClosureAndDecrementPendingTasks(const base::Closure& task) { |
| + task.Run(); |
| + base::AutoLock l(lock_); |
| + pending_tasks_--; |
| + } |
| + |
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| + |
| + base::Lock lock_; |
| + int pending_tasks_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TaskCountingTaskRunner); |
| +}; |
| + |
| // AVDAManager manages shared resources for a number of AVDA instances. |
| // Its responsibilities include: |
| // - Starting and stopping a shared "construction" thread for instantiating and |
| @@ -196,6 +253,8 @@ class AVDAManager { |
| LOG(ERROR) << "Failed to start construction thread."; |
| return false; |
| } |
| + task_runner_ = |
| + new TaskCountingTaskRunner(construction_thread_.task_runner()); |
| } |
| thread_avda_instances_.insert(avda); |
| @@ -214,11 +273,7 @@ class AVDAManager { |
| if (!thread_avda_instances_.empty()) |
| return; |
| - // Don't stop the thread if there are outstanding requests, since they |
| - // might be hung. They also might simply be incomplete, and the thread |
| - // will stay running until we try to shut it down again. |
| - base::AutoLock auto_lock(autodetection_info_.lock_); |
| - if (autodetection_info_.outstanding_) |
| + if (task_runner_ && task_runner_->PendingTaskCount() > 0) |
| return; |
| construction_thread_.Stop(); |
| @@ -261,36 +316,13 @@ class AVDAManager { |
| scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| - return construction_thread_.task_runner(); |
| - } |
| - |
| - // Called on the main thread when the construction thread will be doing work |
| - // that can potentially hang (e.g., autodetection). There may be several |
| - // calls to this before any call to DoneUsingConstructionThread. |
| - // Note that this should only be called from the main thread, else it's a race |
| - // with IsCodecAutodetectionProbablySafe. |
| - void StartUsingConstructionThread() { |
| - DCHECK(thread_checker_.CalledOnValidThread()); |
| - base::AutoLock auto_lock(autodetection_info_.lock_); |
| - ++autodetection_info_.outstanding_; |
| - } |
| - |
| - // Called on any thread after the potentially dangerous construction thread |
| - // work completes safely. May be called on any thread, including the |
| - // construction thread. |
| - // This assumes that requests are ordered, so please don't mix sync and async |
| - // codec construction here. |
| - void DoneUsingConstructionThread() { |
| - base::AutoLock auto_lock_l(autodetection_info_.lock_); |
| - DCHECK_GT(autodetection_info_.outstanding_, 0); |
| - --autodetection_info_.outstanding_; |
| + return task_runner_; |
| } |
| // Return a hint about whether autodetecting the codec type is safe or not. |
| bool IsCodecAutodetectionProbablySafe() { |
| - base::AutoLock auto_lock_l(autodetection_info_.lock_); |
| - |
| - return autodetection_info_.outstanding_ < kMaxConcurrentCodecAutodetections; |
| + return task_runner_ && |
| + task_runner_->PendingTaskCount() < kMaxConcurrentCodecAutodetections; |
| } |
| // |avda| would like to use |surface_id|. If it is not busy, then mark it |
| @@ -398,16 +430,8 @@ class AVDAManager { |
| // Repeating timer responsible for draining pending IO to the codecs. |
| base::RepeatingTimer io_timer_; |
| - // Data for determining if codec creation is hanging. |
| - struct { |
| - // Lock that protects other members of this struct. |
| - base::Lock lock_; |
| - |
| - // Number of currently pending work items of the construction thread. |
| - int outstanding_ = 0; |
| - } autodetection_info_; |
| - |
| base::Thread construction_thread_; |
| + scoped_refptr<TaskCountingTaskRunner> task_runner_; |
| base::ThreadChecker thread_checker_; |
| @@ -1111,8 +1135,6 @@ void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { |
| } |
| codec_config_->notify_completion_ = codec_config_->allow_autodetection_; |
| - if (codec_config_->allow_autodetection_) |
| - g_avda_manager.Get().StartUsingConstructionThread(); |
| // If we're not trying autodetection, then use the main thread. The original |
| // might be blocked. |
| @@ -1168,11 +1190,6 @@ AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread( |
| codec_config->surface_.j_surface().obj(), media_crypto, true, |
| require_software_codec)); |
| - // If we successfully completed after an autodetect, then let the other |
| - // instances know that we didn't get stuck. |
| - if (codec_config->notify_completion_) |
| - g_avda_manager.Get().DoneUsingConstructionThread(); |
| - |
| return codec; |
| } |
| @@ -1683,13 +1700,8 @@ void AndroidVideoDecodeAccelerator::ReleaseMediaCodec() { |
| if (!codec_config_->allow_autodetection_) { |
| media_codec_.reset(); |
| } else { |
| - g_avda_manager.Get().StartUsingConstructionThread(); |
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
| - g_avda_manager.Get().ConstructionTaskRunner(); |
| - task_runner->DeleteSoon(FROM_HERE, media_codec_.release()); |
| - task_runner->PostTask( |
| - FROM_HERE, base::Bind(&AVDAManager::DoneUsingConstructionThread, |
| - base::Unretained(g_avda_manager.Pointer()))); |
| + g_avda_manager.Get().ConstructionTaskRunner()->DeleteSoon( |
| + FROM_HERE, media_codec_.release()); |
| } |
| } |