| 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 |