Chromium Code Reviews| 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) { |
| 414 RUN_ON_MEDIA_THREAD(SetCdm, cdm); | 415 RUN_ON_MEDIA_THREAD(SetCdm, cdm); |
| 416 DCHECK(cdm); | |
|
jrummell
2015/10/29 21:05:17
Should this DCHECK() be first to fail the caller r
xhwang
2015/10/30 16:20:59
Done.
| |
| 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 // No need to set |cdm_unset_cb| since |this| holds a reference to the |cdm_|. |
|
Tima Vaisburd
2015/10/29 01:17:53
Please explain that the second callback will never
xhwang
2015/10/29 03:12:31
I'll update this comment when I address other comm
xhwang
2015/10/30 16:20:59
Done.
| |
| 441 base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_)); | 442 cdm_registration_id_ = drm_bridge->RegisterPlayer( |
| 443 BindToCurrentLoop( | |
| 444 base::Bind(&MediaCodecPlayer::OnKeyAdded, media_weak_this_)), | |
| 445 base::Bind(&base::DoNothing)); | |
| 442 | 446 |
| 443 // Post back to MediaDrmBridge's default thread. | 447 drm_bridge->SetMediaCryptoReadyCB(BindToCurrentLoop( |
| 444 ui_task_runner_->PostTask(FROM_HERE, | 448 base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_))); |
| 445 base::Bind(&MediaDrmBridge::SetMediaCryptoReadyCB, | |
| 446 drm_bridge_->WeakPtr(), cb)); | |
| 447 } | 449 } |
| 448 | 450 |
| 449 // Callbacks from Demuxer. | 451 // Callbacks from Demuxer. |
| 450 | 452 |
| 451 void MediaCodecPlayer::OnDemuxerConfigsAvailable( | 453 void MediaCodecPlayer::OnDemuxerConfigsAvailable( |
| 452 const DemuxerConfigs& configs) { | 454 const DemuxerConfigs& configs) { |
| 453 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 455 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 454 | 456 |
| 455 DVLOG(1) << __FUNCTION__; | 457 DVLOG(1) << __FUNCTION__; |
| 456 | 458 |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 958 DVLOG(1) << __FUNCTION__; | 960 DVLOG(1) << __FUNCTION__; |
| 959 | 961 |
| 960 key_is_added_ = true; | 962 key_is_added_ = true; |
| 961 | 963 |
| 962 if (state_ == kStateWaitingForKey) { | 964 if (state_ == kStateWaitingForKey) { |
| 963 SetState(kStatePlaying); | 965 SetState(kStatePlaying); |
| 964 StartPlaybackOrBrowserSeek(); | 966 StartPlaybackOrBrowserSeek(); |
| 965 } | 967 } |
| 966 } | 968 } |
| 967 | 969 |
| 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 | 970 // State machine operations, called on Media thread |
| 994 | 971 |
| 995 void MediaCodecPlayer::SetState(PlayerState new_state) { | 972 void MediaCodecPlayer::SetState(PlayerState new_state) { |
| 996 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 973 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 997 | 974 |
| 998 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); | 975 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); |
| 999 state_ = new_state; | 976 state_ = new_state; |
| 1000 } | 977 } |
| 1001 | 978 |
| 1002 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { | 979 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1417 RETURN_STRING(kStateWaitingForMediaCrypto); | 1394 RETURN_STRING(kStateWaitingForMediaCrypto); |
| 1418 RETURN_STRING(kStateWaitingForSeek); | 1395 RETURN_STRING(kStateWaitingForSeek); |
| 1419 RETURN_STRING(kStateError); | 1396 RETURN_STRING(kStateError); |
| 1420 } | 1397 } |
| 1421 return nullptr; // crash early | 1398 return nullptr; // crash early |
| 1422 } | 1399 } |
| 1423 | 1400 |
| 1424 #undef RETURN_STRING | 1401 #undef RETURN_STRING |
| 1425 | 1402 |
| 1426 } // namespace media | 1403 } // namespace media |
| OLD | NEW |