OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_source_player.h" | 5 #include "media/base/android/media_source_player.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 scoped_ptr<DemuxerAndroid> demuxer) | 66 scoped_ptr<DemuxerAndroid> demuxer) |
67 : MediaPlayerAndroid(player_id, manager), | 67 : MediaPlayerAndroid(player_id, manager), |
68 demuxer_(demuxer.Pass()), | 68 demuxer_(demuxer.Pass()), |
69 pending_event_(NO_EVENT_PENDING), | 69 pending_event_(NO_EVENT_PENDING), |
70 width_(0), | 70 width_(0), |
71 height_(0), | 71 height_(0), |
72 audio_codec_(kUnknownAudioCodec), | 72 audio_codec_(kUnknownAudioCodec), |
73 video_codec_(kUnknownVideoCodec), | 73 video_codec_(kUnknownVideoCodec), |
74 num_channels_(0), | 74 num_channels_(0), |
75 sampling_rate_(0), | 75 sampling_rate_(0), |
76 audio_finished_(true), | 76 reached_audio_eos_(false), |
77 video_finished_(true), | 77 reached_video_eos_(false), |
78 playing_(false), | 78 playing_(false), |
79 is_audio_encrypted_(false), | 79 is_audio_encrypted_(false), |
80 is_video_encrypted_(false), | 80 is_video_encrypted_(false), |
81 volume_(-1.0), | 81 volume_(-1.0), |
82 clock_(&default_tick_clock_), | 82 clock_(&default_tick_clock_), |
83 next_video_data_is_iframe_(true), | 83 next_video_data_is_iframe_(true), |
84 doing_browser_seek_(false), | 84 doing_browser_seek_(false), |
85 pending_seek_(false), | 85 pending_seek_(false), |
86 reconfig_audio_decoder_(false), | 86 reconfig_audio_decoder_(false), |
87 reconfig_video_decoder_(false), | 87 reconfig_video_decoder_(false), |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 // Create decoder jobs if they are not created | 311 // Create decoder jobs if they are not created |
312 ConfigureAudioDecoderJob(); | 312 ConfigureAudioDecoderJob(); |
313 ConfigureVideoDecoderJob(); | 313 ConfigureVideoDecoderJob(); |
314 | 314 |
315 // If one of the decoder job is not ready, do nothing. | 315 // If one of the decoder job is not ready, do nothing. |
316 if ((HasAudio() && !audio_decoder_job_) || | 316 if ((HasAudio() && !audio_decoder_job_) || |
317 (HasVideo() && !video_decoder_job_)) { | 317 (HasVideo() && !video_decoder_job_)) { |
318 return; | 318 return; |
319 } | 319 } |
320 | 320 |
321 audio_finished_ = false; | |
322 video_finished_ = false; | |
323 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | 321 SetPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
324 ProcessPendingEvents(); | 322 ProcessPendingEvents(); |
325 } | 323 } |
326 | 324 |
327 void MediaSourcePlayer::OnDemuxerConfigsAvailable( | 325 void MediaSourcePlayer::OnDemuxerConfigsAvailable( |
328 const DemuxerConfigs& configs) { | 326 const DemuxerConfigs& configs) { |
329 DVLOG(1) << __FUNCTION__; | 327 DVLOG(1) << __FUNCTION__; |
330 duration_ = base::TimeDelta::FromMilliseconds(configs.duration_ms); | 328 duration_ = base::TimeDelta::FromMilliseconds(configs.duration_ms); |
331 clock_.SetDuration(duration_); | 329 clock_.SetDuration(duration_); |
332 | 330 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 // A browser seek must not jump into the past. Ideally, it seeks to the | 442 // A browser seek must not jump into the past. Ideally, it seeks to the |
445 // requested time, but it might jump into the future. | 443 // requested time, but it might jump into the future. |
446 DCHECK(actual_browser_seek_time >= GetCurrentTime()); | 444 DCHECK(actual_browser_seek_time >= GetCurrentTime()); |
447 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " | 445 DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " |
448 << actual_browser_seek_time.InSecondsF(); | 446 << actual_browser_seek_time.InSecondsF(); |
449 clock_.SetTime(actual_browser_seek_time, actual_browser_seek_time); | 447 clock_.SetTime(actual_browser_seek_time, actual_browser_seek_time); |
450 if (audio_timestamp_helper_) | 448 if (audio_timestamp_helper_) |
451 audio_timestamp_helper_->SetBaseTimestamp(actual_browser_seek_time); | 449 audio_timestamp_helper_->SetBaseTimestamp(actual_browser_seek_time); |
452 } | 450 } |
453 | 451 |
| 452 reached_audio_eos_ = false; |
| 453 reached_video_eos_ = false; |
| 454 |
454 base::TimeDelta current_time = GetCurrentTime(); | 455 base::TimeDelta current_time = GetCurrentTime(); |
455 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| | 456 // TODO(qinmin): Simplify the logic by using |start_presentation_timestamp_| |
456 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| | 457 // to preroll media decoder jobs. Currently |start_presentation_timestamp_| |
457 // is calculated from decoder output, while preroll relies on the access | 458 // is calculated from decoder output, while preroll relies on the access |
458 // unit's timestamp. There are some differences between the two. | 459 // unit's timestamp. There are some differences between the two. |
459 preroll_timestamp_ = current_time; | 460 preroll_timestamp_ = current_time; |
460 if (audio_decoder_job_) | 461 if (audio_decoder_job_) |
461 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); | 462 audio_decoder_job_->BeginPrerolling(preroll_timestamp_); |
462 if (video_decoder_job_) | 463 if (video_decoder_job_) |
463 video_decoder_job_->BeginPrerolling(preroll_timestamp_); | 464 video_decoder_job_->BeginPrerolling(preroll_timestamp_); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 | 524 |
524 // Return early if we can't successfully configure a new video decoder job | 525 // Return early if we can't successfully configure a new video decoder job |
525 // yet, except continue processing other pending events if |surface_| is | 526 // yet, except continue processing other pending events if |surface_| is |
526 // empty. | 527 // empty. |
527 if (HasVideo() && !video_decoder_job_ && !surface_.IsEmpty()) | 528 if (HasVideo() && !video_decoder_job_ && !surface_.IsEmpty()) |
528 return; | 529 return; |
529 } | 530 } |
530 | 531 |
531 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { | 532 if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { |
532 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; | 533 DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; |
533 int count = (audio_decoder_job_ ? 1 : 0) + (video_decoder_job_ ? 1 : 0); | 534 DCHECK(audio_decoder_job_ || AudioFinished()); |
| 535 DCHECK(video_decoder_job_ || VideoFinished()); |
534 | 536 |
| 537 int count = (AudioFinished() ? 0 : 1) + (VideoFinished() ? 0 : 1); |
| 538 |
| 539 // It is possible that all streams have finished decode, yet starvation |
| 540 // occurred during the last stream's EOS decode. In this case, prefetch is a |
| 541 // no-op. |
| 542 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
| 543 if (count == 0) |
| 544 return; |
| 545 |
| 546 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); |
535 base::Closure barrier = BarrierClosure(count, base::Bind( | 547 base::Closure barrier = BarrierClosure(count, base::Bind( |
536 &MediaSourcePlayer::OnPrefetchDone, weak_this_.GetWeakPtr())); | 548 &MediaSourcePlayer::OnPrefetchDone, weak_this_.GetWeakPtr())); |
537 | 549 |
538 if (audio_decoder_job_) | 550 if (!AudioFinished()) |
539 audio_decoder_job_->Prefetch(barrier); | 551 audio_decoder_job_->Prefetch(barrier); |
540 | 552 |
541 if (video_decoder_job_) | 553 if (!VideoFinished()) |
542 video_decoder_job_->Prefetch(barrier); | 554 video_decoder_job_->Prefetch(barrier); |
543 | 555 |
544 SetPendingEvent(PREFETCH_DONE_EVENT_PENDING); | |
545 ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); | |
546 return; | 556 return; |
547 } | 557 } |
548 | 558 |
549 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); | 559 DCHECK_EQ(pending_event_, NO_EVENT_PENDING); |
550 | 560 |
551 // Now that all pending events have been handled, resume decoding if we are | 561 // Now that all pending events have been handled, resume decoding if we are |
552 // still playing. | 562 // still playing. |
553 if (playing_) | 563 if (playing_) |
554 StartInternal(); | 564 StartInternal(); |
555 } | 565 } |
(...skipping 27 matching lines...) Expand all Loading... |
583 if (is_clock_manager) | 593 if (is_clock_manager) |
584 decoder_starvation_callback_.Cancel(); | 594 decoder_starvation_callback_.Cancel(); |
585 | 595 |
586 if (status == MEDIA_CODEC_ERROR) { | 596 if (status == MEDIA_CODEC_ERROR) { |
587 DVLOG(1) << __FUNCTION__ << " : decode error"; | 597 DVLOG(1) << __FUNCTION__ << " : decode error"; |
588 Release(); | 598 Release(); |
589 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); | 599 manager()->OnError(player_id(), MEDIA_ERROR_DECODE); |
590 return; | 600 return; |
591 } | 601 } |
592 | 602 |
| 603 DCHECK(!IsEventPending(PREFETCH_DONE_EVENT_PENDING)); |
| 604 |
| 605 // Let |SEEK_EVENT_PENDING| (the highest priority event outside of |
| 606 // |PREFETCH_DONE_EVENT_PENDING|) preempt output EOS detection here. Process |
| 607 // any other pending events only after handling EOS detection. |
| 608 if (IsEventPending(SEEK_EVENT_PENDING)) { |
| 609 ProcessPendingEvents(); |
| 610 return; |
| 611 } |
| 612 |
| 613 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
| 614 PlaybackCompleted(is_audio); |
| 615 |
593 if (pending_event_ != NO_EVENT_PENDING) { | 616 if (pending_event_ != NO_EVENT_PENDING) { |
594 ProcessPendingEvents(); | 617 ProcessPendingEvents(); |
595 return; | 618 return; |
596 } | 619 } |
597 | 620 |
598 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) { | 621 if (status == MEDIA_CODEC_OUTPUT_END_OF_STREAM) |
599 PlaybackCompleted(is_audio); | |
600 return; | 622 return; |
601 } | |
602 | 623 |
603 if (status == MEDIA_CODEC_OK && is_clock_manager && | 624 if (status == MEDIA_CODEC_OK && is_clock_manager && |
604 presentation_timestamp != kNoTimestamp()) { | 625 presentation_timestamp != kNoTimestamp()) { |
605 UpdateTimestamps(presentation_timestamp, audio_output_bytes); | 626 UpdateTimestamps(presentation_timestamp, audio_output_bytes); |
606 } | 627 } |
607 | 628 |
608 if (!playing_) { | 629 if (!playing_) { |
609 if (is_clock_manager) | 630 if (is_clock_manager) |
610 clock_.Pause(); | 631 clock_.Pause(); |
611 return; | 632 return; |
(...skipping 24 matching lines...) Expand all Loading... |
636 DecodeMoreAudio(); | 657 DecodeMoreAudio(); |
637 return; | 658 return; |
638 } | 659 } |
639 | 660 |
640 DecodeMoreVideo(); | 661 DecodeMoreVideo(); |
641 } | 662 } |
642 | 663 |
643 void MediaSourcePlayer::DecodeMoreAudio() { | 664 void MediaSourcePlayer::DecodeMoreAudio() { |
644 DVLOG(1) << __FUNCTION__; | 665 DVLOG(1) << __FUNCTION__; |
645 DCHECK(!audio_decoder_job_->is_decoding()); | 666 DCHECK(!audio_decoder_job_->is_decoding()); |
| 667 DCHECK(!AudioFinished()); |
646 | 668 |
647 if (audio_decoder_job_->Decode( | 669 if (audio_decoder_job_->Decode( |
648 start_time_ticks_, start_presentation_timestamp_, base::Bind( | 670 start_time_ticks_, start_presentation_timestamp_, base::Bind( |
649 &MediaSourcePlayer::MediaDecoderCallback, | 671 &MediaSourcePlayer::MediaDecoderCallback, |
650 weak_this_.GetWeakPtr(), true))) { | 672 weak_this_.GetWeakPtr(), true))) { |
651 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", | 673 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreAudio", |
652 audio_decoder_job_.get()); | 674 audio_decoder_job_.get()); |
653 return; | 675 return; |
654 } | 676 } |
655 | 677 |
656 // Failed to start the next decode. | 678 // Failed to start the next decode. |
657 // Wait for demuxer ready message. | 679 // Wait for demuxer ready message. |
658 DCHECK(!reconfig_audio_decoder_); | 680 DCHECK(!reconfig_audio_decoder_); |
659 reconfig_audio_decoder_ = true; | 681 reconfig_audio_decoder_ = true; |
660 | 682 |
661 // Config change may have just been detected on the other stream. If so, | 683 // Config change may have just been detected on the other stream. If so, |
662 // don't send a duplicate demuxer config request. | 684 // don't send a duplicate demuxer config request. |
663 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { | 685 if (IsEventPending(CONFIG_CHANGE_EVENT_PENDING)) { |
664 DCHECK(reconfig_video_decoder_); | 686 DCHECK(reconfig_video_decoder_); |
665 return; | 687 return; |
666 } | 688 } |
667 | 689 |
668 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | 690 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); |
669 ProcessPendingEvents(); | 691 ProcessPendingEvents(); |
670 } | 692 } |
671 | 693 |
672 void MediaSourcePlayer::DecodeMoreVideo() { | 694 void MediaSourcePlayer::DecodeMoreVideo() { |
673 DVLOG(1) << __FUNCTION__; | 695 DVLOG(1) << __FUNCTION__; |
674 DCHECK(!video_decoder_job_->is_decoding()); | 696 DCHECK(!video_decoder_job_->is_decoding()); |
| 697 DCHECK(!VideoFinished()); |
675 | 698 |
676 if (video_decoder_job_->Decode( | 699 if (video_decoder_job_->Decode( |
677 start_time_ticks_, start_presentation_timestamp_, base::Bind( | 700 start_time_ticks_, start_presentation_timestamp_, base::Bind( |
678 &MediaSourcePlayer::MediaDecoderCallback, | 701 &MediaSourcePlayer::MediaDecoderCallback, |
679 weak_this_.GetWeakPtr(), false))) { | 702 weak_this_.GetWeakPtr(), false))) { |
680 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", | 703 TRACE_EVENT_ASYNC_BEGIN0("media", "MediaSourcePlayer::DecodeMoreVideo", |
681 video_decoder_job_.get()); | 704 video_decoder_job_.get()); |
682 return; | 705 return; |
683 } | 706 } |
684 | 707 |
(...skipping 14 matching lines...) Expand all Loading... |
699 return; | 722 return; |
700 } | 723 } |
701 | 724 |
702 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); | 725 SetPendingEvent(CONFIG_CHANGE_EVENT_PENDING); |
703 ProcessPendingEvents(); | 726 ProcessPendingEvents(); |
704 } | 727 } |
705 | 728 |
706 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { | 729 void MediaSourcePlayer::PlaybackCompleted(bool is_audio) { |
707 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; | 730 DVLOG(1) << __FUNCTION__ << "(" << is_audio << ")"; |
708 if (is_audio) | 731 if (is_audio) |
709 audio_finished_ = true; | 732 reached_audio_eos_ = true; |
710 else | 733 else |
711 video_finished_ = true; | 734 reached_video_eos_ = true; |
712 | 735 |
713 if ((!HasAudio() || audio_finished_) && (!HasVideo() || video_finished_)) { | 736 if (AudioFinished() && VideoFinished()) { |
714 playing_ = false; | 737 playing_ = false; |
715 clock_.Pause(); | 738 clock_.Pause(); |
716 start_time_ticks_ = base::TimeTicks(); | 739 start_time_ticks_ = base::TimeTicks(); |
717 manager()->OnPlaybackComplete(player_id()); | 740 manager()->OnPlaybackComplete(player_id()); |
718 } | 741 } |
719 } | 742 } |
720 | 743 |
721 void MediaSourcePlayer::ClearDecodingData() { | 744 void MediaSourcePlayer::ClearDecodingData() { |
722 DVLOG(1) << __FUNCTION__; | 745 DVLOG(1) << __FUNCTION__; |
723 if (audio_decoder_job_) | 746 if (audio_decoder_job_) |
724 audio_decoder_job_->Flush(); | 747 audio_decoder_job_->Flush(); |
725 if (video_decoder_job_) | 748 if (video_decoder_job_) |
726 video_decoder_job_->Flush(); | 749 video_decoder_job_->Flush(); |
727 start_time_ticks_ = base::TimeTicks(); | 750 start_time_ticks_ = base::TimeTicks(); |
728 } | 751 } |
729 | 752 |
730 bool MediaSourcePlayer::HasVideo() { | 753 bool MediaSourcePlayer::HasVideo() { |
731 return kUnknownVideoCodec != video_codec_; | 754 return kUnknownVideoCodec != video_codec_; |
732 } | 755 } |
733 | 756 |
734 bool MediaSourcePlayer::HasAudio() { | 757 bool MediaSourcePlayer::HasAudio() { |
735 return kUnknownAudioCodec != audio_codec_; | 758 return kUnknownAudioCodec != audio_codec_; |
736 } | 759 } |
737 | 760 |
| 761 bool MediaSourcePlayer::AudioFinished() { |
| 762 return reached_audio_eos_ || !HasAudio(); |
| 763 } |
| 764 |
| 765 bool MediaSourcePlayer::VideoFinished() { |
| 766 return reached_video_eos_ || !HasVideo(); |
| 767 } |
| 768 |
738 void MediaSourcePlayer::ConfigureAudioDecoderJob() { | 769 void MediaSourcePlayer::ConfigureAudioDecoderJob() { |
739 if (!HasAudio()) { | 770 if (!HasAudio()) { |
740 audio_decoder_job_.reset(); | 771 audio_decoder_job_.reset(); |
741 return; | 772 return; |
742 } | 773 } |
743 | 774 |
744 // Create audio decoder job only if config changes. | 775 // Create audio decoder job only if config changes. |
745 if (audio_decoder_job_ && !reconfig_audio_decoder_) | 776 if (audio_decoder_job_ && !reconfig_audio_decoder_) |
746 return; | 777 return; |
747 | 778 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
909 if (pending_event_ != NO_EVENT_PENDING) { | 940 if (pending_event_ != NO_EVENT_PENDING) { |
910 ProcessPendingEvents(); | 941 ProcessPendingEvents(); |
911 return; | 942 return; |
912 } | 943 } |
913 | 944 |
914 start_time_ticks_ = base::TimeTicks::Now(); | 945 start_time_ticks_ = base::TimeTicks::Now(); |
915 start_presentation_timestamp_ = GetCurrentTime(); | 946 start_presentation_timestamp_ = GetCurrentTime(); |
916 if (!clock_.IsPlaying()) | 947 if (!clock_.IsPlaying()) |
917 clock_.Play(); | 948 clock_.Play(); |
918 | 949 |
919 if (audio_decoder_job_) | 950 if (!AudioFinished()) |
920 DecodeMoreAudio(); | 951 DecodeMoreAudio(); |
921 if (video_decoder_job_) | 952 |
| 953 if (!VideoFinished()) |
922 DecodeMoreVideo(); | 954 DecodeMoreVideo(); |
923 } | 955 } |
924 | 956 |
925 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { | 957 const char* MediaSourcePlayer::GetEventName(PendingEventFlags event) { |
926 static const char* kPendingEventNames[] = { | 958 static const char* kPendingEventNames[] = { |
927 "SEEK", | 959 "SEEK", |
928 "SURFACE_CHANGE", | 960 "SURFACE_CHANGE", |
929 "CONFIG_CHANGE", | 961 "CONFIG_CHANGE", |
930 "PREFETCH_REQUEST", | 962 "PREFETCH_REQUEST", |
931 "PREFETCH_DONE", | 963 "PREFETCH_DONE", |
(...skipping 22 matching lines...) Expand all Loading... |
954 | 986 |
955 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { | 987 void MediaSourcePlayer::ClearPendingEvent(PendingEventFlags event) { |
956 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; | 988 DVLOG(1) << __FUNCTION__ << "(" << GetEventName(event) << ")"; |
957 DCHECK_NE(event, NO_EVENT_PENDING); | 989 DCHECK_NE(event, NO_EVENT_PENDING); |
958 DCHECK(IsEventPending(event)) << GetEventName(event); | 990 DCHECK(IsEventPending(event)) << GetEventName(event); |
959 | 991 |
960 pending_event_ &= ~event; | 992 pending_event_ &= ~event; |
961 } | 993 } |
962 | 994 |
963 } // namespace media | 995 } // namespace media |
OLD | NEW |