OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/base/android/media_codec_player.h" | 5 #include "media/base/android/media_codec_player.h" |
6 | 6 |
7 #include "base/barrier_closure.h" | 7 #include "base/barrier_closure.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/bind_helpers.h" |
9 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
10 #include "base/logging.h" | 11 #include "base/logging.h" |
11 #include "base/thread_task_runner_handle.h" | 12 #include "base/thread_task_runner_handle.h" |
12 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
13 #include "media/base/android/media_codec_audio_decoder.h" | 14 #include "media/base/android/media_codec_audio_decoder.h" |
14 #include "media/base/android/media_codec_video_decoder.h" | 15 #include "media/base/android/media_codec_video_decoder.h" |
15 #include "media/base/android/media_drm_bridge.h" | 16 #include "media/base/android/media_drm_bridge.h" |
16 #include "media/base/android/media_player_manager.h" | 17 #include "media/base/android/media_player_manager.h" |
17 #include "media/base/android/media_task_runner.h" | 18 #include "media/base/android/media_task_runner.h" |
18 #include "media/base/bind_to_current_loop.h" | 19 #include "media/base/bind_to_current_loop.h" |
(...skipping 23 matching lines...) Expand all Loading... |
42 : MediaPlayerAndroid(player_id, | 43 : MediaPlayerAndroid(player_id, |
43 manager.get(), | 44 manager.get(), |
44 on_decoder_resources_released_cb, | 45 on_decoder_resources_released_cb, |
45 frame_url), | 46 frame_url), |
46 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 47 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
47 demuxer_(demuxer.Pass()), | 48 demuxer_(demuxer.Pass()), |
48 state_(kStatePaused), | 49 state_(kStatePaused), |
49 interpolator_(&default_tick_clock_), | 50 interpolator_(&default_tick_clock_), |
50 pending_start_(false), | 51 pending_start_(false), |
51 pending_seek_(kNoTimestamp()), | 52 pending_seek_(kNoTimestamp()), |
52 drm_bridge_(nullptr), | |
53 cdm_registration_id_(0), | 53 cdm_registration_id_(0), |
54 key_is_required_(false), | 54 key_is_required_(false), |
55 key_is_added_(false), | 55 key_is_added_(false), |
56 media_weak_factory_(this) { | 56 media_weak_factory_(this) { |
57 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 57 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
58 | 58 |
59 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; | 59 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; |
60 | 60 |
61 completion_cb_ = | 61 completion_cb_ = |
62 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); | 62 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); |
(...skipping 29 matching lines...) Expand all Loading... |
92 // Release the codecs here, before any member variable is destroyed to make | 92 // Release the codecs here, before any member variable is destroyed to make |
93 // the unit tests happy. | 93 // the unit tests happy. |
94 | 94 |
95 if (video_decoder_) | 95 if (video_decoder_) |
96 video_decoder_->ReleaseDecoderResources(); | 96 video_decoder_->ReleaseDecoderResources(); |
97 if (audio_decoder_) | 97 if (audio_decoder_) |
98 audio_decoder_->ReleaseDecoderResources(); | 98 audio_decoder_->ReleaseDecoderResources(); |
99 | 99 |
100 media_stat_->StopAndReport(GetInterpolatedTime()); | 100 media_stat_->StopAndReport(GetInterpolatedTime()); |
101 | 101 |
102 if (drm_bridge_) { | 102 if (cdm_) { |
103 DCHECK(cdm_registration_id_); | 103 DCHECK(cdm_registration_id_); |
104 drm_bridge_->UnregisterPlayer(cdm_registration_id_); | 104 static_cast<MediaDrmBridge*>(cdm_.get()) |
| 105 ->UnregisterPlayer(cdm_registration_id_); |
105 } | 106 } |
106 } | 107 } |
107 | 108 |
108 void MediaCodecPlayer::Initialize() { | 109 void MediaCodecPlayer::Initialize() { |
109 DVLOG(1) << __FUNCTION__; | 110 DVLOG(1) << __FUNCTION__; |
110 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 111 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
111 | 112 |
112 interpolator_.SetUpperBound(base::TimeDelta()); | 113 interpolator_.SetUpperBound(base::TimeDelta()); |
113 | 114 |
114 CreateDecoders(); | 115 CreateDecoders(); |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 return false; | 404 return false; |
404 } | 405 } |
405 | 406 |
406 bool MediaCodecPlayer::IsPlayerReady() { | 407 bool MediaCodecPlayer::IsPlayerReady() { |
407 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 408 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
408 // This method is called to check whether it's safe to release the player when | 409 // This method is called to check whether it's safe to release the player when |
409 // the OS needs more resources. This class can be released at any time. | 410 // the OS needs more resources. This class can be released at any time. |
410 return true; | 411 return true; |
411 } | 412 } |
412 | 413 |
413 void MediaCodecPlayer::SetCdm(BrowserCdm* cdm) { | 414 void MediaCodecPlayer::SetCdm(const scoped_refptr<MediaKeys>& cdm) { |
| 415 DCHECK(cdm); |
414 RUN_ON_MEDIA_THREAD(SetCdm, cdm); | 416 RUN_ON_MEDIA_THREAD(SetCdm, cdm); |
415 | 417 |
416 DVLOG(1) << __FUNCTION__; | 418 DVLOG(1) << __FUNCTION__; |
417 | 419 |
418 // Currently we don't support DRM change during the middle of playback, even | 420 // Currently we don't support DRM change during the middle of playback, even |
419 // if the player is paused. There is no current plan to support it, see | 421 // if the player is paused. There is no current plan to support it, see |
420 // http://crbug.com/253792. | 422 // http://crbug.com/253792. |
421 if (state_ != kStatePaused || GetInterpolatedTime() > base::TimeDelta()) { | 423 if (state_ != kStatePaused || GetInterpolatedTime() > base::TimeDelta()) { |
422 VLOG(0) << "Setting DRM bridge after playback has started is not supported"; | 424 VLOG(0) << "Setting DRM bridge after playback has started is not supported"; |
423 return; | 425 return; |
424 } | 426 } |
425 | 427 |
426 if (drm_bridge_) { | 428 if (cdm_) { |
427 NOTREACHED() << "Currently we do not support resetting CDM."; | 429 NOTREACHED() << "Currently we do not support resetting CDM."; |
428 return; | 430 return; |
429 } | 431 } |
430 | 432 |
431 DCHECK(cdm); | 433 cdm_ = cdm; |
432 drm_bridge_ = static_cast<MediaDrmBridge*>(cdm); | |
433 | 434 |
434 DCHECK(drm_bridge_); | 435 // Only MediaDrmBridge will be set on MediaCodecPlayer. |
| 436 MediaDrmBridge* drm_bridge = static_cast<MediaDrmBridge*>(cdm_.get()); |
435 | 437 |
436 cdm_registration_id_ = drm_bridge_->RegisterPlayer( | 438 // Register CDM callbacks. The callbacks registered will be posted back to the |
437 base::Bind(&MediaCodecPlayer::OnKeyAdded, media_weak_this_), | 439 // media thread via BindToCurrentLoop. |
438 base::Bind(&MediaCodecPlayer::OnCdmUnset, media_weak_this_)); | |
439 | 440 |
440 MediaDrmBridge::MediaCryptoReadyCB cb = BindToCurrentLoop( | 441 // Since |this| holds a reference to the |cdm_|, by the time the CDM is |
441 base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_)); | 442 // destructed, UnregisterPlayer() must have been called and |this| has been |
| 443 // destructed as well. So the |cdm_unset_cb| will never have a chance to be |
| 444 // called. |
| 445 // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms. |
| 446 cdm_registration_id_ = drm_bridge->RegisterPlayer( |
| 447 BindToCurrentLoop( |
| 448 base::Bind(&MediaCodecPlayer::OnKeyAdded, media_weak_this_)), |
| 449 base::Bind(&base::DoNothing)); |
442 | 450 |
443 // Post back to MediaDrmBridge's default thread. | 451 drm_bridge->SetMediaCryptoReadyCB(BindToCurrentLoop( |
444 ui_task_runner_->PostTask(FROM_HERE, | 452 base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_))); |
445 base::Bind(&MediaDrmBridge::SetMediaCryptoReadyCB, | |
446 drm_bridge_->WeakPtr(), cb)); | |
447 } | 453 } |
448 | 454 |
449 // Callbacks from Demuxer. | 455 // Callbacks from Demuxer. |
450 | 456 |
451 void MediaCodecPlayer::OnDemuxerConfigsAvailable( | 457 void MediaCodecPlayer::OnDemuxerConfigsAvailable( |
452 const DemuxerConfigs& configs) { | 458 const DemuxerConfigs& configs) { |
453 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 459 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
454 | 460 |
455 DVLOG(1) << __FUNCTION__; | 461 DVLOG(1) << __FUNCTION__; |
456 | 462 |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 DVLOG(1) << __FUNCTION__; | 964 DVLOG(1) << __FUNCTION__; |
959 | 965 |
960 key_is_added_ = true; | 966 key_is_added_ = true; |
961 | 967 |
962 if (state_ == kStateWaitingForKey) { | 968 if (state_ == kStateWaitingForKey) { |
963 SetState(kStatePlaying); | 969 SetState(kStatePlaying); |
964 StartPlaybackOrBrowserSeek(); | 970 StartPlaybackOrBrowserSeek(); |
965 } | 971 } |
966 } | 972 } |
967 | 973 |
968 void MediaCodecPlayer::OnCdmUnset() { | |
969 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | |
970 DVLOG(1) << __FUNCTION__; | |
971 | |
972 // This comment is copied from MediaSourcePlayer::OnCdmUnset(). | |
973 // TODO(xhwang): Currently this is only called during teardown. Support full | |
974 // detachment of CDM during playback. This will be needed when we start to | |
975 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release | |
976 // MediaDrm when the video is paused, or when the device goes to sleep (see | |
977 // http://crbug.com/272421). | |
978 | |
979 if (audio_decoder_) { | |
980 audio_decoder_->SetNeedsReconfigure(); | |
981 } | |
982 | |
983 if (video_decoder_) { | |
984 video_decoder_->SetProtectedSurfaceRequired(false); | |
985 video_decoder_->SetNeedsReconfigure(); | |
986 } | |
987 | |
988 cdm_registration_id_ = 0; | |
989 drm_bridge_ = nullptr; | |
990 media_crypto_.reset(); | |
991 } | |
992 | |
993 // State machine operations, called on Media thread | 974 // State machine operations, called on Media thread |
994 | 975 |
995 void MediaCodecPlayer::SetState(PlayerState new_state) { | 976 void MediaCodecPlayer::SetState(PlayerState new_state) { |
996 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 977 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
997 | 978 |
998 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); | 979 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); |
999 state_ = new_state; | 980 state_ = new_state; |
1000 } | 981 } |
1001 | 982 |
1002 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { | 983 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 RETURN_STRING(kStateWaitingForMediaCrypto); | 1398 RETURN_STRING(kStateWaitingForMediaCrypto); |
1418 RETURN_STRING(kStateWaitingForSeek); | 1399 RETURN_STRING(kStateWaitingForSeek); |
1419 RETURN_STRING(kStateError); | 1400 RETURN_STRING(kStateError); |
1420 } | 1401 } |
1421 return nullptr; // crash early | 1402 return nullptr; // crash early |
1422 } | 1403 } |
1423 | 1404 |
1424 #undef RETURN_STRING | 1405 #undef RETURN_STRING |
1425 | 1406 |
1426 } // namespace media | 1407 } // namespace media |
OLD | NEW |