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

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

Issue 1254293003: MediaCodecPlayer implementation (stage 4 - preroll) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mtplayer-browserseek
Patch Set: Added unit tests that check A/V sync after preroll Created 5 years, 4 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 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 425
426 // Restrict the current time to be equal to seek_time 426 // Restrict the current time to be equal to seek_time
427 // for the next StartPlaybackDecoders() call. 427 // for the next StartPlaybackDecoders() call.
428 428
429 base::TimeDelta seek_time = seek_info_->is_browser_seek 429 base::TimeDelta seek_time = seek_info_->is_browser_seek
430 ? actual_browser_seek_time 430 ? actual_browser_seek_time
431 : seek_info_->seek_time; 431 : seek_info_->seek_time;
432 432
433 interpolator_.SetBounds(seek_time, seek_time); 433 interpolator_.SetBounds(seek_time, seek_time);
434 audio_decoder_->SetBaseTimestamp(seek_time); 434 audio_decoder_->SetBaseTimestamp(seek_time);
435 audio_decoder_->SetNeedsPreroll(true);
436 video_decoder_->SetNeedsPreroll(true);
435 437
436 // The Flush() might set the state to kStateError. 438 // The Flush() might set the state to kStateError.
437 if (state_ == kStateError) { 439 if (state_ == kStateError) {
438 // Notify the Renderer. 440 // Notify the Renderer.
439 if (!seek_info_->is_browser_seek) 441 if (!seek_info_->is_browser_seek)
440 ui_task_runner_->PostTask(FROM_HERE, 442 ui_task_runner_->PostTask(FROM_HERE,
441 base::Bind(seek_done_cb_, seek_time)); 443 base::Bind(seek_done_cb_, seek_time));
442 444
443 seek_info_.reset(); 445 seek_info_.reset();
444 return; 446 return;
(...skipping 30 matching lines...) Expand all
475 } 477 }
476 478
477 void MediaCodecPlayer::OnDemuxerDurationChanged( 479 void MediaCodecPlayer::OnDemuxerDurationChanged(
478 base::TimeDelta duration) { 480 base::TimeDelta duration) {
479 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 481 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
480 DVLOG(1) << __FUNCTION__ << " duration:" << duration; 482 DVLOG(1) << __FUNCTION__ << " duration:" << duration;
481 483
482 duration_ = duration; 484 duration_ = duration;
483 } 485 }
484 486
487 void MediaCodecPlayer::SetDecodersTimeCallbackForTests(
488 DecodersTimeCallback cb) {
489 DCHECK(ui_task_runner_->BelongsToCurrentThread());
490 decoders_time_cb_ = cb;
491 }
492
493 bool MediaCodecPlayer::IsPrerollingForTests(DemuxerStream::Type type) const {
494 DCHECK(ui_task_runner_->BelongsToCurrentThread());
495 DCHECK(audio_decoder_ && video_decoder_);
496
497 if (type == DemuxerStream::AUDIO)
498 return audio_decoder_->IsPrerollingForTests();
499 else if (type == DemuxerStream::VIDEO)
500 return video_decoder_->IsPrerollingForTests();
501 else
502 return false;
503 }
504
485 // Events from Player, called on UI thread 505 // Events from Player, called on UI thread
486 506
487 void MediaCodecPlayer::OnMediaMetadataChanged(base::TimeDelta duration, 507 void MediaCodecPlayer::OnMediaMetadataChanged(base::TimeDelta duration,
488 const gfx::Size& video_size) { 508 const gfx::Size& video_size) {
489 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 509 DCHECK(ui_task_runner_->BelongsToCurrentThread());
490 510
491 if (duration != kNoTimestamp()) 511 if (duration != kNoTimestamp())
492 metadata_cache_.duration = duration; 512 metadata_cache_.duration = duration;
493 513
494 if (!video_size.IsEmpty()) 514 if (!video_size.IsEmpty())
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 568
549 if (HasVideo() && !video_decoder_->HasVideoSurface()) { 569 if (HasVideo() && !video_decoder_->HasVideoSurface()) {
550 SetState(kStateWaitingForSurface); 570 SetState(kStateWaitingForSurface);
551 return; 571 return;
552 } 572 }
553 573
554 SetState(kStatePlaying); 574 SetState(kStatePlaying);
555 StartPlaybackOrBrowserSeek(); 575 StartPlaybackOrBrowserSeek();
556 } 576 }
557 577
578 void MediaCodecPlayer::OnPrerollDone() {
579 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
580 DVLOG(1) << __FUNCTION__;
581
582 if (!(audio_decoder_->IsPrerollDone() && video_decoder_->IsPrerollDone())) {
583 DVLOG(1) << __FUNCTION__ << " both audio and video needs to be done"
584 << " prerolling, ignoring";
585 return; // Wait until both streams are done prerolling.
586 }
587
588 if (!AudioFinished())
589 audio_decoder_->ResumeAfterPreroll();
590 if (!VideoFinished())
591 video_decoder_->ResumeAfterPreroll();
592 }
593
558 void MediaCodecPlayer::OnStopDone() { 594 void MediaCodecPlayer::OnStopDone() {
559 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 595 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
560 DVLOG(1) << __FUNCTION__; 596 DVLOG(1) << __FUNCTION__;
561 597
562 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) 598 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) {
599 DVLOG(1) << __FUNCTION__ << " both audio and video has to be stopped"
600 << ", ignoring";
563 return; // Wait until other stream is stopped 601 return; // Wait until other stream is stopped
602 }
564 603
565 // At this point decoder threads should not be running 604 // At this point decoder threads should not be running
566 if (interpolator_.interpolating()) 605 if (interpolator_.interpolating())
567 interpolator_.StopInterpolating(); 606 interpolator_.StopInterpolating();
568 607
569 base::TimeDelta seek_time; 608 base::TimeDelta seek_time;
570 switch (state_) { 609 switch (state_) {
571 case kStateStopping: { 610 case kStateStopping: {
572 base::TimeDelta seek_time = GetPendingSeek(); 611 base::TimeDelta seek_time = GetPendingSeek();
573 if (seek_time != kNoTimestamp()) { 612 if (seek_time != kNoTimestamp()) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 } 668 }
630 669
631 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type, 670 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type,
632 base::TimeDelta now_playing, 671 base::TimeDelta now_playing,
633 base::TimeDelta last_buffered) { 672 base::TimeDelta last_buffered) {
634 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 673 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
635 674
636 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing 675 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing
637 << "," << last_buffered << "]"; 676 << "," << last_buffered << "]";
638 677
678 // For testing only: report time interval as we receive it from decoders
679 // as an indication of what is being rendered.
680 if (!decoders_time_cb_.is_null()) {
681 ui_task_runner_->PostTask(
682 FROM_HERE,
683 base::Bind(decoders_time_cb_, type, now_playing, last_buffered));
684 }
685
639 // I assume that audio stream cannot be added after we get configs by 686 // I assume that audio stream cannot be added after we get configs by
640 // OnDemuxerConfigsAvailable(), but that audio can finish early. 687 // OnDemuxerConfigsAvailable(), but that audio can finish early.
641 688
642 if (type == DemuxerStream::VIDEO) { 689 if (type == DemuxerStream::VIDEO) {
643 // Ignore video PTS if there is audio stream or if it's behind current 690 // Ignore video PTS if there is audio stream or if it's behind current
644 // time as set by audio stream. 691 // time as set by audio stream.
645 if (!AudioFinished() || now_playing < interpolator_.GetInterpolatedTime()) 692 if (!AudioFinished() ||
693 (HasAudio() && now_playing < interpolator_.GetInterpolatedTime()))
646 return; 694 return;
647 } 695 }
648 696
649 interpolator_.SetBounds(now_playing, last_buffered); 697 interpolator_.SetBounds(now_playing, last_buffered);
650 698
651 // Post to UI thread 699 // Post to UI thread
652 ui_task_runner_->PostTask(FROM_HERE, 700 ui_task_runner_->PostTask(FROM_HERE,
653 base::Bind(time_update_cb_, GetInterpolatedTime(), 701 base::Bind(time_update_cb_, GetInterpolatedTime(),
654 base::TimeTicks::Now())); 702 base::TimeTicks::Now()));
655 } 703 }
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
915 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); 963 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
916 DVLOG(1) << __FUNCTION__; 964 DVLOG(1) << __FUNCTION__;
917 965
918 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); 966 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_);
919 967
920 audio_decoder_.reset(new MediaCodecAudioDecoder( 968 audio_decoder_.reset(new MediaCodecAudioDecoder(
921 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, 969 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData,
922 media_weak_this_, DemuxerStream::AUDIO), 970 media_weak_this_, DemuxerStream::AUDIO),
923 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, 971 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_,
924 DemuxerStream::AUDIO), 972 DemuxerStream::AUDIO),
973 base::Bind(&MediaCodecPlayer::OnPrerollDone, media_weak_this_),
925 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), 974 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_),
926 internal_error_cb_, 975 internal_error_cb_,
927 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, 976 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_,
928 DemuxerStream::AUDIO))); 977 DemuxerStream::AUDIO)));
929 978
930 video_decoder_.reset(new MediaCodecVideoDecoder( 979 video_decoder_.reset(new MediaCodecVideoDecoder(
931 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, 980 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData,
932 media_weak_this_, DemuxerStream::VIDEO), 981 media_weak_this_, DemuxerStream::VIDEO),
933 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, 982 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_,
934 DemuxerStream::VIDEO), 983 DemuxerStream::VIDEO),
984 base::Bind(&MediaCodecPlayer::OnPrerollDone, media_weak_this_),
935 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), 985 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_),
936 internal_error_cb_, 986 internal_error_cb_,
937 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, 987 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_,
938 DemuxerStream::VIDEO), 988 DemuxerStream::VIDEO),
939 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), 989 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_),
940 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); 990 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_)));
941 } 991 }
942 992
943 bool MediaCodecPlayer::AudioFinished() const { 993 bool MediaCodecPlayer::AudioFinished() const {
944 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); 994 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream();
(...skipping 25 matching lines...) Expand all
970 RETURN_STRING(kStateWaitingForSurface); 1020 RETURN_STRING(kStateWaitingForSurface);
971 RETURN_STRING(kStateWaitingForSeek); 1021 RETURN_STRING(kStateWaitingForSeek);
972 RETURN_STRING(kStateError); 1022 RETURN_STRING(kStateError);
973 } 1023 }
974 return nullptr; // crash early 1024 return nullptr; // crash early
975 } 1025 }
976 1026
977 #undef RETURN_STRING 1027 #undef RETURN_STRING
978 1028
979 } // namespace media 1029 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698