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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 void MediaSourcePlayer::Pause(bool is_media_related_action) { | 127 void MediaSourcePlayer::Pause(bool is_media_related_action) { |
128 DVLOG(1) << __FUNCTION__; | 128 DVLOG(1) << __FUNCTION__; |
129 | 129 |
130 // Since decoder jobs have their own thread, decoding is not fully paused | 130 // Since decoder jobs have their own thread, decoding is not fully paused |
131 // until all the decoder jobs call MediaDecoderCallback(). It is possible | 131 // until all the decoder jobs call MediaDecoderCallback(). It is possible |
132 // that Start() is called while the player is waiting for | 132 // that Start() is called while the player is waiting for |
133 // MediaDecoderCallback(). In that case, decoding will continue when | 133 // MediaDecoderCallback(). In that case, decoding will continue when |
134 // MediaDecoderCallback() is called. | 134 // MediaDecoderCallback() is called. |
135 playing_ = false; | 135 playing_ = false; |
136 start_time_ticks_ = base::TimeTicks(); | 136 start_time_ticks_ = base::TimeTicks(); |
137 | |
138 SetAudible(false); | |
139 } | 137 } |
140 | 138 |
141 bool MediaSourcePlayer::IsPlaying() { | 139 bool MediaSourcePlayer::IsPlaying() { |
142 return playing_; | 140 return playing_; |
143 } | 141 } |
144 | 142 |
145 int MediaSourcePlayer::GetVideoWidth() { | 143 int MediaSourcePlayer::GetVideoWidth() { |
146 return video_decoder_job_->output_width(); | 144 return video_decoder_job_->output_width(); |
147 } | 145 } |
148 | 146 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 DVLOG(1) << __FUNCTION__; | 179 DVLOG(1) << __FUNCTION__; |
182 | 180 |
183 audio_decoder_job_->ReleaseDecoderResources(); | 181 audio_decoder_job_->ReleaseDecoderResources(); |
184 video_decoder_job_->ReleaseDecoderResources(); | 182 video_decoder_job_->ReleaseDecoderResources(); |
185 | 183 |
186 // Prevent player restart, including job re-creation attempts. | 184 // Prevent player restart, including job re-creation attempts. |
187 playing_ = false; | 185 playing_ = false; |
188 | 186 |
189 decoder_starvation_callback_.Cancel(); | 187 decoder_starvation_callback_.Cancel(); |
190 | 188 |
191 SetAudible(false); | |
192 DetachListener(); | 189 DetachListener(); |
193 } | 190 } |
194 | 191 |
195 void MediaSourcePlayer::SetVolume(double volume) { | 192 void MediaSourcePlayer::SetVolume(double volume) { |
196 audio_decoder_job_->SetVolume(volume); | 193 audio_decoder_job_->SetVolume(volume); |
197 } | 194 } |
198 | 195 |
199 bool MediaSourcePlayer::CanPause() { | 196 bool MediaSourcePlayer::CanPause() { |
200 return Seekable(); | 197 return Seekable(); |
201 } | 198 } |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 PlaybackCompleted(is_audio); | 485 PlaybackCompleted(is_audio); |
489 if (is_clock_manager) | 486 if (is_clock_manager) |
490 interpolator_.StopInterpolating(); | 487 interpolator_.StopInterpolating(); |
491 } | 488 } |
492 | 489 |
493 if (pending_event_ != NO_EVENT_PENDING) { | 490 if (pending_event_ != NO_EVENT_PENDING) { |
494 ProcessPendingEvents(); | 491 ProcessPendingEvents(); |
495 return; | 492 return; |
496 } | 493 } |
497 | 494 |
498 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { | 495 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
499 if (is_audio) | |
500 SetAudible(false); | |
501 return; | 496 return; |
502 } | |
503 | 497 |
504 if (!playing_) { | 498 if (!playing_) { |
505 if (is_clock_manager) | 499 if (is_clock_manager) |
506 interpolator_.StopInterpolating(); | 500 interpolator_.StopInterpolating(); |
507 | 501 |
508 if (is_audio) | |
509 SetAudible(false); | |
510 return; | 502 return; |
511 } | 503 } |
512 | 504 |
513 if (status == MEDIA_CODEC_NO_KEY) { | 505 if (status == MEDIA_CODEC_NO_KEY) { |
514 if (key_added_while_decode_pending_) { | 506 if (key_added_while_decode_pending_) { |
515 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; | 507 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; |
516 ResumePlaybackAfterKeyAdded(); | 508 ResumePlaybackAfterKeyAdded(); |
517 } else { | 509 } else { |
518 if (is_audio) | |
519 SetAudible(false); | |
520 | |
521 is_waiting_for_key_ = true; | 510 is_waiting_for_key_ = true; |
522 manager()->OnWaitingForDecryptionKey(player_id()); | 511 manager()->OnWaitingForDecryptionKey(player_id()); |
523 } | 512 } |
524 return; | 513 return; |
525 } | 514 } |
526 | 515 |
527 // If |key_added_while_decode_pending_| is true and both audio and video | 516 // If |key_added_while_decode_pending_| is true and both audio and video |
528 // decoding succeeded, we should clear |key_added_while_decode_pending_| here. | 517 // decoding succeeded, we should clear |key_added_while_decode_pending_| here. |
529 // But that would add more complexity into this function. If we don't clear it | 518 // But that would add more complexity into this function. If we don't clear it |
530 // here, the worst case would be we call ResumePlaybackAfterKeyAdded() when | 519 // here, the worst case would be we call ResumePlaybackAfterKeyAdded() when |
531 // we don't really have a new key. This should rarely happen and the | 520 // we don't really have a new key. This should rarely happen and the |
532 // performance impact should be pretty small. | 521 // performance impact should be pretty small. |
533 // TODO(qinmin/xhwang): This class is complicated because we handle both audio | 522 // TODO(qinmin/xhwang): This class is complicated because we handle both audio |
534 // and video in one file. If we separate them, we should be able to remove a | 523 // and video in one file. If we separate them, we should be able to remove a |
535 // lot of duplication. | 524 // lot of duplication. |
536 | 525 |
537 // If the status is MEDIA_CODEC_ABORT, stop decoding new data. The player is | 526 // If the status is MEDIA_CODEC_ABORT, stop decoding new data. The player is |
538 // in the middle of a seek or stop event and needs to wait for the IPCs to | 527 // in the middle of a seek or stop event and needs to wait for the IPCs to |
539 // come. | 528 // come. |
540 if (status == MEDIA_CODEC_ABORT) { | 529 if (status == MEDIA_CODEC_ABORT) |
541 if (is_audio) | |
542 SetAudible(false); | |
543 return; | 530 return; |
544 } | |
545 | 531 |
546 if (prerolling_ && IsPrerollFinished(is_audio)) { | 532 if (prerolling_ && IsPrerollFinished(is_audio)) { |
547 if (IsPrerollFinished(!is_audio)) { | 533 if (IsPrerollFinished(!is_audio)) { |
548 prerolling_ = false; | 534 prerolling_ = false; |
549 StartInternal(); | 535 StartInternal(); |
550 } | 536 } |
551 return; | 537 return; |
552 } | 538 } |
553 | 539 |
554 // We successfully decoded a frame and going to the next one. | |
555 // Set the audible state. | |
556 if (is_audio) { | |
557 bool is_audible = !prerolling_ && audio_decoder_job_->volume() > 0; | |
558 SetAudible(is_audible); | |
559 } | |
560 | |
561 if (is_clock_manager) { | 540 if (is_clock_manager) { |
562 // If we have a valid timestamp, start the starvation callback. Otherwise, | 541 // If we have a valid timestamp, start the starvation callback. Otherwise, |
563 // reset the |start_time_ticks_| so that the next frame will not suffer | 542 // reset the |start_time_ticks_| so that the next frame will not suffer |
564 // from the decoding delay caused by the current frame. | 543 // from the decoding delay caused by the current frame. |
565 if (current_presentation_timestamp != kNoTimestamp()) | 544 if (current_presentation_timestamp != kNoTimestamp()) |
566 StartStarvationCallback(current_presentation_timestamp, | 545 StartStarvationCallback(current_presentation_timestamp, |
567 max_presentation_timestamp); | 546 max_presentation_timestamp); |
568 else | 547 else |
569 start_time_ticks_ = base::TimeTicks::Now(); | 548 start_time_ticks_ = base::TimeTicks::Now(); |
570 } | 549 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 return audio_decoder_job_->OutputEOSReached() || !HasAudio(); | 642 return audio_decoder_job_->OutputEOSReached() || !HasAudio(); |
664 } | 643 } |
665 | 644 |
666 bool MediaSourcePlayer::VideoFinished() { | 645 bool MediaSourcePlayer::VideoFinished() { |
667 return video_decoder_job_->OutputEOSReached() || !HasVideo(); | 646 return video_decoder_job_->OutputEOSReached() || !HasVideo(); |
668 } | 647 } |
669 | 648 |
670 void MediaSourcePlayer::OnDecoderStarved() { | 649 void MediaSourcePlayer::OnDecoderStarved() { |
671 DVLOG(1) << __FUNCTION__; | 650 DVLOG(1) << __FUNCTION__; |
672 | 651 |
673 if (HasAudio()) { | |
674 // If the starvation timer fired but there are no encoded frames | |
675 // in the queue we believe the demuxer (i.e. renderer process) froze. | |
676 if (!audio_decoder_job_->HasData()) | |
677 SetAudible(false); | |
678 } | |
679 | |
680 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 652 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
681 ProcessPendingEvents(); | 653 ProcessPendingEvents(); |
682 } | 654 } |
683 | 655 |
684 void MediaSourcePlayer::StartStarvationCallback( | 656 void MediaSourcePlayer::StartStarvationCallback( |
685 base::TimeDelta current_presentation_timestamp, | 657 base::TimeDelta current_presentation_timestamp, |
686 base::TimeDelta max_presentation_timestamp) { | 658 base::TimeDelta max_presentation_timestamp) { |
687 // 20ms was chosen because it is the typical size of a compressed audio frame. | 659 // 20ms was chosen because it is the typical size of a compressed audio frame. |
688 // Anything smaller than this would likely cause unnecessary cycling in and | 660 // Anything smaller than this would likely cause unnecessary cycling in and |
689 // out of the prefetch state. | 661 // out of the prefetch state. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release | 812 // support setMediaKeys(0) (see http://crbug.com/330324), or when we release |
841 // MediaDrm when the video is paused, or when the device goes to sleep (see | 813 // MediaDrm when the video is paused, or when the device goes to sleep (see |
842 // http://crbug.com/272421). | 814 // http://crbug.com/272421). |
843 audio_decoder_job_->SetDrmBridge(NULL); | 815 audio_decoder_job_->SetDrmBridge(NULL); |
844 video_decoder_job_->SetDrmBridge(NULL); | 816 video_decoder_job_->SetDrmBridge(NULL); |
845 cdm_registration_id_ = 0; | 817 cdm_registration_id_ = 0; |
846 drm_bridge_ = NULL; | 818 drm_bridge_ = NULL; |
847 } | 819 } |
848 | 820 |
849 } // namespace media | 821 } // namespace media |
OLD | NEW |