Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |