Chromium Code Reviews| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 return; | 83 return; |
| 84 // Retry video decoder creation. | 84 // Retry video decoder creation. |
| 85 RetryDecoderCreation(false, true); | 85 RetryDecoderCreation(false, true); |
| 86 } | 86 } |
| 87 | 87 |
| 88 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( | 88 void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( |
| 89 base::TimeDelta seek_time) { | 89 base::TimeDelta seek_time) { |
| 90 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; | 90 DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; |
| 91 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); | 91 DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); |
| 92 | 92 |
| 93 // Need to stop here to prevent false reports while seek and drag. | |
|
qinmin
2015/11/18 18:12:27
Do we need this? We should have captured this situ
Tima Vaisburd
2015/11/18 18:31:13
I think we do. During the seek-and-drag II did not
qinmin
2015/11/18 19:11:43
Start() will automatically kick off the MediaDecod
Tima Vaisburd
2015/11/18 20:02:12
Yes, you are right, sorry I misled you. The bug wa
| |
| 94 media_stat_->StopAndReport(GetCurrentTime()); | |
| 95 | |
| 93 pending_seek_ = false; | 96 pending_seek_ = false; |
| 94 | 97 |
| 95 interpolator_.SetBounds(seek_time, seek_time); | 98 interpolator_.SetBounds(seek_time, seek_time); |
| 96 | 99 |
| 97 if (audio_decoder_job_->is_decoding()) | 100 if (audio_decoder_job_->is_decoding()) |
| 98 audio_decoder_job_->StopDecode(); | 101 audio_decoder_job_->StopDecode(); |
| 99 if (video_decoder_job_->is_decoding()) | 102 if (video_decoder_job_->is_decoding()) |
| 100 video_decoder_job_->StopDecode(); | 103 video_decoder_job_->StopDecode(); |
| 101 | 104 |
| 102 SetPendingEvent(SEEK_EVENT_PENDING); | 105 SetPendingEvent(SEEK_EVENT_PENDING); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 return std::min(interpolator_.GetInterpolatedTime(), duration_); | 178 return std::min(interpolator_.GetInterpolatedTime(), duration_); |
| 176 } | 179 } |
| 177 | 180 |
| 178 base::TimeDelta MediaSourcePlayer::GetDuration() { | 181 base::TimeDelta MediaSourcePlayer::GetDuration() { |
| 179 return duration_; | 182 return duration_; |
| 180 } | 183 } |
| 181 | 184 |
| 182 void MediaSourcePlayer::Release() { | 185 void MediaSourcePlayer::Release() { |
| 183 DVLOG(1) << __FUNCTION__; | 186 DVLOG(1) << __FUNCTION__; |
| 184 | 187 |
| 188 media_stat_->StopAndReport(GetCurrentTime()); | |
| 189 | |
| 185 audio_decoder_job_->ReleaseDecoderResources(); | 190 audio_decoder_job_->ReleaseDecoderResources(); |
| 186 video_decoder_job_->ReleaseDecoderResources(); | 191 video_decoder_job_->ReleaseDecoderResources(); |
| 187 | 192 |
| 188 // Prevent player restart, including job re-creation attempts. | 193 // Prevent player restart, including job re-creation attempts. |
| 189 playing_ = false; | 194 playing_ = false; |
| 190 | 195 |
| 191 decoder_starvation_callback_.Cancel(); | 196 decoder_starvation_callback_.Cancel(); |
| 192 | 197 |
| 193 DetachListener(); | 198 DetachListener(); |
| 194 on_decoder_resources_released_cb_.Run(player_id()); | 199 on_decoder_resources_released_cb_.Run(player_id()); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 472 | 477 |
| 473 bool is_clock_manager = is_audio || !HasAudio(); | 478 bool is_clock_manager = is_audio || !HasAudio(); |
| 474 | 479 |
| 475 if (is_clock_manager) | 480 if (is_clock_manager) |
| 476 decoder_starvation_callback_.Cancel(); | 481 decoder_starvation_callback_.Cancel(); |
| 477 | 482 |
| 478 if (status == MEDIA_CODEC_ERROR) { | 483 if (status == MEDIA_CODEC_ERROR) { |
| 479 DVLOG(1) << __FUNCTION__ << " : decode error"; | 484 DVLOG(1) << __FUNCTION__ << " : decode error"; |
| 480 Release(); | 485 Release(); |
| 481 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); | 486 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); |
| 482 media_stat_->StopAndReport(GetCurrentTime()); | 487 if (is_clock_manager) |
| 488 media_stat_->StopAndReport(GetCurrentTime()); | |
| 483 return; | 489 return; |
| 484 } | 490 } |
| 485 | 491 |
| 486 // Increment frame counts for UMA. | 492 // Increment frame counts for UMA. |
| 487 if (current_presentation_timestamp != kNoTimestamp()) { | 493 if (current_presentation_timestamp != kNoTimestamp()) { |
| 488 FrameStatistics& frame_stats = is_audio ? media_stat_->audio_frame_stats() | 494 FrameStatistics& frame_stats = is_audio ? media_stat_->audio_frame_stats() |
| 489 : media_stat_->video_frame_stats(); | 495 : media_stat_->video_frame_stats(); |
| 490 frame_stats.IncrementFrameCount(); | 496 frame_stats.IncrementFrameCount(); |
| 491 if (is_late_frame) | 497 if (is_late_frame) |
| 492 frame_stats.IncrementLateFrameCount(); | 498 frame_stats.IncrementLateFrameCount(); |
| 493 } | 499 } |
| 494 | 500 |
| 495 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); | 501 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); |
| 496 | 502 |
| 497 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of | 503 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of |
| 498 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process | 504 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process |
| 499 // any other pending events only after handling EOS detection. | 505 // any other pending events only after handling EOS detection. |
| 500 if (IsEventPending(SEEK_EVENT_PENDING)) { | 506 if (IsEventPending(SEEK_EVENT_PENDING)) { |
| 501 ProcessPendingEvents(); | 507 ProcessPendingEvents(); |
| 502 media_stat_->StopAndReport(GetCurrentTime()); | 508 // In case of Seek GetCurrentTime() already tells the time to seek to. |
| 509 if (is_clock_manager) | |
| 510 media_stat_->StopAndReport(current_presentation_timestamp); | |
| 503 return; | 511 return; |
| 504 } | 512 } |
| 505 | 513 |
| 506 if ((status == MEDIA_CODEC_OK || status == MEDIA_CODEC_INPUT_END_OF_STREAM) && | 514 if ((status == MEDIA_CODEC_OK || status == MEDIA_CODEC_INPUT_END_OF_STREAM) && |
| 507 is_clock_manager && current_presentation_timestamp != kNoTimestamp()) { | 515 is_clock_manager && current_presentation_timestamp != kNoTimestamp()) { |
| 508 UpdateTimestamps(current_presentation_timestamp, | 516 UpdateTimestamps(current_presentation_timestamp, |
| 509 max_presentation_timestamp); | 517 max_presentation_timestamp); |
| 510 } | 518 } |
| 511 | 519 |
| 512 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { | 520 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { |
| 513 PlaybackCompleted(is_audio); | 521 PlaybackCompleted(is_audio); |
| 514 if (is_clock_manager) | 522 if (is_clock_manager) |
| 515 interpolator_.StopInterpolating(); | 523 interpolator_.StopInterpolating(); |
| 516 } | 524 } |
| 517 | 525 |
| 518 if (pending_event_ != NO_EVENT_PENDING) { | 526 if (pending_event_ != NO_EVENT_PENDING) { |
| 519 ProcessPendingEvents(); | 527 ProcessPendingEvents(); |
| 520 return; | 528 return; |
| 521 } | 529 } |
| 522 | 530 |
| 523 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { | 531 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { |
| 524 media_stat_->StopAndReport(GetCurrentTime()); | 532 if (is_clock_manager) |
| 533 media_stat_->StopAndReport(GetCurrentTime()); | |
| 525 return; | 534 return; |
| 526 } | 535 } |
| 527 | 536 |
| 528 if (!playing_) { | 537 if (!playing_) { |
| 529 if (is_clock_manager) | 538 if (is_clock_manager) |
| 530 interpolator_.StopInterpolating(); | 539 interpolator_.StopInterpolating(); |
| 531 | 540 |
| 532 media_stat_->StopAndReport(GetCurrentTime()); | 541 if (is_clock_manager) |
| 542 media_stat_->StopAndReport(GetCurrentTime()); | |
| 533 return; | 543 return; |
| 534 } | 544 } |
| 535 | 545 |
| 536 if (status == MEDIA_CODEC_NO_KEY) { | 546 if (status == MEDIA_CODEC_NO_KEY) { |
| 537 if (key_added_while_decode_pending_) { | 547 if (key_added_while_decode_pending_) { |
| 538 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; | 548 DVLOG(2) << __FUNCTION__ << ": Key was added during decoding."; |
| 539 ResumePlaybackAfterKeyAdded(); | 549 ResumePlaybackAfterKeyAdded(); |
| 540 } else { | 550 } else { |
| 541 is_waiting_for_key_ = true; | 551 is_waiting_for_key_ = true; |
| 542 manager()->OnWaitingForDecryptionKey(player_id()); | 552 manager()->OnWaitingForDecryptionKey(player_id()); |
| 543 media_stat_->StopAndReport(GetCurrentTime()); | 553 if (is_clock_manager) |
| 554 media_stat_->StopAndReport(GetCurrentTime()); | |
| 544 } | 555 } |
| 545 return; | 556 return; |
| 546 } | 557 } |
| 547 | 558 |
| 548 // If |key_added_while_decode_pending_| is true and both audio and video | 559 // 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. | 560 // 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 | 561 // 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 | 562 // 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 | 563 // we don't really have a new key. This should rarely happen and the |
| 553 // performance impact should be pretty small. | 564 // performance impact should be pretty small. |
| 554 // TODO(qinmin/xhwang): This class is complicated because we handle both audio | 565 // 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 | 566 // and video in one file. If we separate them, we should be able to remove a |
| 556 // lot of duplication. | 567 // lot of duplication. |
| 557 | 568 |
| 558 // If the status is MEDIA_CODEC_ABORT, stop decoding new data. The player is | 569 // 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 | 570 // in the middle of a seek or stop event and needs to wait for the IPCs to |
| 560 // come. | 571 // come. |
| 561 if (status == MEDIA_CODEC_ABORT) { | 572 if (status == MEDIA_CODEC_ABORT) { |
| 562 media_stat_->StopAndReport(GetCurrentTime()); | 573 if (is_clock_manager) |
| 574 media_stat_->StopAndReport(GetCurrentTime()); | |
| 563 return; | 575 return; |
| 564 } | 576 } |
| 565 | 577 |
| 566 if (prerolling_ && IsPrerollFinished(is_audio)) { | 578 if (prerolling_ && IsPrerollFinished(is_audio)) { |
| 567 if (IsPrerollFinished(!is_audio)) { | 579 if (IsPrerollFinished(!is_audio)) { |
| 568 prerolling_ = false; | 580 prerolling_ = false; |
| 569 StartInternal(); | 581 StartInternal(); |
| 570 } | 582 } |
| 571 return; | 583 return; |
| 572 } | 584 } |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 836 is_waiting_for_key_ = false; | 848 is_waiting_for_key_ = false; |
| 837 key_added_while_decode_pending_ = false; | 849 key_added_while_decode_pending_ = false; |
| 838 | 850 |
| 839 // StartInternal() will trigger a prefetch, where in most cases we'll just | 851 // StartInternal() will trigger a prefetch, where in most cases we'll just |
| 840 // use previously received data. | 852 // use previously received data. |
| 841 if (playing_) | 853 if (playing_) |
| 842 StartInternal(); | 854 StartInternal(); |
| 843 } | 855 } |
| 844 | 856 |
| 845 } // namespace media | 857 } // namespace media |
| OLD | NEW |