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

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: Addressed comments. Added thread stopping back. 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 | « media/gpu/android_video_decode_accelerator.h ('k') | 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
11 #include "base/android/build_info.h" 11 #include "base/android/build_info.h"
12 #include "base/auto_reset.h" 12 #include "base/auto_reset.h"
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
15 #include "base/callback_helpers.h" 15 #include "base/callback_helpers.h"
16 #include "base/command_line.h" 16 #include "base/command_line.h"
17 #include "base/lazy_instance.h" 17 #include "base/lazy_instance.h"
18 #include "base/logging.h" 18 #include "base/logging.h"
19 #include "base/message_loop/message_loop.h"
19 #include "base/metrics/histogram.h" 20 #include "base/metrics/histogram.h"
20 #include "base/task_runner_util.h" 21 #include "base/task_runner_util.h"
21 #include "base/threading/thread_checker.h" 22 #include "base/threading/thread_checker.h"
22 #include "base/threading/thread_task_runner_handle.h" 23 #include "base/threading/thread_task_runner_handle.h"
23 #include "base/trace_event/trace_event.h" 24 #include "base/trace_event/trace_event.h"
24 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 25 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
25 #include "gpu/command_buffer/service/mailbox_manager.h" 26 #include "gpu/command_buffer/service/mailbox_manager.h"
26 #include "gpu/ipc/service/gpu_channel.h" 27 #include "gpu/ipc/service/gpu_channel.h"
27 #include "media/base/android/media_codec_bridge.h" 28 #include "media/base/android/media_codec_bridge.h"
28 #include "media/base/android/media_codec_util.h" 29 #include "media/base/android/media_codec_util.h"
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 99
99 constexpr base::TimeDelta NoWaitTimeOut = base::TimeDelta::FromMicroseconds(0); 100 constexpr base::TimeDelta NoWaitTimeOut = base::TimeDelta::FromMicroseconds(0);
100 101
101 constexpr base::TimeDelta IdleTimerTimeOut = base::TimeDelta::FromSeconds(1); 102 constexpr base::TimeDelta IdleTimerTimeOut = base::TimeDelta::FromSeconds(1);
102 103
103 // Time between when we notice an error, and when we actually notify somebody. 104 // Time between when we notice an error, and when we actually notify somebody.
104 // This is to prevent codec errors caused by SurfaceView fullscreen transitions 105 // This is to prevent codec errors caused by SurfaceView fullscreen transitions
105 // from breaking the pipeline, if we're about to be reset anyway. 106 // from breaking the pipeline, if we're about to be reset anyway.
106 constexpr base::TimeDelta ErrorPostingDelay = base::TimeDelta::FromSeconds(2); 107 constexpr base::TimeDelta ErrorPostingDelay = base::TimeDelta::FromSeconds(2);
107 108
108 // Maximum number of concurrent, incomplete codec creations that we'll allow 109 // Give tasks on the construction thread 800ms before considering them hung.
109 // before turning off autodection of codec type. 110 // MediaCodec.configure() calls typically take 100-200ms on a N5, so 800ms is
110 enum { kMaxConcurrentCodecAutodetections = 4 }; 111 // expected to very rarely result in false positives. Also, false positives have
112 // low impact because we resume using the thread if its apparently hung task
113 // completes.
114 constexpr base::TimeDelta kHungTaskDetectionTimeout =
115 base::TimeDelta::FromMilliseconds(800);
111 116
112 // For RecordFormatChangedMetric. 117 // For RecordFormatChangedMetric.
113 enum FormatChangedValue { 118 enum FormatChangedValue {
114 CodecInitialized = false, 119 CodecInitialized = false,
115 MissingFormatChanged = true 120 MissingFormatChanged = true
116 }; 121 };
117 122
118 inline void RecordFormatChangedMetric(FormatChangedValue value) { 123 inline void RecordFormatChangedMetric(FormatChangedValue value) {
119 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.MissingFormatChanged", !!value); 124 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.MissingFormatChanged", !!value);
120 } 125 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 // AVDA that wants the OnFrameAvailable callback. 174 // AVDA that wants the OnFrameAvailable callback.
170 AndroidVideoDecodeAccelerator* owner_; 175 AndroidVideoDecodeAccelerator* owner_;
171 176
172 DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler); 177 DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler);
173 }; 178 };
174 179
175 // AVDAManager manages shared resources for a number of AVDA instances. 180 // AVDAManager manages shared resources for a number of AVDA instances.
176 // Its responsibilities include: 181 // Its responsibilities include:
177 // - Starting and stopping a shared "construction" thread for instantiating and 182 // - Starting and stopping a shared "construction" thread for instantiating and
178 // releasing MediaCodecs. 183 // releasing MediaCodecs.
179 // - Tracking the number of outstanding tasks running on the construction 184 // - Detecting when a task has hung on the construction thread so AVDAs can
180 // thread. (For detecting when one of those tasks has hung indefinitely.) 185 // stop using it.
181 // - Running a RepeatingTimer so that AVDAs can get a regular callback to 186 // - Running a RepeatingTimer so that AVDAs can get a regular callback to
182 // DoIOTask(). 187 // DoIOTask().
183 // - Tracking the allocation of surfaces to AVDAs and delivering callbacks when 188 // - Tracking the allocation of surfaces to AVDAs and delivering callbacks when
184 // surfaces are released. 189 // surfaces are released.
185 class AVDAManager { 190 class AVDAManager {
186 public: 191 public:
187 // Make sure that the construction thread is started for |avda|. 192 class HangDetector : public base::MessageLoop::TaskObserver {
193 public:
194 HangDetector() {}
195
196 void WillProcessTask(const base::PendingTask& pending_task) override {
197 base::AutoLock l(lock_);
198 task_start_time_ = base::TimeTicks::Now();
199 }
200
201 void DidProcessTask(const base::PendingTask& pending_task) override {
202 base::AutoLock l(lock_);
203 task_start_time_ = base::TimeTicks();
204 }
205
206 bool ThreadLikelyHung() {
DaleCurtis 2016/08/19 22:56:03 IsThreadLikelyHung?
watk 2016/08/19 23:22:28 Done.
207 base::AutoLock l(lock_);
208 if (task_start_time_.is_null())
209 return false;
210
211 return (base::TimeTicks::Now() - task_start_time_) >
212 kHungTaskDetectionTimeout;
213 }
214
215 private:
216 base::Lock lock_;
217 // Non-null when a task is currently running.
218 base::TimeTicks task_start_time_;
219
220 DISALLOW_COPY_AND_ASSIGN(HangDetector);
221 };
222
223 // Make sure the construction thread is started for |avda|.
188 bool StartThread(AndroidVideoDecodeAccelerator* avda) { 224 bool StartThread(AndroidVideoDecodeAccelerator* avda) {
189 DCHECK(thread_checker_.CalledOnValidThread()); 225 DCHECK(thread_checker_.CalledOnValidThread());
190 226
191 // 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.
193 // Plus, sometimes we just fail to start the thread.
194 if (!construction_thread_.IsRunning()) { 227 if (!construction_thread_.IsRunning()) {
195 if (!construction_thread_.Start()) { 228 if (!construction_thread_.Start()) {
196 LOG(ERROR) << "Failed to start construction thread."; 229 LOG(ERROR) << "Failed to start construction thread.";
197 return false; 230 return false;
198 } 231 }
232 // Register |hang_detector_| to observe the thread's MessageLoop.
233 construction_thread_.task_runner()->PostTask(
234 FROM_HERE,
235 base::Bind(&base::MessageLoop::AddTaskObserver,
236 base::Unretained(construction_thread_.message_loop()),
237 &hang_detector_));
199 } 238 }
200 239
240 // Cancel any pending StopThreadTask()s because we need the thread now.
241 weak_this_factory_.InvalidateWeakPtrs();
201 thread_avda_instances_.insert(avda); 242 thread_avda_instances_.insert(avda);
202 UMA_HISTOGRAM_ENUMERATION("Media.AVDA.NumAVDAInstances", 243 UMA_HISTOGRAM_ENUMERATION("Media.AVDA.NumAVDAInstances",
203 thread_avda_instances_.size(), 244 thread_avda_instances_.size(),
204 31); // PRESUBMIT_IGNORE_UMA_MAX 245 31); // PRESUBMIT_IGNORE_UMA_MAX
205 return true; 246 return true;
206 } 247 }
207 248
208 // |avda| will no longer need the construction thread. Stop the thread if
209 // this is the last instance.
210 void StopThread(AndroidVideoDecodeAccelerator* avda) { 249 void StopThread(AndroidVideoDecodeAccelerator* avda) {
211 DCHECK(thread_checker_.CalledOnValidThread()); 250 DCHECK(thread_checker_.CalledOnValidThread());
212 251
213 thread_avda_instances_.erase(avda); 252 thread_avda_instances_.erase(avda);
214 if (!thread_avda_instances_.empty()) 253 // Post a task to stop the thread through the thread's task runner and back
215 return; 254 // to this thread. This ensures that all pending tasks are run first. If the
216 255 // thread is hung we don't post a task to avoid leaking an unbounded number
217 // Don't stop the thread if there are outstanding requests, since they 256 // of tasks on its queue. If the thread is not hung, but appears to be, it
218 // might be hung. They also might simply be incomplete, and the thread 257 // will stay alive until next time an AVDA tries to stop it.
219 // will stay running until we try to shut it down again. 258 if (thread_avda_instances_.empty() && !hang_detector_.ThreadLikelyHung()) {
220 base::AutoLock auto_lock(autodetection_info_.lock_); 259 construction_thread_.task_runner()->PostTaskAndReply(
DaleCurtis 2016/08/19 22:56:03 Clever!
221 if (autodetection_info_.outstanding_) 260 FROM_HERE, base::Bind(&base::DoNothing),
222 return; 261 base::Bind(&AVDAManager::StopThreadTask,
223 262 weak_this_factory_.GetWeakPtr()));
224 construction_thread_.Stop(); 263 }
225 } 264 }
226 265
227 // Request periodic callback of |avda|->DoIOTask(). Does nothing if the 266 // Request periodic callback of |avda|->DoIOTask(). Does nothing if the
228 // instance is already registered and the timer started. The first request 267 // instance is already registered and the timer started. The first request
229 // will start the repeating timer on an interval of DecodePollDelay. 268 // will start the repeating timer on an interval of DecodePollDelay.
230 void StartTimer(AndroidVideoDecodeAccelerator* avda) { 269 void StartTimer(AndroidVideoDecodeAccelerator* avda) {
231 DCHECK(thread_checker_.CalledOnValidThread()); 270 DCHECK(thread_checker_.CalledOnValidThread());
232 271
233 timer_avda_instances_.insert(avda); 272 timer_avda_instances_.insert(avda);
234 273
(...skipping 22 matching lines...) Expand all
257 timer_avda_instances_.erase(avda); 296 timer_avda_instances_.erase(avda);
258 if (timer_avda_instances_.empty()) 297 if (timer_avda_instances_.empty())
259 io_timer_.Stop(); 298 io_timer_.Stop();
260 } 299 }
261 300
262 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { 301 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() {
263 DCHECK(thread_checker_.CalledOnValidThread()); 302 DCHECK(thread_checker_.CalledOnValidThread());
264 return construction_thread_.task_runner(); 303 return construction_thread_.task_runner();
265 } 304 }
266 305
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 }
288
289 // Return a hint about whether autodetecting the codec type is safe or not. 306 // Return a hint about whether autodetecting the codec type is safe or not.
290 bool IsCodecAutodetectionProbablySafe() { 307 bool IsCodecAutodetectionProbablySafe() {
291 base::AutoLock auto_lock_l(autodetection_info_.lock_); 308 DCHECK(thread_checker_.CalledOnValidThread());
292 309 return !hang_detector_.ThreadLikelyHung();
293 return autodetection_info_.outstanding_ < kMaxConcurrentCodecAutodetections;
294 } 310 }
295 311
296 // |avda| would like to use |surface_id|. If it is not busy, then mark it 312 // |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, 313 // 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 314 // 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. 315 // is assumed to be on the way out, so we fail its allocation request.
300 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { 316 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
301 // Nobody has to wait for no surface. 317 // Nobody has to wait for no surface.
302 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID) 318 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID)
303 return true; 319 return true;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 363
348 // Promote |waiter| to be the owner. 364 // Promote |waiter| to be the owner.
349 iter->second.owner = waiter; 365 iter->second.owner = waiter;
350 iter->second.waiter = nullptr; 366 iter->second.waiter = nullptr;
351 waiter->OnSurfaceAvailable(true); 367 waiter->OnSurfaceAvailable(true);
352 } 368 }
353 369
354 private: 370 private:
355 friend struct base::DefaultLazyInstanceTraits<AVDAManager>; 371 friend struct base::DefaultLazyInstanceTraits<AVDAManager>;
356 372
357 AVDAManager() : construction_thread_("AVDAThread") {} 373 AVDAManager()
374 : construction_thread_("AVDAThread"), weak_this_factory_(this) {}
358 ~AVDAManager() { NOTREACHED(); } 375 ~AVDAManager() { NOTREACHED(); }
359 376
360 void RunTimer() { 377 void RunTimer() {
361 { 378 {
362 // Call out to all AVDA instances, some of which may attempt to remove 379 // Call out to all AVDA instances, some of which may attempt to remove
363 // themselves from the list during this operation; those removals will be 380 // themselves from the list during this operation; those removals will be
364 // deferred until after all iterations are complete. 381 // deferred until after all iterations are complete.
365 base::AutoReset<bool> scoper(&timer_running_, true); 382 base::AutoReset<bool> scoper(&timer_running_, true);
366 for (auto* avda : timer_avda_instances_) 383 for (auto* avda : timer_avda_instances_)
367 avda->DoIOTask(false); 384 avda->DoIOTask(false);
368 } 385 }
369 386
370 // Take care of any deferred erasures. 387 // Take care of any deferred erasures.
371 for (auto* avda : pending_erase_) 388 for (auto* avda : pending_erase_)
372 StopTimer(avda); 389 StopTimer(avda);
373 pending_erase_.clear(); 390 pending_erase_.clear();
374 391
375 // TODO(dalecurtis): We may want to consider chunking this if task execution 392 // TODO(dalecurtis): We may want to consider chunking this if task execution
376 // takes too long for the combined timer. 393 // takes too long for the combined timer.
377 } 394 }
378 395
396 void StopThreadTask() { construction_thread_.Stop(); }
397
398 // All registered AVDA instances.
399 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_;
400
379 // All AVDA instances that would like us to poll DoIOTask. 401 // All AVDA instances that would like us to poll DoIOTask.
380 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_; 402 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_;
381 403
382 // All AVDA instances that might like to use the construction thread.
383 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_;
384
385 struct OwnerRecord { 404 struct OwnerRecord {
386 AndroidVideoDecodeAccelerator* owner = nullptr; 405 AndroidVideoDecodeAccelerator* owner = nullptr;
387 AndroidVideoDecodeAccelerator* waiter = nullptr; 406 AndroidVideoDecodeAccelerator* waiter = nullptr;
388 }; 407 };
389 // [surface id] = OwnerRecord for that surface. 408 // [surface id] = OwnerRecord for that surface.
390 using SurfaceWaiterMap = std::map<int, OwnerRecord>; 409 using SurfaceWaiterMap = std::map<int, OwnerRecord>;
391 SurfaceWaiterMap surface_waiter_map_; 410 SurfaceWaiterMap surface_waiter_map_;
392 411
393 // Since we can't delete while iterating when using a set, defer erasure until 412 // Since we can't delete while iterating when using a set, defer erasure until
394 // after iteration complete. 413 // after iteration complete.
395 bool timer_running_ = false; 414 bool timer_running_ = false;
396 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; 415 std::set<AndroidVideoDecodeAccelerator*> pending_erase_;
397 416
398 // Repeating timer responsible for draining pending IO to the codecs. 417 // Repeating timer responsible for draining pending IO to the codecs.
399 base::RepeatingTimer io_timer_; 418 base::RepeatingTimer io_timer_;
400 419
401 // Data for determining if codec creation is hanging. 420 // A thread for posting MediaCodec construction and releases to. It's created
402 struct { 421 // lazily when requested.
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_; 422 base::Thread construction_thread_;
411 423
424 // For detecting when MediaCodec a task has hung on |construction_thread_|.
425 HangDetector hang_detector_;
426
412 base::ThreadChecker thread_checker_; 427 base::ThreadChecker thread_checker_;
413 428
429 // For canceling pending StopThreadTask()s.
430 base::WeakPtrFactory<AVDAManager> weak_this_factory_;
431
414 DISALLOW_COPY_AND_ASSIGN(AVDAManager); 432 DISALLOW_COPY_AND_ASSIGN(AVDAManager);
415 }; 433 };
416 434
417 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager = 435 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager =
418 LAZY_INSTANCE_INITIALIZER; 436 LAZY_INSTANCE_INITIALIZER;
419 437
420 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {} 438 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {}
421 439
422 AndroidVideoDecodeAccelerator::CodecConfig::~CodecConfig() {} 440 AndroidVideoDecodeAccelerator::CodecConfig::~CodecConfig() {}
423 441
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 on_destroying_surface_cb_); 597 on_destroying_surface_cb_);
580 598
581 // TODO(watk,liberato): move this into the strategy. 599 // TODO(watk,liberato): move this into the strategy.
582 scoped_refptr<gl::SurfaceTexture> surface_texture = 600 scoped_refptr<gl::SurfaceTexture> surface_texture =
583 strategy_->GetSurfaceTexture(); 601 strategy_->GetSurfaceTexture();
584 if (surface_texture) { 602 if (surface_texture) {
585 on_frame_available_handler_ = 603 on_frame_available_handler_ =
586 new OnFrameAvailableHandler(this, surface_texture); 604 new OnFrameAvailableHandler(this, surface_texture);
587 } 605 }
588 606
589 // Start the thread for async configuration, even if we don't need it now. 607 if (!g_avda_manager.Get().StartThread(this))
590 // ResetCodecState might rebuild the codec later, for example.
591 if (!g_avda_manager.Get().StartThread(this)) {
592 LOG(ERROR) << "Failed to start AVDA thread";
593 return false; 608 return false;
594 }
595 609
596 // If we are encrypted, then we aren't able to create the codec yet. 610 // If we are encrypted, then we aren't able to create the codec yet.
597 if (config_.is_encrypted) { 611 if (config_.is_encrypted) {
598 InitializeCdm(); 612 InitializeCdm();
599 return true; 613 return true;
600 } 614 }
601 615
602 if (deferred_initialization_pending_) { 616 if (deferred_initialization_pending_) {
603 ConfigureMediaCodecAsynchronously(); 617 ConfigureMediaCodecAsynchronously();
604 return true; 618 return true;
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 g_avda_manager.Get().IsCodecAutodetectionProbablySafe(); 1117 g_avda_manager.Get().IsCodecAutodetectionProbablySafe();
1104 1118
1105 // If autodetection is disallowed, fall back to Chrome's software decoders 1119 // If autodetection is disallowed, fall back to Chrome's software decoders
1106 // instead of using the software decoders provided by MediaCodec. 1120 // instead of using the software decoders provided by MediaCodec.
1107 if (!codec_config_->allow_autodetection_ && 1121 if (!codec_config_->allow_autodetection_ &&
1108 IsMediaCodecSoftwareDecodingForbidden()) { 1122 IsMediaCodecSoftwareDecodingForbidden()) {
1109 OnCodecConfigured(nullptr); 1123 OnCodecConfigured(nullptr);
1110 return; 1124 return;
1111 } 1125 }
1112 1126
1113 codec_config_->notify_completion_ = codec_config_->allow_autodetection_;
1114 if (codec_config_->allow_autodetection_)
1115 g_avda_manager.Get().StartUsingConstructionThread();
1116
1117 // If we're not trying autodetection, then use the main thread. The original 1127 // If we're not trying autodetection, then use the main thread. The original
1118 // might be blocked. 1128 // might be blocked.
1119 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 1129 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
1120 codec_config_->allow_autodetection_ 1130 codec_config_->allow_autodetection_
1121 ? g_avda_manager.Get().ConstructionTaskRunner() 1131 ? g_avda_manager.Get().ConstructionTaskRunner()
1122 : base::ThreadTaskRunnerHandle::Get(); 1132 : base::ThreadTaskRunnerHandle::Get();
1123 CHECK(task_runner); 1133 CHECK(task_runner);
1124 1134
1125 base::PostTaskAndReplyWithResult( 1135 base::PostTaskAndReplyWithResult(
1126 task_runner.get(), FROM_HERE, 1136 task_runner.get(), FROM_HERE,
1127 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread, 1137 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread,
1128 codec_config_), 1138 codec_config_),
1129 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured, 1139 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured,
1130 weak_this_factory_.GetWeakPtr())); 1140 weak_this_factory_.GetWeakPtr()));
1131 } 1141 }
DaleCurtis 2016/08/19 22:56:03 Shouldn't this be based on the IsLikelyHung method
watk 2016/08/19 23:22:28 Yep, the IsCodecAutodetectionProbablySafe() on l.1
1132 1142
1133 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() { 1143 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() {
1134 state_ = WAITING_FOR_CODEC; 1144 state_ = WAITING_FOR_CODEC;
1135 1145
1136 // Decide whether to allow autodetection or not. Since we're on the main
1137 // thread, and this request is unordered with respect to pending async config
1138 // attempts, don't record it. It may break book-keeping, and there's not
1139 // much we can do anyway.
1140 codec_config_->allow_autodetection_ = 1146 codec_config_->allow_autodetection_ =
1141 g_avda_manager.Get().IsCodecAutodetectionProbablySafe(); 1147 g_avda_manager.Get().IsCodecAutodetectionProbablySafe();
1142 codec_config_->notify_completion_ = false;
1143 1148
1144 ReleaseMediaCodec(); 1149 ReleaseMediaCodec();
1145 std::unique_ptr<VideoCodecBridge> media_codec = 1150 std::unique_ptr<VideoCodecBridge> media_codec =
1146 ConfigureMediaCodecOnAnyThread(codec_config_); 1151 ConfigureMediaCodecOnAnyThread(codec_config_);
1147 OnCodecConfigured(std::move(media_codec)); 1152 OnCodecConfigured(std::move(media_codec));
1148 return !!media_codec_; 1153 return !!media_codec_;
1149 } 1154 }
1150 1155
1151 std::unique_ptr<VideoCodecBridge> 1156 std::unique_ptr<VideoCodecBridge>
1152 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread( 1157 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread(
1153 scoped_refptr<CodecConfig> codec_config) { 1158 scoped_refptr<CodecConfig> codec_config) {
1154 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); 1159 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec");
1155 1160
1156 jobject media_crypto = codec_config->media_crypto_ 1161 jobject media_crypto = codec_config->media_crypto_
1157 ? codec_config->media_crypto_->obj() 1162 ? codec_config->media_crypto_->obj()
1158 : nullptr; 1163 : nullptr;
1159 1164
1160 // |needs_protected_surface_| implies encrypted stream. 1165 // |needs_protected_surface_| implies encrypted stream.
1161 DCHECK(!codec_config->needs_protected_surface_ || media_crypto); 1166 DCHECK(!codec_config->needs_protected_surface_ || media_crypto);
1162 1167
1163 const bool require_software_codec = !codec_config->allow_autodetection_; 1168 const bool require_software_codec = !codec_config->allow_autodetection_;
1164 1169
1165 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( 1170 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder(
1166 codec_config->codec_, codec_config->needs_protected_surface_, 1171 codec_config->codec_, codec_config->needs_protected_surface_,
1167 codec_config->initial_expected_coded_size_, 1172 codec_config->initial_expected_coded_size_,
1168 codec_config->surface_.j_surface().obj(), media_crypto, true, 1173 codec_config->surface_.j_surface().obj(), media_crypto, true,
1169 require_software_codec)); 1174 require_software_codec));
1170 1175
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; 1176 return codec;
1177 } 1177 }
1178 1178
1179 void AndroidVideoDecodeAccelerator::OnCodecConfigured( 1179 void AndroidVideoDecodeAccelerator::OnCodecConfigured(
1180 std::unique_ptr<VideoCodecBridge> media_codec) { 1180 std::unique_ptr<VideoCodecBridge> media_codec) {
1181 DCHECK(thread_checker_.CalledOnValidThread()); 1181 DCHECK(thread_checker_.CalledOnValidThread());
1182 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); 1182 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED);
1183 1183
1184 // Record one instance of the codec being initialized. 1184 // Record one instance of the codec being initialized.
1185 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); 1185 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 1676 // 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 1677 // thread, and it'll get freed if things start working. If things are
1678 // already working, then it'll be freed soon. 1678 // already working, then it'll be freed soon.
1679 // 1679 //
1680 // We require software codecs when |allow_autodetection_| is false, so use 1680 // 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 1681 // the stored value as a proxy for whether the MediaCodec is software backed
1682 // or not. 1682 // or not.
1683 if (!codec_config_->allow_autodetection_) { 1683 if (!codec_config_->allow_autodetection_) {
1684 media_codec_.reset(); 1684 media_codec_.reset();
1685 } else { 1685 } else {
1686 g_avda_manager.Get().StartUsingConstructionThread(); 1686 g_avda_manager.Get().ConstructionTaskRunner()->DeleteSoon(
1687 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 1687 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 } 1688 }
1694 } 1689 }
1695 1690
1696 // static 1691 // static
1697 bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy( 1692 bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy(
1698 const gpu::GpuPreferences& gpu_preferences) { 1693 const gpu::GpuPreferences& gpu_preferences) {
1699 return true; 1694 return true;
1700 } 1695 }
1701 1696
1702 // static 1697 // static
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1781 1776
1782 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() 1777 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden()
1783 const { 1778 const {
1784 // Prevent MediaCodec from using its internal software decoders when we have 1779 // Prevent MediaCodec from using its internal software decoders when we have
1785 // more secure and up to date versions in the renderer process. 1780 // more secure and up to date versions in the renderer process.
1786 return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 || 1781 return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 ||
1787 codec_config_->codec_ == media::kCodecVP9); 1782 codec_config_->codec_ == media::kCodecVP9);
1788 } 1783 }
1789 1784
1790 } // namespace media 1785 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/android_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698