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

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: clarified comment 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 IsThreadLikelyHung() {
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();
242
201 thread_avda_instances_.insert(avda); 243 thread_avda_instances_.insert(avda);
202 UMA_HISTOGRAM_ENUMERATION("Media.AVDA.NumAVDAInstances", 244 UMA_HISTOGRAM_ENUMERATION("Media.AVDA.NumAVDAInstances",
203 thread_avda_instances_.size(), 245 thread_avda_instances_.size(),
204 31); // PRESUBMIT_IGNORE_UMA_MAX 246 31); // PRESUBMIT_IGNORE_UMA_MAX
205 return true; 247 return true;
206 } 248 }
207 249
208 // |avda| will no longer need the construction thread. Stop the thread if
209 // this is the last instance.
210 void StopThread(AndroidVideoDecodeAccelerator* avda) { 250 void StopThread(AndroidVideoDecodeAccelerator* avda) {
211 DCHECK(thread_checker_.CalledOnValidThread()); 251 DCHECK(thread_checker_.CalledOnValidThread());
212 252
213 thread_avda_instances_.erase(avda); 253 thread_avda_instances_.erase(avda);
214 if (!thread_avda_instances_.empty()) 254 // Post a task to stop the thread through the thread's task runner and back
215 return; 255 // to this thread. This ensures that all pending tasks are run first. If the
216 256 // 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 257 // 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 258 // will stay alive until next time an AVDA tries to stop it. We're
219 // will stay running until we try to shut it down again. 259 // guaranteed to not run StopThreadTask() when the thread is hung because if
220 base::AutoLock auto_lock(autodetection_info_.lock_); 260 // an AVDA queues tasks after DoNothing(), the StopThreadTask() reply will
221 if (autodetection_info_.outstanding_) 261 // be canceled by invalidating its weak pointer.
222 return; 262 if (thread_avda_instances_.empty() &&
223 263 !hang_detector_.IsThreadLikelyHung()) {
224 construction_thread_.Stop(); 264 construction_thread_.task_runner()->PostTaskAndReply(
265 FROM_HERE, base::Bind(&base::DoNothing),
266 base::Bind(&AVDAManager::StopThreadTask,
267 weak_this_factory_.GetWeakPtr()));
268 }
225 } 269 }
226 270
227 // Request periodic callback of |avda|->DoIOTask(). Does nothing if the 271 // Request periodic callback of |avda|->DoIOTask(). Does nothing if the
228 // instance is already registered and the timer started. The first request 272 // instance is already registered and the timer started. The first request
229 // will start the repeating timer on an interval of DecodePollDelay. 273 // will start the repeating timer on an interval of DecodePollDelay.
230 void StartTimer(AndroidVideoDecodeAccelerator* avda) { 274 void StartTimer(AndroidVideoDecodeAccelerator* avda) {
231 DCHECK(thread_checker_.CalledOnValidThread()); 275 DCHECK(thread_checker_.CalledOnValidThread());
232 276
233 timer_avda_instances_.insert(avda); 277 timer_avda_instances_.insert(avda);
234 278
(...skipping 22 matching lines...) Expand all
257 timer_avda_instances_.erase(avda); 301 timer_avda_instances_.erase(avda);
258 if (timer_avda_instances_.empty()) 302 if (timer_avda_instances_.empty())
259 io_timer_.Stop(); 303 io_timer_.Stop();
260 } 304 }
261 305
262 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { 306 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() {
263 DCHECK(thread_checker_.CalledOnValidThread()); 307 DCHECK(thread_checker_.CalledOnValidThread());
264 return construction_thread_.task_runner(); 308 return construction_thread_.task_runner();
265 } 309 }
266 310
267 // Called on the main thread when the construction thread will be doing work 311 // Returns a hint about whether the construction thread has hung.
268 // that can potentially hang (e.g., autodetection). There may be several 312 bool IsConstructionThreadLikelyHung() {
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()); 313 DCHECK(thread_checker_.CalledOnValidThread());
274 base::AutoLock auto_lock(autodetection_info_.lock_); 314 return hang_detector_.IsThreadLikelyHung();
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.
290 bool IsCodecAutodetectionProbablySafe() {
291 base::AutoLock auto_lock_l(autodetection_info_.lock_);
292
293 return autodetection_info_.outstanding_ < kMaxConcurrentCodecAutodetections;
294 } 315 }
295 316
296 // |avda| would like to use |surface_id|. If it is not busy, then mark it 317 // |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, 318 // 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 319 // 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. 320 // is assumed to be on the way out, so we fail its allocation request.
300 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { 321 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
301 // Nobody has to wait for no surface. 322 // Nobody has to wait for no surface.
302 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID) 323 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID)
303 return true; 324 return true;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 368
348 // Promote |waiter| to be the owner. 369 // Promote |waiter| to be the owner.
349 iter->second.owner = waiter; 370 iter->second.owner = waiter;
350 iter->second.waiter = nullptr; 371 iter->second.waiter = nullptr;
351 waiter->OnSurfaceAvailable(true); 372 waiter->OnSurfaceAvailable(true);
352 } 373 }
353 374
354 private: 375 private:
355 friend struct base::DefaultLazyInstanceTraits<AVDAManager>; 376 friend struct base::DefaultLazyInstanceTraits<AVDAManager>;
356 377
357 AVDAManager() : construction_thread_("AVDAThread") {} 378 AVDAManager()
379 : construction_thread_("AVDAThread"), weak_this_factory_(this) {}
358 ~AVDAManager() { NOTREACHED(); } 380 ~AVDAManager() { NOTREACHED(); }
359 381
360 void RunTimer() { 382 void RunTimer() {
361 { 383 {
362 // Call out to all AVDA instances, some of which may attempt to remove 384 // 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 385 // themselves from the list during this operation; those removals will be
364 // deferred until after all iterations are complete. 386 // deferred until after all iterations are complete.
365 base::AutoReset<bool> scoper(&timer_running_, true); 387 base::AutoReset<bool> scoper(&timer_running_, true);
366 for (auto* avda : timer_avda_instances_) 388 for (auto* avda : timer_avda_instances_)
367 avda->DoIOTask(false); 389 avda->DoIOTask(false);
368 } 390 }
369 391
370 // Take care of any deferred erasures. 392 // Take care of any deferred erasures.
371 for (auto* avda : pending_erase_) 393 for (auto* avda : pending_erase_)
372 StopTimer(avda); 394 StopTimer(avda);
373 pending_erase_.clear(); 395 pending_erase_.clear();
374 396
375 // TODO(dalecurtis): We may want to consider chunking this if task execution 397 // TODO(dalecurtis): We may want to consider chunking this if task execution
376 // takes too long for the combined timer. 398 // takes too long for the combined timer.
377 } 399 }
378 400
401 void StopThreadTask() { construction_thread_.Stop(); }
402
403 // All registered AVDA instances.
404 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_;
405
379 // All AVDA instances that would like us to poll DoIOTask. 406 // All AVDA instances that would like us to poll DoIOTask.
380 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_; 407 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_;
381 408
382 // All AVDA instances that might like to use the construction thread.
383 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_;
384
385 struct OwnerRecord { 409 struct OwnerRecord {
386 AndroidVideoDecodeAccelerator* owner = nullptr; 410 AndroidVideoDecodeAccelerator* owner = nullptr;
387 AndroidVideoDecodeAccelerator* waiter = nullptr; 411 AndroidVideoDecodeAccelerator* waiter = nullptr;
388 }; 412 };
389 // [surface id] = OwnerRecord for that surface. 413 // [surface id] = OwnerRecord for that surface.
390 using SurfaceWaiterMap = std::map<int, OwnerRecord>; 414 using SurfaceWaiterMap = std::map<int, OwnerRecord>;
391 SurfaceWaiterMap surface_waiter_map_; 415 SurfaceWaiterMap surface_waiter_map_;
392 416
393 // Since we can't delete while iterating when using a set, defer erasure until 417 // Since we can't delete while iterating when using a set, defer erasure until
394 // after iteration complete. 418 // after iteration complete.
395 bool timer_running_ = false; 419 bool timer_running_ = false;
396 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; 420 std::set<AndroidVideoDecodeAccelerator*> pending_erase_;
397 421
398 // Repeating timer responsible for draining pending IO to the codecs. 422 // Repeating timer responsible for draining pending IO to the codecs.
399 base::RepeatingTimer io_timer_; 423 base::RepeatingTimer io_timer_;
400 424
401 // Data for determining if codec creation is hanging. 425 // A thread for posting MediaCodec construction and releases to. It's created
402 struct { 426 // 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_; 427 base::Thread construction_thread_;
411 428
429 // For detecting when a task has hung on |construction_thread_|.
430 HangDetector hang_detector_;
431
412 base::ThreadChecker thread_checker_; 432 base::ThreadChecker thread_checker_;
413 433
434 // For canceling pending StopThreadTask()s.
435 base::WeakPtrFactory<AVDAManager> weak_this_factory_;
436
414 DISALLOW_COPY_AND_ASSIGN(AVDAManager); 437 DISALLOW_COPY_AND_ASSIGN(AVDAManager);
415 }; 438 };
416 439
417 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager = 440 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager =
418 LAZY_INSTANCE_INITIALIZER; 441 LAZY_INSTANCE_INITIALIZER;
419 442
420 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {} 443 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {}
421 444
422 AndroidVideoDecodeAccelerator::CodecConfig::~CodecConfig() {} 445 AndroidVideoDecodeAccelerator::CodecConfig::~CodecConfig() {}
423 446
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 on_destroying_surface_cb_); 602 on_destroying_surface_cb_);
580 603
581 // TODO(watk,liberato): move this into the strategy. 604 // TODO(watk,liberato): move this into the strategy.
582 scoped_refptr<gl::SurfaceTexture> surface_texture = 605 scoped_refptr<gl::SurfaceTexture> surface_texture =
583 strategy_->GetSurfaceTexture(); 606 strategy_->GetSurfaceTexture();
584 if (surface_texture) { 607 if (surface_texture) {
585 on_frame_available_handler_ = 608 on_frame_available_handler_ =
586 new OnFrameAvailableHandler(this, surface_texture); 609 new OnFrameAvailableHandler(this, surface_texture);
587 } 610 }
588 611
589 // Start the thread for async configuration, even if we don't need it now. 612 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; 613 return false;
594 }
595 614
596 // If we are encrypted, then we aren't able to create the codec yet. 615 // If we are encrypted, then we aren't able to create the codec yet.
597 if (config_.is_encrypted) { 616 if (config_.is_encrypted) {
598 InitializeCdm(); 617 InitializeCdm();
599 return true; 618 return true;
600 } 619 }
601 620
602 if (deferred_initialization_pending_) { 621 if (deferred_initialization_pending_) {
603 ConfigureMediaCodecAsynchronously(); 622 ConfigureMediaCodecAsynchronously();
604 return true; 623 return true;
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 // strategy to forget the codec avoids this. 1112 // strategy to forget the codec avoids this.
1094 if (media_codec_) { 1113 if (media_codec_) {
1095 ReleaseMediaCodec(); 1114 ReleaseMediaCodec();
1096 strategy_->CodecChanged(nullptr); 1115 strategy_->CodecChanged(nullptr);
1097 } 1116 }
1098 1117
1099 // Choose whether to autodetect the codec type. Note that we do this after 1118 // Choose whether to autodetect the codec type. Note that we do this after
1100 // releasing any outgoing codec, so that |codec_config_| still matches the 1119 // releasing any outgoing codec, so that |codec_config_| still matches the
1101 // outgoing codec for ReleaseMediaCodec(). 1120 // outgoing codec for ReleaseMediaCodec().
1102 codec_config_->allow_autodetection_ = 1121 codec_config_->allow_autodetection_ =
1103 g_avda_manager.Get().IsCodecAutodetectionProbablySafe(); 1122 !g_avda_manager.Get().IsConstructionThreadLikelyHung();
1104 1123
1105 // If autodetection is disallowed, fall back to Chrome's software decoders 1124 // If autodetection is disallowed, fall back to Chrome's software decoders
1106 // instead of using the software decoders provided by MediaCodec. 1125 // instead of using the software decoders provided by MediaCodec.
1107 if (!codec_config_->allow_autodetection_ && 1126 if (!codec_config_->allow_autodetection_ &&
1108 IsMediaCodecSoftwareDecodingForbidden()) { 1127 IsMediaCodecSoftwareDecodingForbidden()) {
1109 OnCodecConfigured(nullptr); 1128 OnCodecConfigured(nullptr);
1110 return; 1129 return;
1111 } 1130 }
1112 1131
1113 codec_config_->notify_completion_ = codec_config_->allow_autodetection_; 1132 // If we're not trying autodetection, then use the main thread.
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
1118 // might be blocked.
1119 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 1133 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
1120 codec_config_->allow_autodetection_ 1134 codec_config_->allow_autodetection_
1121 ? g_avda_manager.Get().ConstructionTaskRunner() 1135 ? g_avda_manager.Get().ConstructionTaskRunner()
1122 : base::ThreadTaskRunnerHandle::Get(); 1136 : base::ThreadTaskRunnerHandle::Get();
1123 CHECK(task_runner); 1137 CHECK(task_runner);
1124 1138
1125 base::PostTaskAndReplyWithResult( 1139 base::PostTaskAndReplyWithResult(
1126 task_runner.get(), FROM_HERE, 1140 task_runner.get(), FROM_HERE,
1127 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread, 1141 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread,
1128 codec_config_), 1142 codec_config_),
1129 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured, 1143 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured,
1130 weak_this_factory_.GetWeakPtr())); 1144 weak_this_factory_.GetWeakPtr()));
1131 } 1145 }
1132 1146
1133 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() { 1147 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() {
1134 state_ = WAITING_FOR_CODEC; 1148 state_ = WAITING_FOR_CODEC;
1135 1149
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_ = 1150 codec_config_->allow_autodetection_ =
1141 g_avda_manager.Get().IsCodecAutodetectionProbablySafe(); 1151 !g_avda_manager.Get().IsConstructionThreadLikelyHung();
1142 codec_config_->notify_completion_ = false;
1143 1152
1144 ReleaseMediaCodec(); 1153 ReleaseMediaCodec();
1145 std::unique_ptr<VideoCodecBridge> media_codec = 1154 std::unique_ptr<VideoCodecBridge> media_codec =
1146 ConfigureMediaCodecOnAnyThread(codec_config_); 1155 ConfigureMediaCodecOnAnyThread(codec_config_);
1147 OnCodecConfigured(std::move(media_codec)); 1156 OnCodecConfigured(std::move(media_codec));
1148 return !!media_codec_; 1157 return !!media_codec_;
1149 } 1158 }
1150 1159
1151 std::unique_ptr<VideoCodecBridge> 1160 std::unique_ptr<VideoCodecBridge>
1152 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread( 1161 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread(
1153 scoped_refptr<CodecConfig> codec_config) { 1162 scoped_refptr<CodecConfig> codec_config) {
1154 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); 1163 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec");
1155 1164
1156 jobject media_crypto = codec_config->media_crypto_ 1165 jobject media_crypto = codec_config->media_crypto_
1157 ? codec_config->media_crypto_->obj() 1166 ? codec_config->media_crypto_->obj()
1158 : nullptr; 1167 : nullptr;
1159 1168
1160 // |needs_protected_surface_| implies encrypted stream. 1169 // |needs_protected_surface_| implies encrypted stream.
1161 DCHECK(!codec_config->needs_protected_surface_ || media_crypto); 1170 DCHECK(!codec_config->needs_protected_surface_ || media_crypto);
1162 1171
1163 const bool require_software_codec = !codec_config->allow_autodetection_; 1172 const bool require_software_codec = !codec_config->allow_autodetection_;
1164 1173
1165 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( 1174 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder(
1166 codec_config->codec_, codec_config->needs_protected_surface_, 1175 codec_config->codec_, codec_config->needs_protected_surface_,
1167 codec_config->initial_expected_coded_size_, 1176 codec_config->initial_expected_coded_size_,
1168 codec_config->surface_.j_surface().obj(), media_crypto, true, 1177 codec_config->surface_.j_surface().obj(), media_crypto, true,
1169 require_software_codec)); 1178 require_software_codec));
1170 1179
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; 1180 return codec;
1177 } 1181 }
1178 1182
1179 void AndroidVideoDecodeAccelerator::OnCodecConfigured( 1183 void AndroidVideoDecodeAccelerator::OnCodecConfigured(
1180 std::unique_ptr<VideoCodecBridge> media_codec) { 1184 std::unique_ptr<VideoCodecBridge> media_codec) {
1181 DCHECK(thread_checker_.CalledOnValidThread()); 1185 DCHECK(thread_checker_.CalledOnValidThread());
1182 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); 1186 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED);
1183 1187
1184 // Record one instance of the codec being initialized. 1188 // Record one instance of the codec being initialized.
1185 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); 1189 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 1680 // 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 1681 // thread, and it'll get freed if things start working. If things are
1678 // already working, then it'll be freed soon. 1682 // already working, then it'll be freed soon.
1679 // 1683 //
1680 // We require software codecs when |allow_autodetection_| is false, so use 1684 // 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 1685 // the stored value as a proxy for whether the MediaCodec is software backed
1682 // or not. 1686 // or not.
1683 if (!codec_config_->allow_autodetection_) { 1687 if (!codec_config_->allow_autodetection_) {
1684 media_codec_.reset(); 1688 media_codec_.reset();
1685 } else { 1689 } else {
1686 g_avda_manager.Get().StartUsingConstructionThread(); 1690 g_avda_manager.Get().ConstructionTaskRunner()->DeleteSoon(
1687 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 1691 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 } 1692 }
1694 } 1693 }
1695 1694
1696 // static 1695 // static
1697 bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy( 1696 bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy(
1698 const gpu::GpuPreferences& gpu_preferences) { 1697 const gpu::GpuPreferences& gpu_preferences) {
1699 return true; 1698 return true;
1700 } 1699 }
1701 1700
1702 // static 1701 // static
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1781 1780
1782 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() 1781 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden()
1783 const { 1782 const {
1784 // Prevent MediaCodec from using its internal software decoders when we have 1783 // Prevent MediaCodec from using its internal software decoders when we have
1785 // more secure and up to date versions in the renderer process. 1784 // more secure and up to date versions in the renderer process.
1786 return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 || 1785 return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 ||
1787 codec_config_->codec_ == media::kCodecVP9); 1786 codec_config_->codec_ == media::kCodecVP9);
1788 } 1787 }
1789 1788
1790 } // namespace media 1789 } // 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