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