| 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 return std::min(interpolator_.GetInterpolatedTime(), duration_); | 175 return std::min(interpolator_.GetInterpolatedTime(), duration_); |
| 176 } | 176 } |
| 177 | 177 |
| 178 base::TimeDelta MediaSourcePlayer::GetDuration() { | 178 base::TimeDelta MediaSourcePlayer::GetDuration() { |
| 179 return duration_; | 179 return duration_; |
| 180 } | 180 } |
| 181 | 181 |
| 182 void MediaSourcePlayer::Release() { | 182 void MediaSourcePlayer::Release() { |
| 183 DVLOG(1) << __FUNCTION__; | 183 DVLOG(1) << __FUNCTION__; |
| 184 | 184 |
| 185 media_stat_->StopAndReport(GetCurrentTime()); |
| 186 |
| 185 audio_decoder_job_->ReleaseDecoderResources(); | 187 audio_decoder_job_->ReleaseDecoderResources(); |
| 186 video_decoder_job_->ReleaseDecoderResources(); | 188 video_decoder_job_->ReleaseDecoderResources(); |
| 187 | 189 |
| 188 // Prevent player restart, including job re-creation attempts. | 190 // Prevent player restart, including job re-creation attempts. |
| 189 playing_ = false; | 191 playing_ = false; |
| 190 | 192 |
| 191 decoder_starvation_callback_.Cancel(); | 193 decoder_starvation_callback_.Cancel(); |
| 192 | 194 |
| 193 DetachListener(); | 195 DetachListener(); |
| 194 on_decoder_resources_released_cb_.Run(player_id()); | 196 on_decoder_resources_released_cb_.Run(player_id()); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 | 474 |
| 473 bool is_clock_manager = is_audio || !HasAudio(); | 475 bool is_clock_manager = is_audio || !HasAudio(); |
| 474 | 476 |
| 475 if (is_clock_manager) | 477 if (is_clock_manager) |
| 476 decoder_starvation_callback_.Cancel(); | 478 decoder_starvation_callback_.Cancel(); |
| 477 | 479 |
| 478 if (status == MEDIA_CODEC_ERROR) { | 480 if (status == MEDIA_CODEC_ERROR) { |
| 479 DVLOG(1) << __FUNCTION__ << " : decode error"; | 481 DVLOG(1) << __FUNCTION__ << " : decode error"; |
| 480 Release(); | 482 Release(); |
| 481 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); | 483 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); |
| 482 media_stat_->StopAndReport(GetCurrentTime()); | 484 if (is_clock_manager) |
| 485 media_stat_->StopAndReport(GetCurrentTime()); |
| 483 return; | 486 return; |
| 484 } | 487 } |
| 485 | 488 |
| 486 // Increment frame counts for UMA. | 489 // Increment frame counts for UMA. |
| 487 if (current_presentation_timestamp != kNoTimestamp()) { | 490 if (current_presentation_timestamp != kNoTimestamp()) { |
| 488 FrameStatistics& frame_stats = is_audio ? media_stat_->audio_frame_stats() | 491 FrameStatistics& frame_stats = is_audio ? media_stat_->audio_frame_stats() |
| 489 : media_stat_->video_frame_stats(); | 492 : media_stat_->video_frame_stats(); |
| 490 frame_stats.IncrementFrameCount(); | 493 frame_stats.IncrementFrameCount(); |
| 491 if (is_late_frame) | 494 if (is_late_frame) |
| 492 frame_stats.IncrementLateFrameCount(); | 495 frame_stats.IncrementLateFrameCount(); |
| 493 } | 496 } |
| 494 | 497 |
| 495 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); | 498 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); |
| 496 | 499 |
| 497 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of | 500 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of |
| 498 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process | 501 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process |
| 499 // any other pending events only after handling EOS detection. | 502 // any other pending events only after handling EOS detection. |
| 500 if (IsEventPending(SEEK_EVENT_PENDING)) { | 503 if (IsEventPending(SEEK_EVENT_PENDING)) { |
| 501 ProcessPendingEvents(); | 504 ProcessPendingEvents(); |
| 502 media_stat_->StopAndReport(GetCurrentTime()); | 505 // In case of Seek GetCurrentTime() already tells the time to seek to. |
| 506 if (is_clock_manager) |
| 507 media_stat_->StopAndReport(current_presentation_timestamp); |
| 503 return; | 508 return; |
| 504 } | 509 } |
| 505 | 510 |
| 506 if ((status == MEDIA_CODEC_OK || status == MEDIA_CODEC_INPUT_END_OF_STREAM) && | 511 if ((status == MEDIA_CODEC_OK || status == MEDIA_CODEC_INPUT_END_OF_STREAM) && |
| 507 is_clock_manager && current_presentation_timestamp != kNoTimestamp()) { | 512 is_clock_manager && current_presentation_timestamp != kNoTimestamp()) { |
| 508 UpdateTimestamps(current_presentation_timestamp, | 513 UpdateTimestamps(current_presentation_timestamp, |
| 509 max_presentation_timestamp); | 514 max_presentation_timestamp); |
| 510 } | 515 } |
| 511 | 516 |
| 512 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { | 517 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { |
| 513 PlaybackCompleted(is_audio); | 518 PlaybackCompleted(is_audio); |
| 514 if (is_clock_manager) | 519 if (is_clock_manager) |
| 515 interpolator_.StopInterpolating(); | 520 interpolator_.StopInterpolating(); |
| 516 } | 521 } |
| 517 | 522 |
| 518 if (pending_event_ != NO_EVENT_PENDING) { | 523 if (pending_event_ != NO_EVENT_PENDING) { |
| 519 ProcessPendingEvents(); | 524 ProcessPendingEvents(); |
| 520 return; | 525 return; |
| 521 } | 526 } |
| 522 | 527 |
| 523 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { | 528 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { |
| 524 media_stat_->StopAndReport(GetCurrentTime()); | 529 if (is_clock_manager) |
| 530 media_stat_->StopAndReport(GetCurrentTime()); |
| 525 return; | 531 return; |
| 526 } | 532 } |
| 527 | 533 |
| 528 if (!playing_) { | 534 if (!playing_) { |
| 529 if (is_clock_manager) | 535 if (is_clock_manager) |
| 530 interpolator_.StopInterpolating(); | 536 interpolator_.StopInterpolating(); |
| 531 | 537 |
| 532 media_stat_->StopAndReport(GetCurrentTime()); | 538 if (is_clock_manager) |
| 539 media_stat_->StopAndReport(GetCurrentTime()); |
| 533 return; | 540 return; |
| 534 } | 541 } |
| 535 | 542 |
| 536 if (status == MEDIA_CODEC_NO_KEY) { | 543 if (status == MEDIA_CODEC_NO_KEY) { |
| 537 if (key_added_while_decode_pending_) { | 544 if (key_added_while_decode_pending_) { |
| 538 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; | 545 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; |
| 539 ResumePlaybackAfterKeyAdded(); | 546 ResumePlaybackAfterKeyAdded(); |
| 540 } else { | 547 } else { |
| 541 is_waiting_for_key_ = true; | 548 is_waiting_for_key_ = true; |
| 542 manager()->OnWaitingForDecryptionKey(player_id()); | 549 manager()->OnWaitingForDecryptionKey(player_id()); |
| 543 media_stat_->StopAndReport(GetCurrentTime()); | 550 if (is_clock_manager) |
| 551 media_stat_->StopAndReport(GetCurrentTime()); |
| 544 } | 552 } |
| 545 return; | 553 return; |
| 546 } | 554 } |
| 547 | 555 |
| 548 // If |key_added_while_decode_pending_| is true and both audio and video | 556 // If |key_added_while_decode_pending_| is true and both audio and video |
| 549 // decoding succeeded, we should clear |key_added_while_decode_pending_| here. | 557 // decoding succeeded, we should clear |key_added_while_decode_pending_| here. |
| 550 // But that would add more complexity into this function. If we don't clear it | 558 // But that would add more complexity into this function. If we don't clear it |
| 551 // here, the worst case would be we call ResumePlaybackAfterKeyAdded() when | 559 // here, the worst case would be we call ResumePlaybackAfterKeyAdded() when |
| 552 // we don't really have a new key. This should rarely happen and the | 560 // we don't really have a new key. This should rarely happen and the |
| 553 // performance impact should be pretty small. | 561 // performance impact should be pretty small. |
| 554 // TODO(qinmin/xhwang): This class is complicated because we handle both audio | 562 // TODO(qinmin/xhwang): This class is complicated because we handle both audio |
| 555 // and video in one file. If we separate them, we should be able to remove a | 563 // and video in one file. If we separate them, we should be able to remove a |
| 556 // lot of duplication. | 564 // lot of duplication. |
| 557 | 565 |
| 558 // If the status is MEDIA_CODEC_ABORT, stop decoding new data. The player is | 566 // If the status is MEDIA_CODEC_ABORT, stop decoding new data. The player is |
| 559 // in the middle of a seek or stop event and needs to wait for the IPCs to | 567 // in the middle of a seek or stop event and needs to wait for the IPCs to |
| 560 // come. | 568 // come. |
| 561 if (status == MEDIA_CODEC_ABORT) { | 569 if (status == MEDIA_CODEC_ABORT) { |
| 562 media_stat_->StopAndReport(GetCurrentTime()); | 570 if (is_clock_manager) |
| 571 media_stat_->StopAndReport(GetCurrentTime()); |
| 563 return; | 572 return; |
| 564 } | 573 } |
| 565 | 574 |
| 566 if (prerolling_ && IsPrerollFinished(is_audio)) { | 575 if (prerolling_ && IsPrerollFinished(is_audio)) { |
| 567 if (IsPrerollFinished(!is_audio)) { | 576 if (IsPrerollFinished(!is_audio)) { |
| 568 prerolling_ = false; | 577 prerolling_ = false; |
| 569 StartInternal(); | 578 StartInternal(); |
| 570 } | 579 } |
| 571 return; | 580 return; |
| 572 } | 581 } |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 is_waiting_for_key_ = false; | 845 is_waiting_for_key_ = false; |
| 837 key_added_while_decode_pending_ = false; | 846 key_added_while_decode_pending_ = false; |
| 838 | 847 |
| 839 // StartInternal() will trigger a prefetch, where in most cases we'll just | 848 // StartInternal() will trigger a prefetch, where in most cases we'll just |
| 840 // use previously received data. | 849 // use previously received data. |
| 841 if (playing_) | 850 if (playing_) |
| 842 StartInternal(); | 851 StartInternal(); |
| 843 } | 852 } |
| 844 | 853 |
| 845 } // namespace media | 854 } // namespace media |
| OLD | NEW |