OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <stddef.h> | 5 #include <stddef.h> |
6 #include <stdint.h> | 6 #include <stdint.h> |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 CHECK_NE(codecs_param_end, std::string::npos); | 610 CHECK_NE(codecs_param_end, std::string::npos); |
611 | 611 |
612 std::string codecs_param = mimetype_.substr( | 612 std::string codecs_param = mimetype_.substr( |
613 codecs_param_start, codecs_param_end - codecs_param_start); | 613 codecs_param_start, codecs_param_end - codecs_param_start); |
614 codecs = base::SplitString(codecs_param, ",", base::KEEP_WHITESPACE, | 614 codecs = base::SplitString(codecs_param, ",", base::KEEP_WHITESPACE, |
615 base::SPLIT_WANT_NONEMPTY); | 615 base::SPLIT_WANT_NONEMPTY); |
616 } | 616 } |
617 | 617 |
618 CHECK_EQ(chunk_demuxer_->AddId(kSourceId, type, codecs), ChunkDemuxer::kOk); | 618 CHECK_EQ(chunk_demuxer_->AddId(kSourceId, type, codecs), ChunkDemuxer::kOk); |
619 chunk_demuxer_->SetTracksWatcher( | 619 chunk_demuxer_->SetTracksWatcher( |
620 kSourceId, base::Bind(&MockMediaSource::InitSegmentReceivedWrapper, | 620 kSourceId, base::Bind(&MockMediaSource::InitSegmentReceived, |
621 base::Unretained(this))); | 621 base::Unretained(this))); |
622 | 622 |
623 AppendData(initial_append_size_); | 623 AppendData(initial_append_size_); |
624 } | 624 } |
625 | 625 |
626 void OnEncryptedMediaInitData(EmeInitDataType init_data_type, | 626 void OnEncryptedMediaInitData(EmeInitDataType init_data_type, |
627 const std::vector<uint8_t>& init_data) { | 627 const std::vector<uint8_t>& init_data) { |
628 DCHECK(!init_data.empty()); | 628 DCHECK(!init_data.empty()); |
629 CHECK(!encrypted_media_init_data_cb_.is_null()); | 629 CHECK(!encrypted_media_init_data_cb_.is_null()); |
630 encrypted_media_init_data_cb_.Run(init_data_type, init_data); | 630 encrypted_media_init_data_cb_.Run(init_data_type, init_data); |
631 } | 631 } |
632 | 632 |
633 base::TimeDelta last_timestamp_offset() const { | 633 base::TimeDelta last_timestamp_offset() const { |
634 return last_timestamp_offset_; | 634 return last_timestamp_offset_; |
635 } | 635 } |
636 | 636 |
637 // A workaround for gtest mocks not allowing moving scoped_ptrs. | 637 void InitSegmentReceived(scoped_ptr<MediaTracks> tracks) { |
638 void InitSegmentReceivedWrapper(scoped_ptr<MediaTracks> tracks) { | 638 CHECK(tracks.get()); |
639 InitSegmentReceived(tracks); | 639 EXPECT_GT(tracks->tracks().size(), 0u); |
| 640 media_tracks_ = std::move(tracks); |
| 641 CHECK(chunk_demuxer_); |
| 642 static unsigned track_id = 0; |
| 643 for (const auto& track : media_tracks_->tracks()) { |
| 644 chunk_demuxer_->OnTrackIdAssigned(++track_id, track.get()); |
| 645 } |
640 } | 646 } |
641 | 647 |
642 MOCK_METHOD1(InitSegmentReceived, void(scoped_ptr<MediaTracks>&)); | 648 const MediaTracks* GetMediaTracks() const { return media_tracks_.get(); } |
643 | 649 |
644 private: | 650 private: |
645 scoped_refptr<DecoderBuffer> file_data_; | 651 scoped_refptr<DecoderBuffer> file_data_; |
646 size_t current_position_; | 652 size_t current_position_; |
647 size_t initial_append_size_; | 653 size_t initial_append_size_; |
648 std::string mimetype_; | 654 std::string mimetype_; |
649 ChunkDemuxer* chunk_demuxer_; | 655 ChunkDemuxer* chunk_demuxer_; |
650 scoped_ptr<Demuxer> owned_chunk_demuxer_; | 656 scoped_ptr<Demuxer> owned_chunk_demuxer_; |
| 657 scoped_ptr<MediaTracks> media_tracks_; |
651 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb_; | 658 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb_; |
652 base::TimeDelta last_timestamp_offset_; | 659 base::TimeDelta last_timestamp_offset_; |
653 }; | 660 }; |
654 | 661 |
655 #if defined(MOJO_RENDERER) | 662 #if defined(MOJO_RENDERER) |
656 class PipelineIntegrationTestHost : public mojo::test::ApplicationTestBase, | 663 class PipelineIntegrationTestHost : public mojo::test::ApplicationTestBase, |
657 public PipelineIntegrationTestBase { | 664 public PipelineIntegrationTestBase { |
658 public: | 665 public: |
659 bool ShouldCreateDefaultRunLoop() override { return false; } | 666 bool ShouldCreateDefaultRunLoop() override { return false; } |
660 | 667 |
(...skipping 25 matching lines...) Expand all Loading... |
686 public: | 693 public: |
687 PipelineStatus StartPipelineWithMediaSource(MockMediaSource* source) { | 694 PipelineStatus StartPipelineWithMediaSource(MockMediaSource* source) { |
688 return StartPipelineWithMediaSource(source, kNormal); | 695 return StartPipelineWithMediaSource(source, kNormal); |
689 } | 696 } |
690 | 697 |
691 PipelineStatus StartPipelineWithMediaSource(MockMediaSource* source, | 698 PipelineStatus StartPipelineWithMediaSource(MockMediaSource* source, |
692 uint8_t test_type) { | 699 uint8_t test_type) { |
693 hashing_enabled_ = test_type & kHashed; | 700 hashing_enabled_ = test_type & kHashed; |
694 clockless_playback_ = test_type & kClockless; | 701 clockless_playback_ = test_type & kClockless; |
695 | 702 |
696 EXPECT_CALL(*source, InitSegmentReceived(_)).Times(AtLeast(1)); | |
697 EXPECT_CALL(*this, OnMetadata(_)) | 703 EXPECT_CALL(*this, OnMetadata(_)) |
698 .Times(AtMost(1)) | 704 .Times(AtMost(1)) |
699 .WillRepeatedly(SaveArg<0>(&metadata_)); | 705 .WillRepeatedly(SaveArg<0>(&metadata_)); |
700 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH)) | 706 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH)) |
701 .Times(AnyNumber()); | 707 .Times(AnyNumber()); |
702 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING)) | 708 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING)) |
703 .Times(AnyNumber()); | 709 .Times(AnyNumber()); |
704 | 710 |
705 // Encrypted content not used, so this is never called. | 711 // Encrypted content not used, so this is never called. |
706 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); | 712 EXPECT_CALL(*this, OnWaitingForDecryptionKey()).Times(0); |
707 | 713 |
708 demuxer_ = source->GetDemuxer(); | 714 demuxer_ = source->GetDemuxer(); |
709 pipeline_->Start( | 715 pipeline_->Start( |
710 demuxer_.get(), CreateRenderer(), | 716 demuxer_.get(), CreateRenderer(), |
711 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)), | 717 base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)), |
712 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)), | 718 base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)), |
713 base::Bind(&PipelineIntegrationTest::OnStatusCallback, | 719 base::Bind(&PipelineIntegrationTest::OnStatusCallback, |
714 base::Unretained(this)), | 720 base::Unretained(this)), |
715 base::Bind(&PipelineIntegrationTest::OnMetadata, | 721 base::Bind(&PipelineIntegrationTest::OnMetadata, |
716 base::Unretained(this)), | 722 base::Unretained(this)), |
717 base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged, | 723 base::Bind(&PipelineIntegrationTest::OnBufferingStateChanged, |
718 base::Unretained(this)), | 724 base::Unretained(this)), |
719 base::Closure(), base::Bind(&PipelineIntegrationTest::OnAddTextTrack, | 725 base::Closure(), base::Bind(&PipelineIntegrationTest::OnAddTextTrack, |
720 base::Unretained(this)), | 726 base::Unretained(this)), |
721 base::Bind(&PipelineIntegrationTest::OnWaitingForDecryptionKey, | 727 base::Bind(&PipelineIntegrationTest::OnWaitingForDecryptionKey, |
722 base::Unretained(this))); | 728 base::Unretained(this))); |
723 message_loop_.Run(); | 729 message_loop_.Run(); |
724 EXPECT_EQ(PIPELINE_OK, pipeline_status_); | 730 EXPECT_EQ(PIPELINE_OK, pipeline_status_); |
| 731 EXPECT_GT(source->GetMediaTracks()->tracks().size(), 0u); |
725 return pipeline_status_; | 732 return pipeline_status_; |
726 } | 733 } |
727 | 734 |
| 735 void StartHashedPipelineWithMediaSource(MockMediaSource* source) { |
| 736 hashing_enabled_ = true; |
| 737 StartPipelineWithMediaSource(source); |
| 738 } |
| 739 |
| 740 void StartHashedClocklessPipelineWithMediaSource(MockMediaSource* source) { |
| 741 hashing_enabled_ = true; |
| 742 clockless_playback_ = true; |
| 743 StartPipelineWithMediaSource(source); |
| 744 } |
| 745 |
728 void StartPipelineWithEncryptedMedia(MockMediaSource* source, | 746 void StartPipelineWithEncryptedMedia(MockMediaSource* source, |
729 FakeEncryptedMedia* encrypted_media) { | 747 FakeEncryptedMedia* encrypted_media) { |
730 EXPECT_CALL(*source, InitSegmentReceived(_)).Times(AtLeast(1)); | |
731 EXPECT_CALL(*this, OnMetadata(_)) | 748 EXPECT_CALL(*this, OnMetadata(_)) |
732 .Times(AtMost(1)) | 749 .Times(AtMost(1)) |
733 .WillRepeatedly(SaveArg<0>(&metadata_)); | 750 .WillRepeatedly(SaveArg<0>(&metadata_)); |
734 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH)) | 751 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_ENOUGH)) |
735 .Times(AnyNumber()); | 752 .Times(AnyNumber()); |
736 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING)) | 753 EXPECT_CALL(*this, OnBufferingStateChanged(BUFFERING_HAVE_NOTHING)) |
737 .Times(AnyNumber()); | 754 .Times(AnyNumber()); |
738 EXPECT_CALL(*this, DecryptorAttached(true)); | 755 EXPECT_CALL(*this, DecryptorAttached(true)); |
739 | 756 |
740 // Encrypted content used but keys provided in advance, so this is | 757 // Encrypted content used but keys provided in advance, so this is |
(...skipping 20 matching lines...) Expand all Loading... |
761 base::Unretained(this)), | 778 base::Unretained(this)), |
762 base::Bind(&PipelineIntegrationTest::OnWaitingForDecryptionKey, | 779 base::Bind(&PipelineIntegrationTest::OnWaitingForDecryptionKey, |
763 base::Unretained(this))); | 780 base::Unretained(this))); |
764 | 781 |
765 source->set_encrypted_media_init_data_cb( | 782 source->set_encrypted_media_init_data_cb( |
766 base::Bind(&FakeEncryptedMedia::OnEncryptedMediaInitData, | 783 base::Bind(&FakeEncryptedMedia::OnEncryptedMediaInitData, |
767 base::Unretained(encrypted_media))); | 784 base::Unretained(encrypted_media))); |
768 | 785 |
769 message_loop_.Run(); | 786 message_loop_.Run(); |
770 EXPECT_EQ(PIPELINE_OK, pipeline_status_); | 787 EXPECT_EQ(PIPELINE_OK, pipeline_status_); |
| 788 EXPECT_GT(source->GetMediaTracks()->tracks().size(), 0u); |
771 } | 789 } |
772 | 790 |
773 // Verifies that seeking works properly for ChunkDemuxer when the | 791 // Verifies that seeking works properly for ChunkDemuxer when the |
774 // seek happens while there is a pending read on the ChunkDemuxer | 792 // seek happens while there is a pending read on the ChunkDemuxer |
775 // and no data is available. | 793 // and no data is available. |
776 bool TestSeekDuringRead(const std::string& filename, | 794 bool TestSeekDuringRead(const std::string& filename, |
777 const std::string& mimetype, | 795 const std::string& mimetype, |
778 int initial_append_size, | 796 int initial_append_size, |
779 base::TimeDelta start_seek_time, | 797 base::TimeDelta start_seek_time, |
780 base::TimeDelta seek_time, | 798 base::TimeDelta seek_time, |
(...skipping 1347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2128 } | 2146 } |
2129 | 2147 |
2130 TEST_F(PipelineIntegrationTest, BasicPlaybackPositiveStartTime) { | 2148 TEST_F(PipelineIntegrationTest, BasicPlaybackPositiveStartTime) { |
2131 ASSERT_EQ(PIPELINE_OK, Start("nonzero-start-time.webm")); | 2149 ASSERT_EQ(PIPELINE_OK, Start("nonzero-start-time.webm")); |
2132 Play(); | 2150 Play(); |
2133 ASSERT_TRUE(WaitUntilOnEnded()); | 2151 ASSERT_TRUE(WaitUntilOnEnded()); |
2134 ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000), | 2152 ASSERT_EQ(base::TimeDelta::FromMicroseconds(396000), |
2135 demuxer_->GetStartTime()); | 2153 demuxer_->GetStartTime()); |
2136 } | 2154 } |
2137 | 2155 |
| 2156 TEST_F(PipelineIntegrationTest, AudioTrackMuteUnmute) { |
| 2157 ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm")); |
| 2158 |
| 2159 // Start playback and play a little, to ensure demuxer streams are created. |
| 2160 Play(); |
| 2161 ASSERT_TRUE( |
| 2162 WaitUntilCurrentTimeIsAfter(base::TimeDelta::FromMilliseconds(500))); |
| 2163 Pause(); |
| 2164 |
| 2165 const DemuxerStream* demux_stream = demuxer_->GetDemuxerStreamByTrackId(2); |
| 2166 EXPECT_NE(demux_stream, nullptr); |
| 2167 EXPECT_EQ(demux_stream->type(), DemuxerStream::AUDIO); |
| 2168 |
| 2169 // TODO(servolk): Find a way to verify that audio is really muted/unmuted. |
| 2170 // This should mute the audio stream. |
| 2171 std::vector<const DemuxerStream*> enabledAudioStreams; |
| 2172 pipeline_->OnEnabledAudioStreamsChanged(enabledAudioStreams); |
| 2173 // This should unmute the audio stream. |
| 2174 enabledAudioStreams.push_back(demux_stream); |
| 2175 pipeline_->OnEnabledAudioStreamsChanged(enabledAudioStreams); |
| 2176 |
| 2177 Play(); |
| 2178 ASSERT_TRUE(WaitUntilOnEnded()); |
| 2179 } |
| 2180 |
2138 } // namespace media | 2181 } // namespace media |
OLD | NEW |