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/base/android/media_source_player.h" | 5 #include "media/base/android/media_source_player.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
47 is_audio_encrypted_(false), | 47 is_audio_encrypted_(false), |
48 is_video_encrypted_(false), | 48 is_video_encrypted_(false), |
49 volume_(-1.0), | 49 volume_(-1.0), |
50 clock_(&default_tick_clock_), | 50 clock_(&default_tick_clock_), |
51 next_video_data_is_iframe_(true), | 51 next_video_data_is_iframe_(true), |
52 doing_browser_seek_(false), | 52 doing_browser_seek_(false), |
53 pending_seek_(false), | 53 pending_seek_(false), |
54 reconfig_audio_decoder_(false), | 54 reconfig_audio_decoder_(false), |
55 reconfig_video_decoder_(false), | 55 reconfig_video_decoder_(false), |
56 drm_bridge_(NULL), | 56 drm_bridge_(NULL), |
57 cdm_registration_id_(0), | |
57 is_waiting_for_key_(false), | 58 is_waiting_for_key_(false), |
58 has_pending_audio_data_request_(false), | 59 has_pending_audio_data_request_(false), |
59 has_pending_video_data_request_(false), | 60 has_pending_video_data_request_(false), |
60 weak_factory_(this) { | 61 weak_factory_(this) { |
61 demuxer_->Initialize(this); | 62 demuxer_->Initialize(this); |
62 clock_.SetMaxTime(base::TimeDelta()); | 63 clock_.SetMaxTime(base::TimeDelta()); |
64 weak_this_ = weak_factory_.GetWeakPtr(); | |
63 } | 65 } |
64 | 66 |
65 MediaSourcePlayer::~MediaSourcePlayer() { | 67 MediaSourcePlayer::~MediaSourcePlayer() { |
66 Release(); | 68 Release(); |
69 if (drm_bridge_) { | |
70 DCHECK_NE(cdm_registration_id_, 0); | |
ddorwin
2014/06/02 20:20:29
If you want a DCHECK, it's probably something like
xhwang
2014/06/02 21:41:22
Done.
| |
71 drm_bridge_->UnregisterPlayer(cdm_registration_id_); | |
72 cdm_registration_id_ = 0; | |
73 } | |
67 } | 74 } |
68 | 75 |
69 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { | 76 void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
70 // For an empty surface, always pass it to the decoder job so that it | 77 // For an empty surface, always pass it to the decoder job so that it |
71 // can detach from the current one. Otherwise, don't pass an unprotected | 78 // can detach from the current one. Otherwise, don't pass an unprotected |
72 // surface if the video content requires a protected one. | 79 // surface if the video content requires a protected one. |
73 if (!surface.IsEmpty() && | 80 if (!surface.IsEmpty() && |
74 IsProtectedSurfaceRequired() && !surface.is_protected()) { | 81 IsProtectedSurfaceRequired() && !surface.is_protected()) { |
75 return; | 82 return; |
76 } | 83 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
232 DVLOG(1) << __FUNCTION__ << " : Resuming seek or config change processing"; | 239 DVLOG(1) << __FUNCTION__ << " : Resuming seek or config change processing"; |
233 ProcessPendingEvents(); | 240 ProcessPendingEvents(); |
234 } | 241 } |
235 } | 242 } |
236 | 243 |
237 void MediaSourcePlayer::SetVolume(double volume) { | 244 void MediaSourcePlayer::SetVolume(double volume) { |
238 volume_ = volume; | 245 volume_ = volume; |
239 SetVolumeInternal(); | 246 SetVolumeInternal(); |
240 } | 247 } |
241 | 248 |
242 void MediaSourcePlayer::OnKeyAdded() { | |
243 DVLOG(1) << __FUNCTION__; | |
244 if (!is_waiting_for_key_) | |
245 return; | |
246 | |
247 is_waiting_for_key_ = false; | |
248 if (playing_) | |
249 StartInternal(); | |
250 } | |
251 | |
252 bool MediaSourcePlayer::IsSurfaceInUse() const { | 249 bool MediaSourcePlayer::IsSurfaceInUse() const { |
253 return is_surface_in_use_; | 250 return is_surface_in_use_; |
254 } | 251 } |
255 | 252 |
256 bool MediaSourcePlayer::CanPause() { | 253 bool MediaSourcePlayer::CanPause() { |
257 return Seekable(); | 254 return Seekable(); |
258 } | 255 } |
259 | 256 |
260 bool MediaSourcePlayer::CanSeekForward() { | 257 bool MediaSourcePlayer::CanSeekForward() { |
261 return Seekable(); | 258 return Seekable(); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 } | 345 } |
349 | 346 |
350 void MediaSourcePlayer::OnMediaCryptoReady() { | 347 void MediaSourcePlayer::OnMediaCryptoReady() { |
351 DCHECK(!drm_bridge_->GetMediaCrypto().is_null()); | 348 DCHECK(!drm_bridge_->GetMediaCrypto().is_null()); |
352 drm_bridge_->SetMediaCryptoReadyCB(base::Closure()); | 349 drm_bridge_->SetMediaCryptoReadyCB(base::Closure()); |
353 | 350 |
354 if (playing_) | 351 if (playing_) |
355 StartInternal(); | 352 StartInternal(); |
356 } | 353 } |
357 | 354 |
358 void MediaSourcePlayer::SetCdm(MediaKeys* cdm) { | 355 void MediaSourcePlayer::SetCdm(BrowserCdm* cdm) { |
359 // Currently we don't support DRM change during the middle of playback, even | 356 // Currently we don't support DRM change during the middle of playback, even |
360 // if the player is paused. | 357 // if the player is paused. |
361 // TODO(qinmin): support DRM change after playback has started. | 358 // TODO(qinmin): support DRM change after playback has started. |
362 // http://crbug.com/253792. | 359 // http://crbug.com/253792. |
363 if (GetCurrentTime() > base::TimeDelta()) { | 360 if (GetCurrentTime() > base::TimeDelta()) { |
364 VLOG(0) << "Setting DRM bridge after playback has started. " | 361 VLOG(0) << "Setting DRM bridge after playback has started. " |
365 << "This is not well supported!"; | 362 << "This is not well supported!"; |
366 } | 363 } |
367 | 364 |
365 if (drm_bridge_) { | |
366 NOTREACHED() << "Currently we do not support resetting CDM."; | |
367 return; | |
368 } | |
369 | |
368 // Only MediaDrmBridge will be set on MediaSourcePlayer. | 370 // Only MediaDrmBridge will be set on MediaSourcePlayer. |
369 drm_bridge_ = static_cast<MediaDrmBridge*>(cdm); | 371 drm_bridge_ = static_cast<MediaDrmBridge*>(cdm); |
370 | 372 |
373 cdm_registration_id_ = drm_bridge_->RegisterPlayer( | |
374 base::Bind(&MediaSourcePlayer::OnKeyAdded, weak_this_), | |
375 base::Bind(&MediaSourcePlayer::OnCdmUnset, weak_this_)); | |
376 | |
371 if (drm_bridge_->GetMediaCrypto().is_null()) { | 377 if (drm_bridge_->GetMediaCrypto().is_null()) { |
372 drm_bridge_->SetMediaCryptoReadyCB(base::Bind( | 378 drm_bridge_->SetMediaCryptoReadyCB( |
373 &MediaSourcePlayer::OnMediaCryptoReady, weak_factory_.GetWeakPtr())); | 379 base::Bind(&MediaSourcePlayer::OnMediaCryptoReady, weak_this_)); |
374 return; | 380 return; |
375 } | 381 } |
376 | 382 |
377 if (playing_) | 383 if (playing_) |
378 StartInternal(); | 384 StartInternal(); |
379 } | 385 } |
380 | 386 |
381 void MediaSourcePlayer::OnDemuxerSeekDone( | 387 void MediaSourcePlayer::OnDemuxerSeekDone( |
382 base::TimeDelta actual_browser_seek_time) { | 388 base::TimeDelta actual_browser_seek_time) { |
383 DVLOG(1) << __FUNCTION__; | 389 DVLOG(1) << __FUNCTION__; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
517 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); | 523 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); |
518 | 524 |
519 // It is possible that all streams have finished decode, yet starvation | 525 // It is possible that all streams have finished decode, yet starvation |
520 // occurred during the last stream's EOS decode. In this case, prefetch is a | 526 // occurred during the last stream's EOS decode. In this case, prefetch is a |
521 // no-op. | 527 // no-op. |
522 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 528 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
523 if (count == 0) | 529 if (count == 0) |
524 return; | 530 return; |
525 | 531 |
526 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); | 532 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); |
527 base::Closure barrier = | 533 base::Closure barrier = BarrierClosure( |
528 BarrierClosure(count, | 534 count, base::Bind(&MediaSourcePlayer::OnPrefetchDone, weak_this_)); |
529 base::Bind(&MediaSourcePlayer::OnPrefetchDone, | |
530 weak_factory_.GetWeakPtr())); | |
531 | 535 |
532 if (!AudioFinished()) | 536 if (!AudioFinished()) |
533 audio_decoder_job_->Prefetch(barrier); | 537 audio_decoder_job_->Prefetch(barrier); |
534 | 538 |
535 if (!VideoFinished()) | 539 if (!VideoFinished()) |
536 video_decoder_job_->Prefetch(barrier); | 540 video_decoder_job_->Prefetch(barrier); |
537 | 541 |
538 return; | 542 return; |
539 } | 543 } |
540 | 544 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
648 } | 652 } |
649 | 653 |
650 void MediaSourcePlayer::DecodeMoreAudio() { | 654 void MediaSourcePlayer::DecodeMoreAudio() { |
651 DVLOG(1) << __FUNCTION__; | 655 DVLOG(1) << __FUNCTION__; |
652 DCHECK(!audio_decoder_job_->is_decoding()); | 656 DCHECK(!audio_decoder_job_->is_decoding()); |
653 DCHECK(!AudioFinished()); | 657 DCHECK(!AudioFinished()); |
654 | 658 |
655 scoped_ptr<DemuxerConfigs> configs(audio_decoder_job_->Decode( | 659 scoped_ptr<DemuxerConfigs> configs(audio_decoder_job_->Decode( |
656 start_time_ticks_, | 660 start_time_ticks_, |
657 start_presentation_timestamp_, | 661 start_presentation_timestamp_, |
658 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, | 662 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, weak_this_, true))); |
659 weak_factory_.GetWeakPtr(), | |
660 true))); | |
661 if (!configs) { | 663 if (!configs) { |
662 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", | 664 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", |
663 audio_decoder_job_.get()); | 665 audio_decoder_job_.get()); |
664 return; | 666 return; |
665 } | 667 } |
666 | 668 |
667 // Failed to start the next decode. | 669 // Failed to start the next decode. |
668 DCHECK(!reconfig_audio_decoder_); | 670 DCHECK(!reconfig_audio_decoder_); |
669 reconfig_audio_decoder_ = true; | 671 reconfig_audio_decoder_ = true; |
670 SetDemuxerConfigs(*configs, true); | 672 SetDemuxerConfigs(*configs, true); |
671 | 673 |
672 // Config change may have just been detected on the other stream. If so, | 674 // Config change may have just been detected on the other stream. If so, |
673 // don't send a duplicate demuxer config request. | 675 // don't send a duplicate demuxer config request. |
674 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 676 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
675 DCHECK(reconfig_video_decoder_); | 677 DCHECK(reconfig_video_decoder_); |
676 return; | 678 return; |
677 } | 679 } |
678 | 680 |
679 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | 681 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); |
680 } | 682 } |
681 | 683 |
682 void MediaSourcePlayer::DecodeMoreVideo() { | 684 void MediaSourcePlayer::DecodeMoreVideo() { |
683 DVLOG(1) << __FUNCTION__; | 685 DVLOG(1) << __FUNCTION__; |
684 DCHECK(!video_decoder_job_->is_decoding()); | 686 DCHECK(!video_decoder_job_->is_decoding()); |
685 DCHECK(!VideoFinished()); | 687 DCHECK(!VideoFinished()); |
686 | 688 |
687 scoped_ptr<DemuxerConfigs> configs(video_decoder_job_->Decode( | 689 scoped_ptr<DemuxerConfigs> configs(video_decoder_job_->Decode( |
688 start_time_ticks_, | 690 start_time_ticks_, |
689 start_presentation_timestamp_, | 691 start_presentation_timestamp_, |
690 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, | 692 base::Bind(&MediaSourcePlayer::MediaDecoderCallback, weak_this_, false))); |
691 weak_factory_.GetWeakPtr(), | |
692 false))); | |
693 if (!configs) { | 693 if (!configs) { |
694 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", | 694 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", |
695 video_decoder_job_.get()); | 695 video_decoder_job_.get()); |
696 return; | 696 return; |
697 } | 697 } |
698 | 698 |
699 // Failed to start the next decode. | 699 // Failed to start the next decode. |
700 // After this detection of video config change, next video data received | 700 // After this detection of video config change, next video data received |
701 // will begin with I-frame. | 701 // will begin with I-frame. |
702 next_video_data_is_iframe_ = true; | 702 next_video_data_is_iframe_ = true; |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
907 // For video only streams, fps can be estimated from the difference | 907 // For video only streams, fps can be estimated from the difference |
908 // between the previous and current presentation timestamps. The | 908 // between the previous and current presentation timestamps. The |
909 // previous presentation timestamp is equal to current_timestamp. | 909 // previous presentation timestamp is equal to current_timestamp. |
910 // TODO(qinmin): determine whether 2 is a good coefficient for estimating | 910 // TODO(qinmin): determine whether 2 is a good coefficient for estimating |
911 // video frame timeout. | 911 // video frame timeout. |
912 timeout = 2 * (current_presentation_timestamp - current_timestamp); | 912 timeout = 2 * (current_presentation_timestamp - current_timestamp); |
913 } | 913 } |
914 | 914 |
915 timeout = std::max(timeout, kMinStarvationTimeout); | 915 timeout = std::max(timeout, kMinStarvationTimeout); |
916 | 916 |
917 decoder_starvation_callback_.Reset(base::Bind( | 917 decoder_starvation_callback_.Reset( |
918 &MediaSourcePlayer::OnDecoderStarved, weak_factory_.GetWeakPtr())); | 918 base::Bind(&MediaSourcePlayer::OnDecoderStarved, weak_this_)); |
919 base::MessageLoop::current()->PostDelayedTask( | 919 base::MessageLoop::current()->PostDelayedTask( |
920 FROM_HERE, decoder_starvation_callback_.callback(), timeout); | 920 FROM_HERE, decoder_starvation_callback_.callback(), timeout); |
921 } | 921 } |
922 | 922 |
923 void MediaSourcePlayer::SetVolumeInternal() { | 923 void MediaSourcePlayer::SetVolumeInternal() { |
924 if (audio_decoder_job_ && volume_ >= 0) | 924 if (audio_decoder_job_ && volume_ >= 0) |
925 audio_decoder_job_->SetVolume(volume_); | 925 audio_decoder_job_->SetVolume(volume_); |
926 } | 926 } |
927 | 927 |
928 bool MediaSourcePlayer::IsProtectedSurfaceRequired() { | 928 bool MediaSourcePlayer::IsProtectedSurfaceRequired() { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1015 is_audio_encrypted_ = configs.is_audio_encrypted; | 1015 is_audio_encrypted_ = configs.is_audio_encrypted; |
1016 audio_extra_data_ = configs.audio_extra_data; | 1016 audio_extra_data_ = configs.audio_extra_data; |
1017 } else { | 1017 } else { |
1018 video_codec_ = configs.video_codec; | 1018 video_codec_ = configs.video_codec; |
1019 width_ = configs.video_size.width(); | 1019 width_ = configs.video_size.width(); |
1020 height_ = configs.video_size.height(); | 1020 height_ = configs.video_size.height(); |
1021 is_video_encrypted_ = configs.is_video_encrypted; | 1021 is_video_encrypted_ = configs.is_video_encrypted; |
1022 } | 1022 } |
1023 } | 1023 } |
1024 | 1024 |
1025 void MediaSourcePlayer::OnKeyAdded() { | |
1026 DVLOG(1) << __FUNCTION__; | |
1027 if (!is_waiting_for_key_) | |
1028 return; | |
1029 | |
1030 is_waiting_for_key_ = false; | |
1031 if (playing_) | |
1032 StartInternal(); | |
1033 } | |
1034 | |
1035 void MediaSourcePlayer::OnCdmUnset() { | |
1036 DVLOG(1) << __FUNCTION__; | |
1037 DCHECK(drm_bridge_); | |
1038 // TODO(xhwang): Support detachment of CDM. | |
1039 DVLOG(1) << "CDM detachment not supported."; | |
1040 } | |
1041 | |
1025 } // namespace media | 1042 } // namespace media |
OLD | NEW |