Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(780)

Side by Side Diff: media/gpu/android_video_decode_accelerator.cc

Issue 2245333004: Convert AVDAs thread hang detection to be timer based (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/android_video_decode_accelerator.h" 5 #include "media/gpu/android_video_decode_accelerator.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 165
166 // Protects changes to owner_. 166 // Protects changes to owner_.
167 base::Lock lock_; 167 base::Lock lock_;
168 168
169 // AVDA that wants the OnFrameAvailable callback. 169 // AVDA that wants the OnFrameAvailable callback.
170 AndroidVideoDecodeAccelerator* owner_; 170 AndroidVideoDecodeAccelerator* owner_;
171 171
172 DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler); 172 DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler);
173 }; 173 };
174 174
175 class TaskCountingTaskRunner : public base::SingleThreadTaskRunner {
176 public:
177 TaskCountingTaskRunner(
178 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
179 : task_runner_(task_runner), pending_tasks_(0) {}
180
181 bool PostDelayedTask(const tracked_objects::Location& from_here,
182 const base::Closure& task,
183 base::TimeDelta delay) override {
184 IncrementPendingTasks();
185 return task_runner_->PostDelayedTask(
186 from_here,
187 base::Bind(&TaskCountingTaskRunner::RunClosureAndDecrementPendingTasks,
188 base::Unretained(this), task),
liberato (no reviews please) 2016/08/16 23:08:36 not sure if this should be unretained. seems like
189 delay);
190 }
191
192 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
193 const base::Closure& task,
194 base::TimeDelta delay) override {
195 IncrementPendingTasks();
196 return task_runner_->PostNonNestableDelayedTask(
197 from_here,
198 base::Bind(&TaskCountingTaskRunner::RunClosureAndDecrementPendingTasks,
199 base::Unretained(this), task),
liberato (no reviews please) 2016/08/16 23:08:36 same question.
200 delay);
201 }
202
203 bool RunsTasksOnCurrentThread() const override {
204 return task_runner_->RunsTasksOnCurrentThread();
205 }
206
207 int PendingTaskCount() {
208 base::AutoLock l(lock_);
209 return pending_tasks_;
210 }
211
212 private:
213 void IncrementPendingTasks() {
214 base::AutoLock l(lock_);
215 pending_tasks_++;
216 }
217
218 void RunClosureAndDecrementPendingTasks(const base::Closure& task) {
219 task.Run();
220 base::AutoLock l(lock_);
221 pending_tasks_--;
222 }
223
224 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
225
226 base::Lock lock_;
227 int pending_tasks_;
228
229 DISALLOW_COPY_AND_ASSIGN(TaskCountingTaskRunner);
230 };
231
175 // AVDAManager manages shared resources for a number of AVDA instances. 232 // AVDAManager manages shared resources for a number of AVDA instances.
176 // Its responsibilities include: 233 // Its responsibilities include:
177 // - Starting and stopping a shared "construction" thread for instantiating and 234 // - Starting and stopping a shared "construction" thread for instantiating and
178 // releasing MediaCodecs. 235 // releasing MediaCodecs.
179 // - Tracking the number of outstanding tasks running on the construction 236 // - Tracking the number of outstanding tasks running on the construction
180 // thread. (For detecting when one of those tasks has hung indefinitely.) 237 // thread. (For detecting when one of those tasks has hung indefinitely.)
181 // - Running a RepeatingTimer so that AVDAs can get a regular callback to 238 // - Running a RepeatingTimer so that AVDAs can get a regular callback to
182 // DoIOTask(). 239 // DoIOTask().
183 // - Tracking the allocation of surfaces to AVDAs and delivering callbacks when 240 // - Tracking the allocation of surfaces to AVDAs and delivering callbacks when
184 // surfaces are released. 241 // surfaces are released.
185 class AVDAManager { 242 class AVDAManager {
186 public: 243 public:
187 // Make sure that the construction thread is started for |avda|. 244 // Make sure that the construction thread is started for |avda|.
188 bool StartThread(AndroidVideoDecodeAccelerator* avda) { 245 bool StartThread(AndroidVideoDecodeAccelerator* avda) {
189 DCHECK(thread_checker_.CalledOnValidThread()); 246 DCHECK(thread_checker_.CalledOnValidThread());
190 247
191 // If we chose not to shut it down due to pending codec constructions, then 248 // If we chose not to shut it down due to pending codec constructions, then
192 // the thread might already be started even if there are no avda instances. 249 // the thread might already be started even if there are no avda instances.
193 // Plus, sometimes we just fail to start the thread. 250 // Plus, sometimes we just fail to start the thread.
194 if (!construction_thread_.IsRunning()) { 251 if (!construction_thread_.IsRunning()) {
195 if (!construction_thread_.Start()) { 252 if (!construction_thread_.Start()) {
196 LOG(ERROR) << "Failed to start construction thread."; 253 LOG(ERROR) << "Failed to start construction thread.";
197 return false; 254 return false;
198 } 255 }
256 task_runner_ =
257 new TaskCountingTaskRunner(construction_thread_.task_runner());
199 } 258 }
200 259
201 thread_avda_instances_.insert(avda); 260 thread_avda_instances_.insert(avda);
202 UMA_HISTOGRAM_ENUMERATION("Media.AVDA.NumAVDAInstances", 261 UMA_HISTOGRAM_ENUMERATION("Media.AVDA.NumAVDAInstances",
203 thread_avda_instances_.size(), 262 thread_avda_instances_.size(),
204 31); // PRESUBMIT_IGNORE_UMA_MAX 263 31); // PRESUBMIT_IGNORE_UMA_MAX
205 return true; 264 return true;
206 } 265 }
207 266
208 // |avda| will no longer need the construction thread. Stop the thread if 267 // |avda| will no longer need the construction thread. Stop the thread if
209 // this is the last instance. 268 // this is the last instance.
210 void StopThread(AndroidVideoDecodeAccelerator* avda) { 269 void StopThread(AndroidVideoDecodeAccelerator* avda) {
211 DCHECK(thread_checker_.CalledOnValidThread()); 270 DCHECK(thread_checker_.CalledOnValidThread());
212 271
213 thread_avda_instances_.erase(avda); 272 thread_avda_instances_.erase(avda);
214 if (!thread_avda_instances_.empty()) 273 if (!thread_avda_instances_.empty())
215 return; 274 return;
216 275
217 // Don't stop the thread if there are outstanding requests, since they 276 if (task_runner_ && task_runner_->PendingTaskCount() > 0)
218 // might be hung. They also might simply be incomplete, and the thread
219 // will stay running until we try to shut it down again.
220 base::AutoLock auto_lock(autodetection_info_.lock_);
221 if (autodetection_info_.outstanding_)
222 return; 277 return;
223 278
224 construction_thread_.Stop(); 279 construction_thread_.Stop();
225 } 280 }
226 281
227 // Request periodic callback of |avda|->DoIOTask(). Does nothing if the 282 // Request periodic callback of |avda|->DoIOTask(). Does nothing if the
228 // instance is already registered and the timer started. The first request 283 // instance is already registered and the timer started. The first request
229 // will start the repeating timer on an interval of DecodePollDelay. 284 // will start the repeating timer on an interval of DecodePollDelay.
230 void StartTimer(AndroidVideoDecodeAccelerator* avda) { 285 void StartTimer(AndroidVideoDecodeAccelerator* avda) {
231 DCHECK(thread_checker_.CalledOnValidThread()); 286 DCHECK(thread_checker_.CalledOnValidThread());
(...skipping 22 matching lines...) Expand all
254 return; 309 return;
255 } 310 }
256 311
257 timer_avda_instances_.erase(avda); 312 timer_avda_instances_.erase(avda);
258 if (timer_avda_instances_.empty()) 313 if (timer_avda_instances_.empty())
259 io_timer_.Stop(); 314 io_timer_.Stop();
260 } 315 }
261 316
262 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { 317 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() {
263 DCHECK(thread_checker_.CalledOnValidThread()); 318 DCHECK(thread_checker_.CalledOnValidThread());
264 return construction_thread_.task_runner(); 319 return task_runner_;
265 }
266
267 // Called on the main thread when the construction thread will be doing work
268 // that can potentially hang (e.g., autodetection). There may be several
269 // calls to this before any call to DoneUsingConstructionThread.
270 // Note that this should only be called from the main thread, else it's a race
271 // with IsCodecAutodetectionProbablySafe.
272 void StartUsingConstructionThread() {
273 DCHECK(thread_checker_.CalledOnValidThread());
274 base::AutoLock auto_lock(autodetection_info_.lock_);
275 ++autodetection_info_.outstanding_;
276 }
277
278 // Called on any thread after the potentially dangerous construction thread
279 // work completes safely. May be called on any thread, including the
280 // construction thread.
281 // This assumes that requests are ordered, so please don't mix sync and async
282 // codec construction here.
283 void DoneUsingConstructionThread() {
284 base::AutoLock auto_lock_l(autodetection_info_.lock_);
285 DCHECK_GT(autodetection_info_.outstanding_, 0);
286 --autodetection_info_.outstanding_;
287 } 320 }
288 321
289 // Return a hint about whether autodetecting the codec type is safe or not. 322 // Return a hint about whether autodetecting the codec type is safe or not.
290 bool IsCodecAutodetectionProbablySafe() { 323 bool IsCodecAutodetectionProbablySafe() {
291 base::AutoLock auto_lock_l(autodetection_info_.lock_); 324 return task_runner_ &&
292 325 task_runner_->PendingTaskCount() < kMaxConcurrentCodecAutodetections;
293 return autodetection_info_.outstanding_ < kMaxConcurrentCodecAutodetections;
294 } 326 }
295 327
296 // |avda| would like to use |surface_id|. If it is not busy, then mark it 328 // |avda| would like to use |surface_id|. If it is not busy, then mark it
297 // as busy and return true. If it is busy, then replace any existing waiter, 329 // as busy and return true. If it is busy, then replace any existing waiter,
298 // make |avda| the current waiter, and return false. Any existing waiter 330 // make |avda| the current waiter, and return false. Any existing waiter
299 // is assumed to be on the way out, so we fail its allocation request. 331 // is assumed to be on the way out, so we fail its allocation request.
300 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { 332 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
301 // Nobody has to wait for no surface. 333 // Nobody has to wait for no surface.
302 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID) 334 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID)
303 return true; 335 return true;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
391 SurfaceWaiterMap surface_waiter_map_; 423 SurfaceWaiterMap surface_waiter_map_;
392 424
393 // Since we can't delete while iterating when using a set, defer erasure until 425 // Since we can't delete while iterating when using a set, defer erasure until
394 // after iteration complete. 426 // after iteration complete.
395 bool timer_running_ = false; 427 bool timer_running_ = false;
396 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; 428 std::set<AndroidVideoDecodeAccelerator*> pending_erase_;
397 429
398 // Repeating timer responsible for draining pending IO to the codecs. 430 // Repeating timer responsible for draining pending IO to the codecs.
399 base::RepeatingTimer io_timer_; 431 base::RepeatingTimer io_timer_;
400 432
401 // Data for determining if codec creation is hanging.
402 struct {
403 // Lock that protects other members of this struct.
404 base::Lock lock_;
405
406 // Number of currently pending work items of the construction thread.
407 int outstanding_ = 0;
408 } autodetection_info_;
409
410 base::Thread construction_thread_; 433 base::Thread construction_thread_;
434 scoped_refptr<TaskCountingTaskRunner> task_runner_;
411 435
412 base::ThreadChecker thread_checker_; 436 base::ThreadChecker thread_checker_;
413 437
414 DISALLOW_COPY_AND_ASSIGN(AVDAManager); 438 DISALLOW_COPY_AND_ASSIGN(AVDAManager);
415 }; 439 };
416 440
417 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager = 441 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager =
418 LAZY_INSTANCE_INITIALIZER; 442 LAZY_INSTANCE_INITIALIZER;
419 443
420 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {} 444 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {}
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 1128
1105 // If autodetection is disallowed, fall back to Chrome's software decoders 1129 // If autodetection is disallowed, fall back to Chrome's software decoders
1106 // instead of using the software decoders provided by MediaCodec. 1130 // instead of using the software decoders provided by MediaCodec.
1107 if (!codec_config_->allow_autodetection_ && 1131 if (!codec_config_->allow_autodetection_ &&
1108 IsMediaCodecSoftwareDecodingForbidden()) { 1132 IsMediaCodecSoftwareDecodingForbidden()) {
1109 OnCodecConfigured(nullptr); 1133 OnCodecConfigured(nullptr);
1110 return; 1134 return;
1111 } 1135 }
1112 1136
1113 codec_config_->notify_completion_ = codec_config_->allow_autodetection_; 1137 codec_config_->notify_completion_ = codec_config_->allow_autodetection_;
1114 if (codec_config_->allow_autodetection_)
1115 g_avda_manager.Get().StartUsingConstructionThread();
1116 1138
1117 // If we're not trying autodetection, then use the main thread. The original 1139 // If we're not trying autodetection, then use the main thread. The original
1118 // might be blocked. 1140 // might be blocked.
1119 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 1141 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
1120 codec_config_->allow_autodetection_ 1142 codec_config_->allow_autodetection_
1121 ? g_avda_manager.Get().ConstructionTaskRunner() 1143 ? g_avda_manager.Get().ConstructionTaskRunner()
1122 : base::ThreadTaskRunnerHandle::Get(); 1144 : base::ThreadTaskRunnerHandle::Get();
1123 CHECK(task_runner); 1145 CHECK(task_runner);
1124 1146
1125 base::PostTaskAndReplyWithResult( 1147 base::PostTaskAndReplyWithResult(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 DCHECK(!codec_config->needs_protected_surface_ || media_crypto); 1183 DCHECK(!codec_config->needs_protected_surface_ || media_crypto);
1162 1184
1163 const bool require_software_codec = !codec_config->allow_autodetection_; 1185 const bool require_software_codec = !codec_config->allow_autodetection_;
1164 1186
1165 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( 1187 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder(
1166 codec_config->codec_, codec_config->needs_protected_surface_, 1188 codec_config->codec_, codec_config->needs_protected_surface_,
1167 codec_config->initial_expected_coded_size_, 1189 codec_config->initial_expected_coded_size_,
1168 codec_config->surface_.j_surface().obj(), media_crypto, true, 1190 codec_config->surface_.j_surface().obj(), media_crypto, true,
1169 require_software_codec)); 1191 require_software_codec));
1170 1192
1171 // If we successfully completed after an autodetect, then let the other
1172 // instances know that we didn't get stuck.
1173 if (codec_config->notify_completion_)
1174 g_avda_manager.Get().DoneUsingConstructionThread();
1175
1176 return codec; 1193 return codec;
1177 } 1194 }
1178 1195
1179 void AndroidVideoDecodeAccelerator::OnCodecConfigured( 1196 void AndroidVideoDecodeAccelerator::OnCodecConfigured(
1180 std::unique_ptr<VideoCodecBridge> media_codec) { 1197 std::unique_ptr<VideoCodecBridge> media_codec) {
1181 DCHECK(thread_checker_.CalledOnValidThread()); 1198 DCHECK(thread_checker_.CalledOnValidThread());
1182 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); 1199 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED);
1183 1200
1184 // Record one instance of the codec being initialized. 1201 // Record one instance of the codec being initialized.
1185 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); 1202 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized);
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
1676 // backed by hardware, else it may hang too. Post it to the construction 1693 // backed by hardware, else it may hang too. Post it to the construction
1677 // thread, and it'll get freed if things start working. If things are 1694 // thread, and it'll get freed if things start working. If things are
1678 // already working, then it'll be freed soon. 1695 // already working, then it'll be freed soon.
1679 // 1696 //
1680 // We require software codecs when |allow_autodetection_| is false, so use 1697 // We require software codecs when |allow_autodetection_| is false, so use
1681 // the stored value as a proxy for whether the MediaCodec is software backed 1698 // the stored value as a proxy for whether the MediaCodec is software backed
1682 // or not. 1699 // or not.
1683 if (!codec_config_->allow_autodetection_) { 1700 if (!codec_config_->allow_autodetection_) {
1684 media_codec_.reset(); 1701 media_codec_.reset();
1685 } else { 1702 } else {
1686 g_avda_manager.Get().StartUsingConstructionThread(); 1703 g_avda_manager.Get().ConstructionTaskRunner()->DeleteSoon(
1687 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 1704 FROM_HERE, media_codec_.release());
1688 g_avda_manager.Get().ConstructionTaskRunner();
1689 task_runner->DeleteSoon(FROM_HERE, media_codec_.release());
1690 task_runner->PostTask(
1691 FROM_HERE, base::Bind(&AVDAManager::DoneUsingConstructionThread,
1692 base::Unretained(g_avda_manager.Pointer())));
1693 } 1705 }
1694 } 1706 }
1695 1707
1696 // static 1708 // static
1697 bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy( 1709 bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy(
1698 const gpu::GpuPreferences& gpu_preferences) { 1710 const gpu::GpuPreferences& gpu_preferences) {
1699 return true; 1711 return true;
1700 } 1712 }
1701 1713
1702 // static 1714 // static
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1781 1793
1782 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() 1794 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden()
1783 const { 1795 const {
1784 // Prevent MediaCodec from using its internal software decoders when we have 1796 // Prevent MediaCodec from using its internal software decoders when we have
1785 // more secure and up to date versions in the renderer process. 1797 // more secure and up to date versions in the renderer process.
1786 return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 || 1798 return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 ||
1787 codec_config_->codec_ == media::kCodecVP9); 1799 codec_config_->codec_ == media::kCodecVP9);
1788 } 1800 }
1789 1801
1790 } // namespace media 1802 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698