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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
242 io_timer_.Stop(); | 242 io_timer_.Stop(); |
243 } | 243 } |
244 | 244 |
245 // Eventually, we should run the timer on this thread. For now, we just keep | 245 // Eventually, we should run the timer on this thread. For now, we just keep |
246 // it as a convenience for construction. | 246 // it as a convenience for construction. |
247 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { | 247 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { |
248 DCHECK(thread_checker_.CalledOnValidThread()); | 248 DCHECK(thread_checker_.CalledOnValidThread()); |
249 return construction_thread_.task_runner(); | 249 return construction_thread_.task_runner(); |
250 } | 250 } |
251 | 251 |
252 // |owner| would like to use |surface_id|. If it is not busy, then mark it | |
watk
2016/05/18 20:38:18
No "owner" any more
liberato (no reviews please)
2016/05/18 21:13:13
Done.
| |
253 // as busy and return true. If it is busy, then replace any existing waiter, | |
254 // make |owner| the current waiter, and return false. Any existing waiter | |
255 // is assumed to be on the way out, so we fail its allocation request. | |
256 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { | |
257 SurfaceWaiterMap::iterator iter = surface_waiter_map_.find(surface_id); | |
258 | |
259 // Nobody has to wait for no surface. | |
DaleCurtis
2016/05/18 17:59:11
Move above find?
liberato (no reviews please)
2016/05/18 18:49:39
Done.
| |
260 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID) | |
261 return true; | |
262 | |
263 if (iter == surface_waiter_map_.end()) { | |
264 // SurfaceView isn't allocated. Succeed. | |
265 surface_waiter_map_[surface_id].owner = avda; | |
266 surface_waiter_map_[surface_id].waiter = nullptr; | |
267 return true; | |
268 } | |
269 | |
270 // SurfaceView is already allocated. | |
271 | |
272 if (iter->second.waiter != nullptr) { | |
DaleCurtis
2016/05/18 17:59:11
Can you explain this design choice? I.e. why would
liberato (no reviews please)
2016/05/18 18:49:39
because WMPI maintains at most one AVDA instance.
DaleCurtis
2016/05/18 18:55:49
Hmm, what about other WMPI instances?
liberato (no reviews please)
2016/05/18 19:51:18
|surface_id_| will not be the same if the surface
| |
273 // Some other AVDA is waiting. |avda| will replace it, so notify it | |
274 // that it will fail. | |
275 iter->second.waiter->OnSurfaceAvailable(false); | |
276 iter->second.waiter = nullptr; | |
277 } | |
278 | |
279 // |avda| is now waiting. | |
280 iter->second.waiter = avda; | |
281 return false; | |
282 } | |
283 | |
284 // Clear any waiting request for |surface_id| by |avda|. It is okay if | |
285 // |waiter| is not waiting and/or isn't the owner of |surface_id|. | |
286 void DeallocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { | |
287 SurfaceWaiterMap::iterator iter = surface_waiter_map_.find(surface_id); | |
288 if (iter == surface_waiter_map_.end()) | |
DaleCurtis
2016/05/18 17:59:11
Should this dcheck?
liberato (no reviews please)
2016/05/18 18:49:39
no. this way, one simply calls Deallocate uncondi
| |
289 return; | |
290 | |
291 // If |avda| was waiting, then remove it without OnSurfaceAvailable. | |
292 if (iter->second.waiter == avda) | |
293 iter->second.waiter = nullptr; | |
294 | |
295 // If |avda| is the owner, then let the next owner have it. | |
296 if (iter->second.owner == avda) { | |
DaleCurtis
2016/05/18 17:59:11
Use early returns instead.
liberato (no reviews please)
2016/05/18 18:49:39
Done.
| |
297 if (AndroidVideoDecodeAccelerator* waiter = iter->second.waiter) { | |
298 // Promote |waiter| to be the owner. | |
299 iter->second.owner = waiter; | |
300 iter->second.waiter = nullptr; | |
301 waiter->OnSurfaceAvailable(true); | |
302 } else { | |
303 // No waiter -- remove the record and return since |iter| is | |
304 // no longer valid. | |
305 surface_waiter_map_.erase(iter); | |
306 return; | |
307 } | |
308 } | |
309 } | |
310 | |
252 private: | 311 private: |
253 friend struct base::DefaultLazyInstanceTraits<AVDATimerManager>; | 312 friend struct base::DefaultLazyInstanceTraits<AVDATimerManager>; |
254 | 313 |
255 AVDATimerManager() : construction_thread_("AVDAThread") {} | 314 AVDATimerManager() : construction_thread_("AVDAThread") {} |
256 ~AVDATimerManager() { NOTREACHED(); } | 315 ~AVDATimerManager() { NOTREACHED(); } |
257 | 316 |
258 void RunTimer() { | 317 void RunTimer() { |
259 { | 318 { |
260 // Call out to all AVDA instances, some of which may attempt to remove | 319 // Call out to all AVDA instances, some of which may attempt to remove |
261 // themselves from the list during this operation; those removals will be | 320 // themselves from the list during this operation; those removals will be |
(...skipping 11 matching lines...) Expand all Loading... | |
273 // TODO(dalecurtis): We may want to consider chunking this if task execution | 332 // TODO(dalecurtis): We may want to consider chunking this if task execution |
274 // takes too long for the combined timer. | 333 // takes too long for the combined timer. |
275 } | 334 } |
276 | 335 |
277 // All AVDA instances that would like us to poll DoIOTask. | 336 // All AVDA instances that would like us to poll DoIOTask. |
278 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_; | 337 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_; |
279 | 338 |
280 // All AVDA instances that might like to use the construction thread. | 339 // All AVDA instances that might like to use the construction thread. |
281 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_; | 340 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_; |
282 | 341 |
342 // [surface id] = accelerator that owns the surface, or nullptr. | |
watk
2016/05/18 20:38:18
Comment seems out of date/wrong place
liberato (no reviews please)
2016/05/18 21:13:13
Done.
| |
343 struct OwnerRecord { | |
344 OwnerRecord() : owner(nullptr), waiter(nullptr) {} | |
DaleCurtis
2016/05/18 17:59:11
Constructor prevents this from being a POD type. I
liberato (no reviews please)
2016/05/18 18:49:39
hrm, i just tried brace-or-equal but that doesn't
DaleCurtis
2016/05/18 18:55:49
Dropping the constructor and not using = nullptr o
liberato (no reviews please)
2016/05/18 19:51:17
i switched to "= nullptr" in the most recent CL.
| |
345 AndroidVideoDecodeAccelerator* owner; | |
346 AndroidVideoDecodeAccelerator* waiter; | |
347 }; | |
348 using SurfaceWaiterMap = std::map<int, OwnerRecord>; | |
349 SurfaceWaiterMap surface_waiter_map_; | |
350 | |
283 // Since we can't delete while iterating when using a set, defer erasure until | 351 // Since we can't delete while iterating when using a set, defer erasure until |
284 // after iteration complete. | 352 // after iteration complete. |
285 bool timer_running_ = false; | 353 bool timer_running_ = false; |
286 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; | 354 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; |
287 | 355 |
288 // Repeating timer responsible for draining pending IO to the codecs. | 356 // Repeating timer responsible for draining pending IO to the codecs. |
289 base::RepeatingTimer io_timer_; | 357 base::RepeatingTimer io_timer_; |
290 | 358 |
291 base::Thread construction_thread_; | 359 base::Thread construction_thread_; |
292 | 360 |
(...skipping 18 matching lines...) Expand all Loading... | |
311 is_encrypted_(false), | 379 is_encrypted_(false), |
312 state_(NO_ERROR), | 380 state_(NO_ERROR), |
313 picturebuffers_requested_(false), | 381 picturebuffers_requested_(false), |
314 drain_type_(DRAIN_TYPE_NONE), | 382 drain_type_(DRAIN_TYPE_NONE), |
315 media_drm_bridge_cdm_context_(nullptr), | 383 media_drm_bridge_cdm_context_(nullptr), |
316 cdm_registration_id_(0), | 384 cdm_registration_id_(0), |
317 pending_input_buf_index_(-1), | 385 pending_input_buf_index_(-1), |
318 error_sequence_token_(0), | 386 error_sequence_token_(0), |
319 defer_errors_(false), | 387 defer_errors_(false), |
320 deferred_initialization_pending_(false), | 388 deferred_initialization_pending_(false), |
389 cdm_id_(0), | |
321 surface_id_(media::VideoDecodeAccelerator::Config::kNoSurfaceID), | 390 surface_id_(media::VideoDecodeAccelerator::Config::kNoSurfaceID), |
322 weak_this_factory_(this) {} | 391 weak_this_factory_(this) {} |
323 | 392 |
324 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 393 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
325 DCHECK(thread_checker_.CalledOnValidThread()); | 394 DCHECK(thread_checker_.CalledOnValidThread()); |
326 g_avda_timer.Pointer()->StopTimer(this); | 395 g_avda_timer.Pointer()->StopTimer(this); |
327 g_avda_timer.Pointer()->StopThread(this); | 396 g_avda_timer.Pointer()->StopThread(this); |
328 | 397 |
329 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 398 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
330 if (!media_drm_bridge_cdm_context_) | 399 if (!media_drm_bridge_cdm_context_) |
(...skipping 21 matching lines...) Expand all Loading... | |
352 return false; | 421 return false; |
353 } | 422 } |
354 | 423 |
355 DCHECK(client); | 424 DCHECK(client); |
356 client_ = client; | 425 client_ = client; |
357 codec_config_ = new CodecConfig(); | 426 codec_config_ = new CodecConfig(); |
358 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile); | 427 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile); |
359 codec_config_->initial_expected_coded_size_ = | 428 codec_config_->initial_expected_coded_size_ = |
360 config.initial_expected_coded_size; | 429 config.initial_expected_coded_size; |
361 is_encrypted_ = config.is_encrypted; | 430 is_encrypted_ = config.is_encrypted; |
431 cdm_id_ = config.cdm_id; | |
362 | 432 |
363 // We signalled that we support deferred initialization, so see if the client | 433 // We signalled that we support deferred initialization, so see if the client |
364 // does also. | 434 // does also. |
365 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; | 435 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; |
366 | 436 |
367 if (is_encrypted_ && !deferred_initialization_pending_) { | 437 if (is_encrypted_ && !deferred_initialization_pending_) { |
368 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams"; | 438 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams"; |
369 return false; | 439 return false; |
370 } | 440 } |
371 | 441 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; | 478 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; |
409 strategy_.reset(new AndroidCopyingBackingStrategy(this)); | 479 strategy_.reset(new AndroidCopyingBackingStrategy(this)); |
410 } | 480 } |
411 | 481 |
412 if (!make_context_current_cb_.Run()) { | 482 if (!make_context_current_cb_.Run()) { |
413 LOG(ERROR) << "Failed to make this decoder's GL context current."; | 483 LOG(ERROR) << "Failed to make this decoder's GL context current."; |
414 return false; | 484 return false; |
415 } | 485 } |
416 | 486 |
417 surface_id_ = config.surface_id; | 487 surface_id_ = config.surface_id; |
488 if (g_avda_timer.Pointer()->AllocateSurface(surface_id_, this)) { | |
489 // We have succesfully owned the surface, so finish initialization now. | |
490 return InitializeStrategy(); | |
491 } | |
492 | |
493 // We have to wait for some other AVDA instance to free up the surface. | |
494 // OnSurfaceAvailable will be called when it's available. | |
495 return true; | |
496 } | |
497 | |
498 void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) { | |
499 DCHECK(deferred_initialization_pending_); | |
500 | |
501 if (!success) { | |
502 // Surface isn't available and/or we're being destroyed. | |
503 NotifyInitializationComplete(false); | |
504 deferred_initialization_pending_ = false; | |
505 return; | |
506 } | |
507 | |
508 if (!InitializeStrategy()) { | |
watk
2016/05/18 20:38:18
Could merge this block into the above with a || if
liberato (no reviews please)
2016/05/18 21:13:13
Done.
| |
509 NotifyInitializationComplete(false); | |
510 deferred_initialization_pending_ = false; | |
511 } | |
512 } | |
513 | |
514 bool AndroidVideoDecodeAccelerator::InitializeStrategy() { | |
418 codec_config_->surface_ = strategy_->Initialize(surface_id_); | 515 codec_config_->surface_ = strategy_->Initialize(surface_id_); |
419 if (codec_config_->surface_.IsEmpty()) { | 516 if (codec_config_->surface_.IsEmpty()) { |
420 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " | 517 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " |
421 "Java surface is empty."; | 518 "Java surface is empty."; |
422 return false; | 519 return false; |
423 } | 520 } |
424 | 521 |
425 on_destroying_surface_cb_ = | 522 on_destroying_surface_cb_ = |
426 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface, | 523 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface, |
427 weak_this_factory_.GetWeakPtr()); | 524 weak_this_factory_.GetWeakPtr()); |
(...skipping 10 matching lines...) Expand all Loading... | |
438 | 535 |
439 // Start the thread for async configuration, even if we don't need it now. | 536 // Start the thread for async configuration, even if we don't need it now. |
440 // ResetCodecState might rebuild the codec later, for example. | 537 // ResetCodecState might rebuild the codec later, for example. |
441 if (!g_avda_timer.Pointer()->StartThread(this)) { | 538 if (!g_avda_timer.Pointer()->StartThread(this)) { |
442 LOG(ERROR) << "Failed to start AVDA thread"; | 539 LOG(ERROR) << "Failed to start AVDA thread"; |
443 return false; | 540 return false; |
444 } | 541 } |
445 | 542 |
446 // If we are encrypted, then we aren't able to create the codec yet. | 543 // If we are encrypted, then we aren't able to create the codec yet. |
447 if (is_encrypted_) { | 544 if (is_encrypted_) { |
448 InitializeCdm(config.cdm_id); | 545 InitializeCdm(); |
449 return true; | 546 return true; |
450 } | 547 } |
451 | 548 |
452 if (deferred_initialization_pending_) { | 549 if (deferred_initialization_pending_) { |
453 ConfigureMediaCodecAsynchronously(); | 550 ConfigureMediaCodecAsynchronously(); |
454 return true; | 551 return true; |
455 } | 552 } |
456 | 553 |
457 // If the client doesn't support deferred initialization (WebRTC), then we | 554 // If the client doesn't support deferred initialization (WebRTC), then we |
458 // should complete it now and return a meaningful result. | 555 // should complete it now and return a meaningful result. Note that it would |
556 // be nice if we didn't have to worry about starting codec configuration at | |
557 // all (::Initialize or the wrapper can do it), but then they have to remember | |
558 // not to start codec config if we have to wait for the cdm. It's somewhat | |
559 // clearer for us to handle both cases. | |
459 return ConfigureMediaCodecSynchronously(); | 560 return ConfigureMediaCodecSynchronously(); |
460 } | 561 } |
461 | 562 |
462 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { | 563 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { |
463 DCHECK(thread_checker_.CalledOnValidThread()); | 564 DCHECK(thread_checker_.CalledOnValidThread()); |
464 TRACE_EVENT0("media", "AVDA::DoIOTask"); | 565 TRACE_EVENT0("media", "AVDA::DoIOTask"); |
465 if (state_ == ERROR || state_ == WAITING_FOR_CODEC || | 566 if (state_ == ERROR || state_ == WAITING_FOR_CODEC || |
466 state_ == SURFACE_DESTROYED) { | 567 state_ == SURFACE_DESTROYED) { |
467 return; | 568 return; |
468 } | 569 } |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1197 | 1298 |
1198 void AndroidVideoDecodeAccelerator::ActualDestroy() { | 1299 void AndroidVideoDecodeAccelerator::ActualDestroy() { |
1199 DVLOG(1) << __FUNCTION__; | 1300 DVLOG(1) << __FUNCTION__; |
1200 DCHECK(thread_checker_.CalledOnValidThread()); | 1301 DCHECK(thread_checker_.CalledOnValidThread()); |
1201 | 1302 |
1202 if (!on_destroying_surface_cb_.is_null()) { | 1303 if (!on_destroying_surface_cb_.is_null()) { |
1203 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback( | 1304 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback( |
1204 on_destroying_surface_cb_); | 1305 on_destroying_surface_cb_); |
1205 } | 1306 } |
1206 | 1307 |
1308 // We no longer care about |surface_id_|, in case we did before. It's okay | |
1309 // if we have no surface and/or weren't the owner or a waiter. | |
1310 g_avda_timer.Pointer()->DeallocateSurface(surface_id_, this); | |
1311 | |
1207 // Note that async codec construction might still be in progress. In that | 1312 // Note that async codec construction might still be in progress. In that |
1208 // case, the codec will be deleted when it completes once we invalidate all | 1313 // case, the codec will be deleted when it completes once we invalidate all |
1209 // our weak refs. | 1314 // our weak refs. |
1210 weak_this_factory_.InvalidateWeakPtrs(); | 1315 weak_this_factory_.InvalidateWeakPtrs(); |
1211 if (media_codec_) { | 1316 if (media_codec_) { |
1212 g_avda_timer.Pointer()->StopTimer(this); | 1317 g_avda_timer.Pointer()->StopTimer(this); |
1213 media_codec_.reset(); | 1318 media_codec_.reset(); |
1214 } | 1319 } |
1215 delete this; | 1320 delete this; |
1216 } | 1321 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1289 const ::tracked_objects::Location& from_here, | 1394 const ::tracked_objects::Location& from_here, |
1290 media::VideoDecodeAccelerator::Error error) { | 1395 media::VideoDecodeAccelerator::Error error) { |
1291 base::MessageLoop::current()->PostDelayedTask( | 1396 base::MessageLoop::current()->PostDelayedTask( |
1292 from_here, | 1397 from_here, |
1293 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, | 1398 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, |
1294 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), | 1399 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), |
1295 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); | 1400 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); |
1296 state_ = ERROR; | 1401 state_ = ERROR; |
1297 } | 1402 } |
1298 | 1403 |
1299 void AndroidVideoDecodeAccelerator::InitializeCdm(int cdm_id) { | 1404 void AndroidVideoDecodeAccelerator::InitializeCdm() { |
1300 DVLOG(2) << __FUNCTION__ << ": " << cdm_id; | 1405 DVLOG(2) << __FUNCTION__ << ": " << cdm_id_; |
1301 | 1406 |
1302 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 1407 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
1303 NOTIMPLEMENTED(); | 1408 NOTIMPLEMENTED(); |
1304 NotifyInitializationComplete(false); | 1409 NotifyInitializationComplete(false); |
1305 #else | 1410 #else |
1306 // Store the CDM to hold a reference to it. | 1411 // Store the CDM to hold a reference to it. |
1307 cdm_for_reference_holding_only_ = media::MojoCdmService::LegacyGetCdm(cdm_id); | 1412 cdm_for_reference_holding_only_ = |
1413 media::MojoCdmService::LegacyGetCdm(cdm_id_); | |
1308 DCHECK(cdm_for_reference_holding_only_); | 1414 DCHECK(cdm_for_reference_holding_only_); |
1309 | 1415 |
1310 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext. | 1416 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext. |
1311 media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>( | 1417 media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>( |
1312 cdm_for_reference_holding_only_->GetCdmContext()); | 1418 cdm_for_reference_holding_only_->GetCdmContext()); |
1313 DCHECK(media_drm_bridge_cdm_context_); | 1419 DCHECK(media_drm_bridge_cdm_context_); |
1314 | 1420 |
1315 // Register CDM callbacks. The callbacks registered will be posted back to | 1421 // Register CDM callbacks. The callbacks registered will be posted back to |
1316 // this thread via BindToCurrentLoop. | 1422 // this thread via BindToCurrentLoop. |
1317 | 1423 |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1502 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { | 1608 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { |
1503 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: | 1609 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: |
1504 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1610 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
1505 } | 1611 } |
1506 } | 1612 } |
1507 | 1613 |
1508 return capabilities; | 1614 return capabilities; |
1509 } | 1615 } |
1510 | 1616 |
1511 } // namespace media | 1617 } // namespace media |
OLD | NEW |