| 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 |