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