Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Side by Side Diff: media/base/android/media_codec_player.cc

Issue 1312103006: MediaCodecPlayer - preroll and reconfiguration fixes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-reconfig
Patch Set: Rebased Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/base/android/media_codec_decoder.cc ('k') | media/base/android/media_codec_player_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698