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