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

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: Added more unit tests 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 } 605 }
602 606
603 SetState(kStatePlaying); 607 SetState(kStatePlaying);
604 StartPlaybackOrBrowserSeek(); 608 StartPlaybackOrBrowserSeek();
605 } 609 }
606 610
607 void MediaCodecPlayer::OnPrerollDone() { 611 void MediaCodecPlayer::OnPrerollDone() {
608 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 612 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
609 DVLOG(1) << __FUNCTION__; 613 DVLOG(1) << __FUNCTION__;
610 614
615 if (state_ != kStatePlaying) {
616 DVLOG(1) << __FUNCTION__ << ": in state " << AsString(state_)
617 << ", ignoring";
618 return;
619 }
620
611 StartStatus status = StartDecoders(); 621 StartStatus status = StartDecoders();
612 if (status != kStartOk) 622 if (status != kStartOk)
613 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); 623 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_);
614 } 624 }
615 625
616 void MediaCodecPlayer::OnDecoderDrained(DemuxerStream::Type type) { 626 void MediaCodecPlayer::OnDecoderDrained(DemuxerStream::Type type) {
617 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 627 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
618 DVLOG(1) << __FUNCTION__ << " " << type; 628 DVLOG(1) << __FUNCTION__ << " " << type;
619 629
620 // We expect that OnStopDone() comes next. 630 // We expect that OnStopDone() comes next.
621 631
622 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO); 632 DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO);
623 DCHECK(state_ == kStatePlaying || state_ == kStateStopping) 633 DCHECK(state_ == kStatePlaying || state_ == kStateStopping)
624 << __FUNCTION__ << " illegal state: " << AsString(state_); 634 << __FUNCTION__ << " illegal state: " << AsString(state_);
625 635
626 switch (state_) { 636 switch (state_) {
627 case kStatePlaying: 637 case kStatePlaying:
628 SetState(kStateStopping); 638 SetState(kStateStopping);
629 SetPendingStart(true); 639 SetPendingStart(true);
630 640
631 if (type == DemuxerStream::AUDIO && !VideoFinished()) { 641 if (type == DemuxerStream::AUDIO && !VideoFinished()) {
632 DVLOG(1) << __FUNCTION__ << " requesting to stop video"; 642 DVLOG(1) << __FUNCTION__ << " requesting to stop video";
633 video_decoder_->SetDecodingUntilOutputIsPresent();
634 video_decoder_->RequestToStop(); 643 video_decoder_->RequestToStop();
635 } else if (type == DemuxerStream::VIDEO && !AudioFinished()) { 644 } else if (type == DemuxerStream::VIDEO && !AudioFinished()) {
636 DVLOG(1) << __FUNCTION__ << " requesting to stop audio"; 645 DVLOG(1) << __FUNCTION__ << " requesting to stop audio";
637 audio_decoder_->SetDecodingUntilOutputIsPresent();
638 audio_decoder_->RequestToStop(); 646 audio_decoder_->RequestToStop();
639 } 647 }
640 break; 648 break;
641 649
642 case kStateStopping:
643 if (type == DemuxerStream::AUDIO && !VideoFinished())
644 video_decoder_->SetDecodingUntilOutputIsPresent();
645 else if (type == DemuxerStream::VIDEO && !AudioFinished())
646 audio_decoder_->SetDecodingUntilOutputIsPresent();
647 break;
648
649 default: 650 default:
650 NOTREACHED();
651 break; 651 break;
652 } 652 }
653 } 653 }
654 654
655 void MediaCodecPlayer::OnStopDone(DemuxerStream::Type type) { 655 void MediaCodecPlayer::OnStopDone(DemuxerStream::Type type) {
656 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 656 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
657 DVLOG(1) << __FUNCTION__ << " " << type 657 DVLOG(1) << __FUNCTION__ << " " << type
658 << " interpolated time:" << GetInterpolatedTime(); 658 << " interpolated time:" << GetInterpolatedTime();
659 659
660 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) { 660 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) {
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 } 956 }
957 } 957 }
958 958
959 return kStartOk; 959 return kStartOk;
960 } 960 }
961 961
962 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( 962 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders(
963 bool* preroll_required) { 963 bool* preroll_required) {
964 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 964 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
965 965
966 base::TimeDelta current_time = GetInterpolatedTime(); 966 DVLOG(1) << __FUNCTION__ << " current_time:" << GetInterpolatedTime();
967
968 DVLOG(1) << __FUNCTION__ << " current_time:" << current_time;
969 967
970 // If requested, preroll is always done in the beginning of the playback, 968 // If requested, preroll is always done in the beginning of the playback,
971 // after prefetch. The request might not happen at all though, in which case 969 // after prefetch. The request might not happen at all though, in which case
972 // we won't have prerolling phase. We need the prerolling when we (re)create 970 // we won't have prerolling phase. We need the prerolling when we (re)create
973 // the decoder, because its configuration and initialization (getting input, 971 // the decoder, because its configuration and initialization (getting input,
974 // but not making output) can take time, and after the seek because there 972 // but not making output) can take time, and after the seek because there
975 // could be some data to be skipped and there is again initialization after 973 // could be some data to be skipped and there is again initialization after
976 // the flush. 974 // the flush.
977 975
978 *preroll_required = false; 976 *preroll_required = false;
979 977
980 int count = 0; 978 int count = 0;
981 const bool do_audio_preroll = audio_decoder_->NotCompletedAndNeedsPreroll(); 979 const bool do_audio = audio_decoder_->NotCompletedAndNeedsPreroll();
982 if (do_audio_preroll) 980 if (do_audio)
983 ++count; 981 ++count;
984 982
985 const bool do_video_preroll = video_decoder_->NotCompletedAndNeedsPreroll(); 983 const bool do_video = video_decoder_->NotCompletedAndNeedsPreroll();
986 if (do_video_preroll) 984 if (do_video)
987 ++count; 985 ++count;
988 986
989 if (count == 0) { 987 if (count == 0) {
990 DVLOG(1) << __FUNCTION__ << ": preroll is not required, skipping"; 988 DVLOG(1) << __FUNCTION__ << ": preroll is not required, skipping";
991 return kStartOk; 989 return kStartOk;
992 } 990 }
993 991
994 *preroll_required = true; 992 *preroll_required = true;
995 993
996 DCHECK(count > 0); 994 DCHECK(count > 0);
997 DCHECK(do_audio_preroll || do_video_preroll); 995 DCHECK(do_audio || do_video);
998 996
999 DVLOG(1) << __FUNCTION__ << ": preroll for " << count << " stream(s)"; 997 DVLOG(1) << __FUNCTION__ << ": preroll for " << count << " stream(s)";
1000 998
1001 base::Closure preroll_cb = base::BarrierClosure( 999 base::Closure preroll_cb = base::BarrierClosure(
1002 count, base::Bind(&MediaCodecPlayer::OnPrerollDone, media_weak_this_)); 1000 count, base::Bind(&MediaCodecPlayer::OnPrerollDone, media_weak_this_));
1003 1001
1004 if (do_audio_preroll) { 1002 if (do_audio) {
qinmin 2015/09/03 05:30:04 simply if (do_audio && !audio_decoder_->Preroll(p
Tima Vaisburd 2015/09/03 19:55:27 Done.
1005 if (!audio_decoder_->Preroll(current_time, preroll_cb)) 1003 if (!audio_decoder_->Preroll(preroll_cb))
1006 return kStartFailed; 1004 return kStartFailed;
1007 } 1005 }
1008 1006
1009 if (do_video_preroll) { 1007 if (do_video) {
qinmin 2015/09/03 05:30:04 ditto
Tima Vaisburd 2015/09/03 19:55:27 Done.
1010 if (!video_decoder_->Preroll(current_time, preroll_cb)) 1008 if (!video_decoder_->Preroll(preroll_cb))
1011 return kStartFailed; 1009 return kStartFailed;
1012 } 1010 }
1013 1011
1014 return kStartOk; 1012 return kStartOk;
1015 } 1013 }
1016 1014
1017 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartDecoders() { 1015 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartDecoders() {
1018 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 1016 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
1019 1017
1020 if (!interpolator_.interpolating()) 1018 if (!interpolator_.interpolating())
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 RETURN_STRING(kStateWaitingForSurface); 1168 RETURN_STRING(kStateWaitingForSurface);
1171 RETURN_STRING(kStateWaitingForSeek); 1169 RETURN_STRING(kStateWaitingForSeek);
1172 RETURN_STRING(kStateError); 1170 RETURN_STRING(kStateError);
1173 } 1171 }
1174 return nullptr; // crash early 1172 return nullptr; // crash early
1175 } 1173 }
1176 1174
1177 #undef RETURN_STRING 1175 #undef RETURN_STRING
1178 1176
1179 } // namespace media 1177 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698