| 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 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 } | 475 } |
| 476 | 476 |
| 477 void MediaCodecPlayer::OnDemuxerDurationChanged( | 477 void MediaCodecPlayer::OnDemuxerDurationChanged( |
| 478 base::TimeDelta duration) { | 478 base::TimeDelta duration) { |
| 479 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 479 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 480 DVLOG(1) << __FUNCTION__ << " duration:" << duration; | 480 DVLOG(1) << __FUNCTION__ << " duration:" << duration; |
| 481 | 481 |
| 482 duration_ = duration; | 482 duration_ = duration; |
| 483 } | 483 } |
| 484 | 484 |
| 485 void MediaCodecPlayer::SetDecodersTimeCallbackForTests( |
| 486 DecodersTimeCallback cb) { |
| 487 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 488 decoders_time_cb_ = cb; |
| 489 } |
| 490 |
| 491 bool MediaCodecPlayer::IsPrerollingForTests(DemuxerStream::Type type) const { |
| 492 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 493 DCHECK(audio_decoder_ && video_decoder_); |
| 494 |
| 495 if (type == DemuxerStream::AUDIO) |
| 496 return audio_decoder_->IsPrerollingForTests(); |
| 497 else if (type == DemuxerStream::VIDEO) |
| 498 return video_decoder_->IsPrerollingForTests(); |
| 499 else |
| 500 return false; |
| 501 } |
| 502 |
| 485 // Events from Player, called on UI thread | 503 // Events from Player, called on UI thread |
| 486 | 504 |
| 487 void MediaCodecPlayer::OnMediaMetadataChanged(base::TimeDelta duration, | 505 void MediaCodecPlayer::OnMediaMetadataChanged(base::TimeDelta duration, |
| 488 const gfx::Size& video_size) { | 506 const gfx::Size& video_size) { |
| 489 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 507 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 490 | 508 |
| 491 if (duration != kNoTimestamp()) | 509 if (duration != kNoTimestamp()) |
| 492 metadata_cache_.duration = duration; | 510 metadata_cache_.duration = duration; |
| 493 | 511 |
| 494 if (!video_size.IsEmpty()) | 512 if (!video_size.IsEmpty()) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 | 566 |
| 549 if (HasVideo() && !video_decoder_->HasVideoSurface()) { | 567 if (HasVideo() && !video_decoder_->HasVideoSurface()) { |
| 550 SetState(kStateWaitingForSurface); | 568 SetState(kStateWaitingForSurface); |
| 551 return; | 569 return; |
| 552 } | 570 } |
| 553 | 571 |
| 554 SetState(kStatePlaying); | 572 SetState(kStatePlaying); |
| 555 StartPlaybackOrBrowserSeek(); | 573 StartPlaybackOrBrowserSeek(); |
| 556 } | 574 } |
| 557 | 575 |
| 576 void MediaCodecPlayer::OnPrerollDone() { |
| 577 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 578 DVLOG(1) << __FUNCTION__; |
| 579 |
| 580 DCHECK(interpolator_.interpolating()); |
| 581 |
| 582 StartStatus status = StartDecoders(interpolator_.GetInterpolatedTime()); |
| 583 if (status != kStartOk) |
| 584 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
| 585 } |
| 586 |
| 558 void MediaCodecPlayer::OnStopDone() { | 587 void MediaCodecPlayer::OnStopDone() { |
| 559 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 588 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 560 DVLOG(1) << __FUNCTION__; | 589 DVLOG(1) << __FUNCTION__; |
| 561 | 590 |
| 562 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) | 591 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) { |
| 592 DVLOG(1) << __FUNCTION__ << " both audio and video has to be stopped" |
| 593 << ", ignoring"; |
| 563 return; // Wait until other stream is stopped | 594 return; // Wait until other stream is stopped |
| 595 } |
| 564 | 596 |
| 565 // At this point decoder threads should not be running | 597 // At this point decoder threads should not be running |
| 566 if (interpolator_.interpolating()) | 598 if (interpolator_.interpolating()) |
| 567 interpolator_.StopInterpolating(); | 599 interpolator_.StopInterpolating(); |
| 568 | 600 |
| 569 base::TimeDelta seek_time; | 601 base::TimeDelta seek_time; |
| 570 switch (state_) { | 602 switch (state_) { |
| 571 case kStateStopping: { | 603 case kStateStopping: { |
| 572 base::TimeDelta seek_time = GetPendingSeek(); | 604 base::TimeDelta seek_time = GetPendingSeek(); |
| 573 if (seek_time != kNoTimestamp()) { | 605 if (seek_time != kNoTimestamp()) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 } | 661 } |
| 630 | 662 |
| 631 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type, | 663 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type, |
| 632 base::TimeDelta now_playing, | 664 base::TimeDelta now_playing, |
| 633 base::TimeDelta last_buffered) { | 665 base::TimeDelta last_buffered) { |
| 634 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 666 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 635 | 667 |
| 636 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing | 668 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing |
| 637 << "," << last_buffered << "]"; | 669 << "," << last_buffered << "]"; |
| 638 | 670 |
| 671 // For testing only: report time interval as we receive it from decoders |
| 672 // as an indication of what is being rendered. |
| 673 if (!decoders_time_cb_.is_null()) { |
| 674 ui_task_runner_->PostTask( |
| 675 FROM_HERE, |
| 676 base::Bind(decoders_time_cb_, type, now_playing, last_buffered)); |
| 677 } |
| 678 |
| 639 // I assume that audio stream cannot be added after we get configs by | 679 // I assume that audio stream cannot be added after we get configs by |
| 640 // OnDemuxerConfigsAvailable(), but that audio can finish early. | 680 // OnDemuxerConfigsAvailable(), but that audio can finish early. |
| 641 | 681 |
| 642 if (type == DemuxerStream::VIDEO) { | 682 if (type == DemuxerStream::VIDEO) { |
| 643 // Ignore video PTS if there is audio stream or if it's behind current | 683 // Ignore video PTS if there is audio stream or if it's behind current |
| 644 // time as set by audio stream. | 684 // time as set by audio stream. |
| 645 if (!AudioFinished() || now_playing < interpolator_.GetInterpolatedTime()) | 685 if (!AudioFinished() || |
| 686 (HasAudio() && now_playing < interpolator_.GetInterpolatedTime())) |
| 646 return; | 687 return; |
| 647 } | 688 } |
| 648 | 689 |
| 649 interpolator_.SetBounds(now_playing, last_buffered); | 690 interpolator_.SetBounds(now_playing, last_buffered); |
| 650 | 691 |
| 651 // Post to UI thread | 692 // Post to UI thread |
| 652 ui_task_runner_->PostTask(FROM_HERE, | 693 ui_task_runner_->PostTask(FROM_HERE, |
| 653 base::Bind(time_update_cb_, GetInterpolatedTime(), | 694 base::Bind(time_update_cb_, GetInterpolatedTime(), |
| 654 base::TimeTicks::Now())); | 695 base::TimeTicks::Now())); |
| 655 } | 696 } |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 break; | 826 break; |
| 786 case kStartOk: | 827 case kStartOk: |
| 787 break; | 828 break; |
| 788 } | 829 } |
| 789 } | 830 } |
| 790 | 831 |
| 791 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { | 832 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { |
| 792 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 833 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 793 DVLOG(1) << __FUNCTION__; | 834 DVLOG(1) << __FUNCTION__; |
| 794 | 835 |
| 795 bool do_audio = !AudioFinished(); | 836 // Configure all streams before the start since we may discover that browser |
| 796 bool do_video = !VideoFinished(); | 837 // seek is required. |
| 838 MediaCodecPlayer::StartStatus status = ConfigureDecoders(); |
| 839 if (status != kStartOk) |
| 840 return status; |
| 841 |
| 842 // At this point decoder threads should not be running. |
| 843 if (!interpolator_.interpolating()) |
| 844 interpolator_.StartInterpolating(); |
| 845 |
| 846 base::TimeDelta current_time = GetInterpolatedTime(); |
| 847 |
| 848 bool preroll_required = false; |
| 849 status = MaybePrerollDecoders(current_time, &preroll_required); |
| 850 if (preroll_required) |
| 851 return status; |
| 852 |
| 853 return StartDecoders(current_time); |
| 854 } |
| 855 |
| 856 MediaCodecPlayer::StartStatus MediaCodecPlayer::ConfigureDecoders() { |
| 857 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 858 DVLOG(1) << __FUNCTION__; |
| 859 |
| 860 const bool do_audio = !AudioFinished(); |
| 861 const bool do_video = !VideoFinished(); |
| 797 | 862 |
| 798 // If there is nothing to play, the state machine should determine this at the | 863 // If there is nothing to play, the state machine should determine this at the |
| 799 // prefetch state and never call this method. | 864 // prefetch state and never call this method. |
| 800 DCHECK(do_audio || do_video); | 865 DCHECK(do_audio || do_video); |
| 801 | 866 |
| 802 // Configure all streams before the start since we may discover that browser | 867 // Start with video: if browser seek is required it would |
| 803 // seek is required. Start with video: if browser seek is required it would | |
| 804 // not make sense to configure audio. | 868 // not make sense to configure audio. |
| 805 | 869 |
| 806 if (do_video) { | 870 if (do_video) { |
| 807 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); | 871 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); |
| 808 switch (status) { | 872 switch (status) { |
| 809 case MediaCodecDecoder::kConfigOk: | 873 case MediaCodecDecoder::kConfigOk: |
| 810 break; | 874 break; |
| 811 case MediaCodecDecoder::kConfigKeyFrameRequired: | 875 case MediaCodecDecoder::kConfigKeyFrameRequired: |
| 812 // TODO(timav): post a task or return the status? | 876 // TODO(timav): post a task or return the status? |
| 813 return kStartBrowserSeekRequired; | 877 return kStartBrowserSeekRequired; |
| 814 case MediaCodecDecoder::kConfigFailure: | 878 case MediaCodecDecoder::kConfigFailure: |
| 815 return kStartFailed; | 879 return kStartFailed; |
| 816 } | 880 } |
| 817 } | 881 } |
| 818 | 882 |
| 819 if (do_audio) { | 883 if (do_audio) { |
| 820 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); | 884 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); |
| 821 if (status != MediaCodecDecoder::kConfigOk) { | 885 if (status != MediaCodecDecoder::kConfigOk) { |
| 822 return kStartFailed; | 886 return kStartFailed; |
| 823 } | 887 } |
| 824 } | 888 } |
| 825 | 889 |
| 826 // At this point decoder threads should not be running. | 890 return kStartOk; |
| 827 if (!interpolator_.interpolating()) | 891 } |
| 828 interpolator_.StartInterpolating(); | |
| 829 | 892 |
| 830 base::TimeDelta current_time = GetInterpolatedTime(); | 893 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( |
| 894 base::TimeDelta current_time, |
| 895 bool* preroll_required) { |
| 896 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 897 DVLOG(1) << __FUNCTION__ << " current_time:" << current_time; |
| 831 | 898 |
| 832 if (do_audio) { | 899 // If requested, preroll is always done in the beginning of the playback, |
| 833 if (!audio_decoder_->Start(current_time)) { | 900 // after prefetch. The request might not happen at all though, in which case |
| 901 // we won't have prerolling phase. We need the prerolling when we (re)create |
| 902 // the decoder, because its configuration and initialization (getting input, |
| 903 // but not making output) can take time, and after the seek because there |
| 904 // could be some data to be skipped and there is again initialization after |
| 905 // the flush. |
| 906 |
| 907 int count = 0; |
| 908 const bool do_audio_preroll = audio_decoder_->NotCompletedAndNeedsPreroll(); |
| 909 if (do_audio_preroll) |
| 910 ++count; |
| 911 |
| 912 const bool do_video_preroll = video_decoder_->NotCompletedAndNeedsPreroll(); |
| 913 if (do_video_preroll) |
| 914 ++count; |
| 915 |
| 916 if (count == 0) { |
| 917 DVLOG(1) << __FUNCTION__ << ": preroll is not required, skipping"; |
| 918 *preroll_required = false; |
| 919 return kStartOk; |
| 920 } |
| 921 |
| 922 *preroll_required = true; |
| 923 |
| 924 DCHECK(count > 0); |
| 925 DCHECK(do_audio_preroll || do_video_preroll); |
| 926 |
| 927 DVLOG(1) << __FUNCTION__ << ": preroll for " << count << " stream(s)"; |
| 928 |
| 929 base::Closure preroll_cb = base::BarrierClosure( |
| 930 count, base::Bind(&MediaCodecPlayer::OnPrerollDone, media_weak_this_)); |
| 931 |
| 932 if (do_audio_preroll) { |
| 933 if (!audio_decoder_->Preroll(current_time, preroll_cb)) |
| 834 return kStartFailed; | 934 return kStartFailed; |
| 835 } | 935 } |
| 936 |
| 937 if (do_video_preroll) { |
| 938 if (!video_decoder_->Preroll(current_time, preroll_cb)) |
| 939 return kStartFailed; |
| 940 } |
| 941 |
| 942 return kStartOk; |
| 943 } |
| 944 |
| 945 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartDecoders( |
| 946 base::TimeDelta current_time) { |
| 947 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 948 DVLOG(1) << __FUNCTION__ << " current_time:" << current_time; |
| 949 |
| 950 if (!AudioFinished()) { |
| 951 if (!audio_decoder_->Start(current_time)) |
| 952 return kStartFailed; |
| 836 | 953 |
| 837 // Attach listener on UI thread | 954 // Attach listener on UI thread |
| 838 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); | 955 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); |
| 839 } | 956 } |
| 840 | 957 |
| 841 if (do_video) { | 958 if (!VideoFinished()) { |
| 842 if (!video_decoder_->Start(current_time)) { | 959 if (!video_decoder_->Start(current_time)) |
| 843 return kStartFailed; | 960 return kStartFailed; |
| 844 } | |
| 845 } | 961 } |
| 846 | 962 |
| 847 return kStartOk; | 963 return kStartOk; |
| 848 } | 964 } |
| 849 | 965 |
| 850 void MediaCodecPlayer::StopDecoders() { | 966 void MediaCodecPlayer::StopDecoders() { |
| 851 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 967 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 852 DVLOG(1) << __FUNCTION__; | 968 DVLOG(1) << __FUNCTION__; |
| 853 | 969 |
| 854 video_decoder_->SyncStop(); | 970 video_decoder_->SyncStop(); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 RETURN_STRING(kStateWaitingForSurface); | 1086 RETURN_STRING(kStateWaitingForSurface); |
| 971 RETURN_STRING(kStateWaitingForSeek); | 1087 RETURN_STRING(kStateWaitingForSeek); |
| 972 RETURN_STRING(kStateError); | 1088 RETURN_STRING(kStateError); |
| 973 } | 1089 } |
| 974 return nullptr; // crash early | 1090 return nullptr; // crash early |
| 975 } | 1091 } |
| 976 | 1092 |
| 977 #undef RETURN_STRING | 1093 #undef RETURN_STRING |
| 978 | 1094 |
| 979 } // namespace media | 1095 } // namespace media |
| OLD | NEW |