OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_codec_player.h" | 5 #include "media/base/android/media_codec_player.h" |
6 | 6 |
7 #include "base/barrier_closure.h" | 7 #include "base/barrier_closure.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 seek_info_->seek_time <= actual_browser_seek_time); | 434 seek_info_->seek_time <= actual_browser_seek_time); |
435 | 435 |
436 // Restrict the current time to be equal to seek_time | 436 // Restrict the current time to be equal to seek_time |
437 // for the next StartPlaybackDecoders() call. | 437 // for the next StartPlaybackDecoders() call. |
438 | 438 |
439 base::TimeDelta seek_time = seek_info_->is_browser_seek | 439 base::TimeDelta seek_time = seek_info_->is_browser_seek |
440 ? actual_browser_seek_time | 440 ? actual_browser_seek_time |
441 : seek_info_->seek_time; | 441 : seek_info_->seek_time; |
442 | 442 |
443 interpolator_.SetBounds(seek_time, seek_time); | 443 interpolator_.SetBounds(seek_time, seek_time); |
| 444 |
444 audio_decoder_->SetBaseTimestamp(seek_time); | 445 audio_decoder_->SetBaseTimestamp(seek_time); |
445 | 446 |
| 447 audio_decoder_->SetPrerollTimestamp(seek_time); |
| 448 video_decoder_->SetPrerollTimestamp(seek_time); |
| 449 |
446 // The Flush() might set the state to kStateError. | 450 // The Flush() might set the state to kStateError. |
447 if (state_ == kStateError) { | 451 if (state_ == kStateError) { |
448 // Notify the Renderer. | 452 // Notify the Renderer. |
449 if (!seek_info_->is_browser_seek) | 453 if (!seek_info_->is_browser_seek) |
450 ui_task_runner_->PostTask(FROM_HERE, | 454 ui_task_runner_->PostTask(FROM_HERE, |
451 base::Bind(seek_done_cb_, seek_time)); | 455 base::Bind(seek_done_cb_, seek_time)); |
452 | 456 |
453 seek_info_.reset(); | 457 seek_info_.reset(); |
454 return; | 458 return; |
455 } | 459 } |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 SetState(kStatePlaying); | 617 SetState(kStatePlaying); |
614 StartPlaybackOrBrowserSeek(); | 618 StartPlaybackOrBrowserSeek(); |
615 } | 619 } |
616 | 620 |
617 void MediaCodecPlayer::OnPrerollDone() { | 621 void MediaCodecPlayer::OnPrerollDone() { |
618 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 622 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
619 | 623 |
620 // http://crbug.com/526755 | 624 // http://crbug.com/526755 |
621 DVLOG(0) << __FUNCTION__; | 625 DVLOG(0) << __FUNCTION__; |
622 | 626 |
| 627 if (state_ != kStatePlaying) { |
| 628 DVLOG(1) << __FUNCTION__ << ": in state " << AsString(state_) |
| 629 << ", ignoring"; |
| 630 return; |
| 631 } |
| 632 |
623 StartStatus status = StartDecoders(); | 633 StartStatus status = StartDecoders(); |
624 if (status != kStartOk) | 634 if (status != kStartOk) |
625 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); | 635 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
626 } | 636 } |
627 | 637 |
628 void MediaCodecPlayer::OnDecoderDrained(DemuxerStream::Type type) { | 638 void MediaCodecPlayer::OnDecoderDrained(DemuxerStream::Type type) { |
629 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 639 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
630 DVLOG(1) << __FUNCTION__ << " " << type; | 640 DVLOG(1) << __FUNCTION__ << " " << type; |
631 | 641 |
632 // We expect that OnStopDone() comes next. | 642 // We expect that OnStopDone() comes next. |
633 | 643 |
634 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); | 644 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); |
635 DCHECK(state_ == kStatePlaying || state_ == kStateStopping) | 645 DCHECK(state_ == kStatePlaying || state_ == kStateStopping) |
636 << __FUNCTION__ << " illegal state: " << AsString(state_); | 646 << __FUNCTION__ << " illegal state: " << AsString(state_); |
637 | 647 |
638 switch (state_) { | 648 switch (state_) { |
639 case kStatePlaying: | 649 case kStatePlaying: |
640 SetState(kStateStopping); | 650 SetState(kStateStopping); |
641 SetPendingStart(true); | 651 SetPendingStart(true); |
642 | 652 |
643 if (type == DemuxerStream::AUDIO && !VideoFinished()) { | 653 if (type == DemuxerStream::AUDIO && !VideoFinished()) { |
644 DVLOG(1) << __FUNCTION__ << " requesting to stop video"; | 654 DVLOG(1) << __FUNCTION__ << " requesting to stop video"; |
645 video_decoder_->SetDecodingUntilOutputIsPresent(); | |
646 video_decoder_->RequestToStop(); | 655 video_decoder_->RequestToStop(); |
647 } else if (type == DemuxerStream::VIDEO && !AudioFinished()) { | 656 } else if (type == DemuxerStream::VIDEO && !AudioFinished()) { |
648 DVLOG(1) << __FUNCTION__ << " requesting to stop audio"; | 657 DVLOG(1) << __FUNCTION__ << " requesting to stop audio"; |
649 audio_decoder_->SetDecodingUntilOutputIsPresent(); | |
650 audio_decoder_->RequestToStop(); | 658 audio_decoder_->RequestToStop(); |
651 } | 659 } |
652 break; | 660 break; |
653 | 661 |
654 case kStateStopping: | |
655 if (type == DemuxerStream::AUDIO && !VideoFinished()) | |
656 video_decoder_->SetDecodingUntilOutputIsPresent(); | |
657 else if (type == DemuxerStream::VIDEO && !AudioFinished()) | |
658 audio_decoder_->SetDecodingUntilOutputIsPresent(); | |
659 break; | |
660 | |
661 default: | 662 default: |
662 NOTREACHED(); | |
663 break; | 663 break; |
664 } | 664 } |
665 } | 665 } |
666 | 666 |
667 void MediaCodecPlayer::OnStopDone(DemuxerStream::Type type) { | 667 void MediaCodecPlayer::OnStopDone(DemuxerStream::Type type) { |
668 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 668 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
669 DVLOG(1) << __FUNCTION__ << " " << type | 669 DVLOG(1) << __FUNCTION__ << " " << type |
670 << " interpolated time:" << GetInterpolatedTime(); | 670 << " interpolated time:" << GetInterpolatedTime(); |
671 | 671 |
672 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) { | 672 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) { |
(...skipping 26 matching lines...) Expand all Loading... |
699 // Unexpected stop means completion | 699 // Unexpected stop means completion |
700 SetState(kStatePaused); | 700 SetState(kStatePaused); |
701 break; | 701 break; |
702 default: | 702 default: |
703 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); | 703 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); |
704 // NOTREACHED(); | 704 // NOTREACHED(); |
705 // Ignore! There can be a race condition: audio posts OnStopDone, | 705 // Ignore! There can be a race condition: audio posts OnStopDone, |
706 // then video posts, then first OnStopDone arrives at which point | 706 // then video posts, then first OnStopDone arrives at which point |
707 // both streams are already stopped, then second OnStopDone arrives. When | 707 // both streams are already stopped, then second OnStopDone arrives. When |
708 // the second one arrives, the state us not kStateStopping any more. | 708 // the second one arrives, the state us not kStateStopping any more. |
709 break; | 709 return; |
710 } | 710 } |
711 | 711 |
712 // DetachListener to UI thread | 712 // DetachListener to UI thread |
713 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); | 713 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); |
714 | 714 |
715 if (AudioFinished() && VideoFinished()) | 715 if (AudioFinished() && VideoFinished()) |
716 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); | 716 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); |
717 } | 717 } |
718 | 718 |
719 void MediaCodecPlayer::OnError() { | 719 void MediaCodecPlayer::OnError() { |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 } | 968 } |
969 } | 969 } |
970 | 970 |
971 return kStartOk; | 971 return kStartOk; |
972 } | 972 } |
973 | 973 |
974 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( | 974 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( |
975 bool* preroll_required) { | 975 bool* preroll_required) { |
976 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 976 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
977 | 977 |
978 base::TimeDelta current_time = GetInterpolatedTime(); | 978 DVLOG(1) << __FUNCTION__ << " current_time:" << GetInterpolatedTime(); |
979 | |
980 DVLOG(1) << __FUNCTION__ << " current_time:" << current_time; | |
981 | 979 |
982 // If requested, preroll is always done in the beginning of the playback, | 980 // If requested, preroll is always done in the beginning of the playback, |
983 // after prefetch. The request might not happen at all though, in which case | 981 // after prefetch. The request might not happen at all though, in which case |
984 // we won't have prerolling phase. We need the prerolling when we (re)create | 982 // we won't have prerolling phase. We need the prerolling when we (re)create |
985 // the decoder, because its configuration and initialization (getting input, | 983 // the decoder, because its configuration and initialization (getting input, |
986 // but not making output) can take time, and after the seek because there | 984 // but not making output) can take time, and after the seek because there |
987 // could be some data to be skipped and there is again initialization after | 985 // could be some data to be skipped and there is again initialization after |
988 // the flush. | 986 // the flush. |
989 | 987 |
990 *preroll_required = false; | 988 *preroll_required = false; |
991 | 989 |
992 int count = 0; | 990 int count = 0; |
993 const bool do_audio_preroll = audio_decoder_->NotCompletedAndNeedsPreroll(); | 991 const bool do_audio = audio_decoder_->NotCompletedAndNeedsPreroll(); |
994 if (do_audio_preroll) | 992 if (do_audio) |
995 ++count; | 993 ++count; |
996 | 994 |
997 const bool do_video_preroll = video_decoder_->NotCompletedAndNeedsPreroll(); | 995 const bool do_video = video_decoder_->NotCompletedAndNeedsPreroll(); |
998 if (do_video_preroll) | 996 if (do_video) |
999 ++count; | 997 ++count; |
1000 | 998 |
1001 if (count == 0) { | 999 if (count == 0) { |
1002 DVLOG(1) << __FUNCTION__ << ": preroll is not required, skipping"; | 1000 DVLOG(1) << __FUNCTION__ << ": preroll is not required, skipping"; |
1003 return kStartOk; | 1001 return kStartOk; |
1004 } | 1002 } |
1005 | 1003 |
1006 *preroll_required = true; | 1004 *preroll_required = true; |
1007 | 1005 |
1008 DCHECK(count > 0); | 1006 DCHECK(count > 0); |
1009 DCHECK(do_audio_preroll || do_video_preroll); | 1007 DCHECK(do_audio || do_video); |
1010 | 1008 |
1011 DVLOG(1) << __FUNCTION__ << ": preroll for " << count << " stream(s)"; | 1009 DVLOG(1) << __FUNCTION__ << ": preroll for " << count << " stream(s)"; |
1012 | 1010 |
1013 base::Closure preroll_cb = base::BarrierClosure( | 1011 base::Closure preroll_cb = base::BarrierClosure( |
1014 count, base::Bind(&MediaCodecPlayer::OnPrerollDone, media_weak_this_)); | 1012 count, base::Bind(&MediaCodecPlayer::OnPrerollDone, media_weak_this_)); |
1015 | 1013 |
1016 if (do_audio_preroll) { | 1014 if (do_audio && !audio_decoder_->Preroll(preroll_cb)) |
1017 if (!audio_decoder_->Preroll(current_time, preroll_cb)) | 1015 return kStartFailed; |
1018 return kStartFailed; | |
1019 } | |
1020 | 1016 |
1021 if (do_video_preroll) { | 1017 if (do_video && !video_decoder_->Preroll(preroll_cb)) |
1022 if (!video_decoder_->Preroll(current_time, preroll_cb)) | 1018 return kStartFailed; |
1023 return kStartFailed; | |
1024 } | |
1025 | 1019 |
1026 return kStartOk; | 1020 return kStartOk; |
1027 } | 1021 } |
1028 | 1022 |
1029 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartDecoders() { | 1023 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartDecoders() { |
1030 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1024 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
1031 | 1025 |
1032 if (!interpolator_.interpolating()) | 1026 if (!interpolator_.interpolating()) |
1033 interpolator_.StartInterpolating(); | 1027 interpolator_.StartInterpolating(); |
1034 | 1028 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1183 RETURN_STRING(kStateWaitingForSurface); | 1177 RETURN_STRING(kStateWaitingForSurface); |
1184 RETURN_STRING(kStateWaitingForSeek); | 1178 RETURN_STRING(kStateWaitingForSeek); |
1185 RETURN_STRING(kStateError); | 1179 RETURN_STRING(kStateError); |
1186 } | 1180 } |
1187 return nullptr; // crash early | 1181 return nullptr; // crash early |
1188 } | 1182 } |
1189 | 1183 |
1190 #undef RETURN_STRING | 1184 #undef RETURN_STRING |
1191 | 1185 |
1192 } // namespace media | 1186 } // namespace media |
OLD | NEW |