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" |
11 #include "base/barrier_closure.h" | 11 #include "base/barrier_closure.h" |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/callback_helpers.h" | 14 #include "base/callback_helpers.h" |
15 #include "base/debug/trace_event.h" | 15 #include "base/debug/trace_event.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "media/base/android/audio_decoder_job.h" | 18 #include "media/base/android/audio_decoder_job.h" |
19 #include "media/base/android/media_drm_bridge.h" | 19 #include "media/base/android/media_drm_bridge.h" |
20 #include "media/base/android/media_player_manager.h" | 20 #include "media/base/android/media_player_manager.h" |
21 #include "media/base/android/video_decoder_job.h" | 21 #include "media/base/android/video_decoder_job.h" |
22 | 22 |
23 | |
24 namespace media { | 23 namespace media { |
25 | 24 |
26 MediaSourcePlayer::MediaSourcePlayer( | 25 MediaSourcePlayer::MediaSourcePlayer( |
27 int player_id, | 26 int player_id, |
28 MediaPlayerManager* manager, | 27 MediaPlayerManager* manager, |
29 const RequestMediaResourcesCB& request_media_resources_cb, | 28 const RequestMediaResourcesCB& request_media_resources_cb, |
30 scoped_ptr<DemuxerAndroid> demuxer, | 29 scoped_ptr<DemuxerAndroid> demuxer, |
31 const GURL& frame_url) | 30 const GURL& frame_url) |
32 : MediaPlayerAndroid(player_id, | 31 : MediaPlayerAndroid(player_id, |
33 manager, | 32 manager, |
34 request_media_resources_cb, | 33 request_media_resources_cb, |
35 frame_url), | 34 frame_url), |
36 demuxer_(demuxer.Pass()), | 35 demuxer_(demuxer.Pass()), |
37 pending_event_(NO_EVENT_PENDING), | 36 pending_event_(NO_EVENT_PENDING), |
38 playing_(false), | 37 playing_(false), |
39 interpolator_(&default_tick_clock_), | 38 interpolator_(&default_tick_clock_), |
40 doing_browser_seek_(false), | 39 doing_browser_seek_(false), |
41 pending_seek_(false), | 40 pending_seek_(false), |
42 drm_bridge_(NULL), | 41 drm_bridge_(NULL), |
43 cdm_registration_id_(0), | 42 cdm_registration_id_(0), |
44 is_waiting_for_key_(false), | 43 is_waiting_for_key_(false), |
| 44 key_added_while_decode_pending_(false), |
45 is_waiting_for_audio_decoder_(false), | 45 is_waiting_for_audio_decoder_(false), |
46 is_waiting_for_video_decoder_(false), | 46 is_waiting_for_video_decoder_(false), |
47 prerolling_(true), | 47 prerolling_(true), |
48 weak_factory_(this) { | 48 weak_factory_(this) { |
49 audio_decoder_job_.reset(new AudioDecoderJob( | 49 audio_decoder_job_.reset(new AudioDecoderJob( |
50 base::Bind(&DemuxerAndroid::RequestDemuxerData, | 50 base::Bind(&DemuxerAndroid::RequestDemuxerData, |
51 base::Unretained(demuxer_.get()), | 51 base::Unretained(demuxer_.get()), |
52 DemuxerStream::AUDIO), | 52 DemuxerStream::AUDIO), |
53 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, | 53 base::Bind(&MediaSourcePlayer::OnDemuxerConfigsChanged, |
54 weak_factory_.GetWeakPtr()))); | 54 weak_factory_.GetWeakPtr()))); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 bool MediaSourcePlayer::IsPlayerReady() { | 216 bool MediaSourcePlayer::IsPlayerReady() { |
217 return audio_decoder_job_ || video_decoder_job_; | 217 return audio_decoder_job_ || video_decoder_job_; |
218 } | 218 } |
219 | 219 |
220 void MediaSourcePlayer::StartInternal() { | 220 void MediaSourcePlayer::StartInternal() { |
221 DVLOG(1) << __FUNCTION__; | 221 DVLOG(1) << __FUNCTION__; |
222 // If there are pending events, wait for them finish. | 222 // If there are pending events, wait for them finish. |
223 if (pending_event_ != NO_EVENT_PENDING) | 223 if (pending_event_ != NO_EVENT_PENDING) |
224 return; | 224 return; |
225 | 225 |
226 // When we start, we'll have new demuxed data coming in. This new data could | 226 // When we start, we could have new demuxed data coming in. This new data |
227 // be clear (not encrypted) or encrypted with different keys. So | 227 // could be clear (not encrypted) or encrypted with different keys. So key |
228 // |is_waiting_for_key_| condition may not be true anymore. | 228 // related info should all be cleared. |
229 is_waiting_for_key_ = false; | 229 is_waiting_for_key_ = false; |
| 230 key_added_while_decode_pending_ = false; |
230 AttachListener(NULL); | 231 AttachListener(NULL); |
231 | 232 |
232 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 233 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
233 ProcessPendingEvents(); | 234 ProcessPendingEvents(); |
234 } | 235 } |
235 | 236 |
236 void MediaSourcePlayer::OnDemuxerConfigsAvailable( | 237 void MediaSourcePlayer::OnDemuxerConfigsAvailable( |
237 const DemuxerConfigs& configs) { | 238 const DemuxerConfigs& configs) { |
238 DVLOG(1) << __FUNCTION__; | 239 DVLOG(1) << __FUNCTION__; |
239 DCHECK(!HasAudio() && !HasVideo()); | 240 DCHECK(!HasAudio() && !HasVideo()); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) | 496 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
496 return; | 497 return; |
497 | 498 |
498 if (!playing_) { | 499 if (!playing_) { |
499 if (is_clock_manager) | 500 if (is_clock_manager) |
500 interpolator_.StopInterpolating(); | 501 interpolator_.StopInterpolating(); |
501 return; | 502 return; |
502 } | 503 } |
503 | 504 |
504 if (status == MEDIA_CODEC_NO_KEY) { | 505 if (status == MEDIA_CODEC_NO_KEY) { |
505 is_waiting_for_key_ = true; | 506 if (key_added_while_decode_pending_) { |
| 507 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; |
| 508 ResumePlaybackAfterKeyAdded(); |
| 509 } else { |
| 510 is_waiting_for_key_ = true; |
| 511 } |
506 return; | 512 return; |
507 } | 513 } |
508 | 514 |
| 515 // If |key_added_while_decode_pending_| is true and both audio and video |
| 516 // decoding succeeded, we should clear |key_added_while_decode_pending_| here. |
| 517 // But that would add more complexity into this function. If we don't clear it |
| 518 // here, the worst case would be we call ResumePlaybackAfterKeyAdded() when |
| 519 // we don't really have a new key. This should rarely happen and the |
| 520 // performance impact should be pretty small. |
| 521 // TODO(qinmin/xhwang): This class is complicated because we handle both audio |
| 522 // and video in one file. If we separate them, we should be able to remove a |
| 523 // lot of duplication. |
| 524 |
509 // If the status is MEDIA_CODEC_STOPPED, stop decoding new data. The player is | 525 // If the status is MEDIA_CODEC_STOPPED, stop decoding new data. The player is |
510 // in the middle of a seek or stop event and needs to wait for the IPCs to | 526 // in the middle of a seek or stop event and needs to wait for the IPCs to |
511 // come. | 527 // come. |
512 if (status == MEDIA_CODEC_STOPPED) | 528 if (status == MEDIA_CODEC_STOPPED) |
513 return; | 529 return; |
514 | 530 |
515 if (prerolling_ && IsPrerollFinished(is_audio)) { | 531 if (prerolling_ && IsPrerollFinished(is_audio)) { |
516 if (IsPrerollFinished(!is_audio)) { | 532 if (IsPrerollFinished(!is_audio)) { |
517 prerolling_ = false; | 533 prerolling_ = false; |
518 StartInternal(); | 534 StartInternal(); |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 if (audio) | 764 if (audio) |
749 is_waiting_for_audio_decoder_ = false; | 765 is_waiting_for_audio_decoder_ = false; |
750 if (video) | 766 if (video) |
751 is_waiting_for_video_decoder_ = false; | 767 is_waiting_for_video_decoder_ = false; |
752 if (IsEventPending(DECODER_CREATION_EVENT_PENDING)) | 768 if (IsEventPending(DECODER_CREATION_EVENT_PENDING)) |
753 ProcessPendingEvents(); | 769 ProcessPendingEvents(); |
754 } | 770 } |
755 | 771 |
756 void MediaSourcePlayer::OnKeyAdded() { | 772 void MediaSourcePlayer::OnKeyAdded() { |
757 DVLOG(1) << __FUNCTION__; | 773 DVLOG(1) << __FUNCTION__; |
758 if (!is_waiting_for_key_) | 774 |
| 775 if (is_waiting_for_key_) { |
| 776 ResumePlaybackAfterKeyAdded(); |
759 return; | 777 return; |
| 778 } |
| 779 |
| 780 if ((audio_decoder_job_->is_content_encrypted() && |
| 781 audio_decoder_job_->is_decoding()) || |
| 782 (video_decoder_job_->is_content_encrypted() && |
| 783 video_decoder_job_->is_decoding())) { |
| 784 DVLOG(1) << __FUNCTION__ << ": " << "Key added during pending decode."; |
| 785 key_added_while_decode_pending_ = true; |
| 786 } |
| 787 } |
| 788 |
| 789 void MediaSourcePlayer::ResumePlaybackAfterKeyAdded() { |
| 790 DVLOG(1) << __FUNCTION__; |
| 791 DCHECK(is_waiting_for_key_ || key_added_while_decode_pending_); |
760 | 792 |
761 is_waiting_for_key_ = false; | 793 is_waiting_for_key_ = false; |
| 794 key_added_while_decode_pending_ = false; |
| 795 |
| 796 // StartInternal() will trigger a prefetch, where in most cases we'll just |
| 797 // use previously received data. |
762 if (playing_) | 798 if (playing_) |
763 StartInternal(); | 799 StartInternal(); |
764 } | 800 } |
765 | 801 |
766 void MediaSourcePlayer::OnCdmUnset() { | 802 void MediaSourcePlayer::OnCdmUnset() { |
767 DVLOG(1) << __FUNCTION__; | 803 DVLOG(1) << __FUNCTION__; |
768 DCHECK(drm_bridge_); | 804 DCHECK(drm_bridge_); |
769 // TODO(xhwang): Currently this is only called during teardown. Support full | 805 // TODO(xhwang): Currently this is only called during teardown. Support full |
770 // detachment of CDM during playback. This will be needed when we start to | 806 // detachment of CDM during playback. This will be needed when we start to |
771 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release | 807 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release |
772 // MediaDrm when the video is paused, or when the device goes to sleep (see | 808 // MediaDrm when the video is paused, or when the device goes to sleep (see |
773 // http://crbug.com/272421). | 809 // http://crbug.com/272421). |
774 audio_decoder_job_->SetDrmBridge(NULL); | 810 audio_decoder_job_->SetDrmBridge(NULL); |
775 video_decoder_job_->SetDrmBridge(NULL); | 811 video_decoder_job_->SetDrmBridge(NULL); |
776 cdm_registration_id_ = 0; | 812 cdm_registration_id_ = 0; |
777 drm_bridge_ = NULL; | 813 drm_bridge_ = NULL; |
778 } | 814 } |
779 | 815 |
780 } // namespace media | 816 } // namespace media |
OLD | NEW |