OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 renderer_impl_( | 75 renderer_impl_( |
76 new RendererImpl(message_loop_.task_runner(), | 76 new RendererImpl(message_loop_.task_runner(), |
77 std::unique_ptr<AudioRenderer>(audio_renderer_), | 77 std::unique_ptr<AudioRenderer>(audio_renderer_), |
78 std::unique_ptr<VideoRenderer>(video_renderer_))), | 78 std::unique_ptr<VideoRenderer>(video_renderer_))), |
79 cdm_context_(new StrictMock<MockCdmContext>()), | 79 cdm_context_(new StrictMock<MockCdmContext>()), |
80 video_renderer_client_(nullptr), | 80 video_renderer_client_(nullptr), |
81 audio_renderer_client_(nullptr), | 81 audio_renderer_client_(nullptr), |
82 initialization_status_(PIPELINE_OK) { | 82 initialization_status_(PIPELINE_OK) { |
83 // CreateAudioStream() and CreateVideoStream() overrides expectations for | 83 // CreateAudioStream() and CreateVideoStream() overrides expectations for |
84 // expected non-NULL streams. | 84 // expected non-NULL streams. |
85 DemuxerStream* null_pointer = NULL; | 85 std::vector<DemuxerStream*> empty; |
86 EXPECT_CALL(*demuxer_, GetStream(_)) | 86 EXPECT_CALL(*demuxer_, GetStreams()).WillRepeatedly(Return(empty)); |
87 .WillRepeatedly(Return(null_pointer)); | |
88 } | 87 } |
89 | 88 |
90 virtual ~RendererImplTest() { Destroy(); } | 89 virtual ~RendererImplTest() { Destroy(); } |
91 | 90 |
92 protected: | 91 protected: |
93 void Destroy() { | 92 void Destroy() { |
94 renderer_impl_.reset(); | 93 renderer_impl_.reset(); |
95 base::RunLoop().RunUntilIdle(); | 94 base::RunLoop().RunUntilIdle(); |
96 } | 95 } |
97 | 96 |
98 std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream( | 97 std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream( |
99 DemuxerStream::Type type) { | 98 DemuxerStream::Type type) { |
100 std::unique_ptr<StrictMock<MockDemuxerStream>> stream( | 99 std::unique_ptr<StrictMock<MockDemuxerStream>> stream( |
101 new StrictMock<MockDemuxerStream>(type)); | 100 new StrictMock<MockDemuxerStream>(type)); |
102 EXPECT_CALL(*stream, SetStreamStatusChangeCB(_)) | 101 EXPECT_CALL(*stream, enabled()).WillRepeatedly(Return(true)); |
102 EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) | |
103 .Times(testing::AnyNumber()); | 103 .Times(testing::AnyNumber()); |
104 return stream; | 104 return stream; |
105 } | 105 } |
106 | 106 |
107 // Sets up expectations to allow the audio renderer to initialize. | 107 // Sets up expectations to allow the audio renderer to initialize. |
108 void SetAudioRendererInitializeExpectations(PipelineStatus status) { | 108 void SetAudioRendererInitializeExpectations(PipelineStatus status) { |
109 EXPECT_CALL(*audio_renderer_, Initialize(audio_stream_.get(), _, _, _)) | 109 EXPECT_CALL(*audio_renderer_, Initialize(audio_stream_.get(), _, _, _)) |
110 .WillOnce( | 110 .WillOnce( |
111 DoAll(SaveArg<2>(&audio_renderer_client_), RunCallback<3>(status))); | 111 DoAll(SaveArg<2>(&audio_renderer_client_), RunCallback<3>(status))); |
112 } | 112 } |
(...skipping 18 matching lines...) Expand all Loading... | |
131 } | 131 } |
132 | 132 |
133 renderer_impl_->Initialize(demuxer_.get(), &callbacks_, | 133 renderer_impl_->Initialize(demuxer_.get(), &callbacks_, |
134 base::Bind(&CallbackHelper::OnInitialize, | 134 base::Bind(&CallbackHelper::OnInitialize, |
135 base::Unretained(&callbacks_))); | 135 base::Unretained(&callbacks_))); |
136 base::RunLoop().RunUntilIdle(); | 136 base::RunLoop().RunUntilIdle(); |
137 } | 137 } |
138 | 138 |
139 void CreateAudioStream() { | 139 void CreateAudioStream() { |
140 audio_stream_ = CreateStream(DemuxerStream::AUDIO); | 140 audio_stream_ = CreateStream(DemuxerStream::AUDIO); |
141 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO)) | 141 std::vector<DemuxerStream*> streams; |
142 .WillRepeatedly(Return(audio_stream_.get())); | 142 streams.push_back(audio_stream_.get()); |
143 if (video_stream_) | |
144 streams.push_back(video_stream_.get()); | |
xhwang
2017/02/01 18:26:04
ditto about refactor this test, e.g. maybe just s/
servolk
2017/02/01 22:29:21
Done.
| |
145 EXPECT_CALL(*demuxer_, GetStreams()).WillRepeatedly(Return(streams)); | |
143 } | 146 } |
144 | 147 |
145 void CreateVideoStream(bool is_encrypted = false) { | 148 void CreateVideoStream(bool is_encrypted = false) { |
146 video_stream_ = CreateStream(DemuxerStream::VIDEO); | 149 video_stream_ = CreateStream(DemuxerStream::VIDEO); |
147 video_stream_->set_video_decoder_config( | 150 video_stream_->set_video_decoder_config( |
148 is_encrypted ? TestVideoConfig::NormalEncrypted() | 151 is_encrypted ? TestVideoConfig::NormalEncrypted() |
149 : TestVideoConfig::Normal()); | 152 : TestVideoConfig::Normal()); |
150 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO)) | 153 std::vector<DemuxerStream*> streams; |
151 .WillRepeatedly(Return(video_stream_.get())); | 154 if (audio_stream_) |
155 streams.push_back(audio_stream_.get()); | |
156 streams.push_back(video_stream_.get()); | |
157 EXPECT_CALL(*demuxer_, GetStreams()).WillRepeatedly(Return(streams)); | |
152 } | 158 } |
153 | 159 |
154 void CreateEncryptedVideoStream() { CreateVideoStream(true); } | 160 void CreateEncryptedVideoStream() { CreateVideoStream(true); } |
155 | 161 |
156 void CreateAudioAndVideoStream() { | 162 void CreateAudioAndVideoStream() { |
157 CreateAudioStream(); | 163 CreateAudioStream(); |
158 CreateVideoStream(); | 164 CreateVideoStream(); |
159 } | 165 } |
160 | 166 |
161 void InitializeWithAudio() { | 167 void InitializeWithAudio() { |
162 CreateAudioStream(); | 168 CreateAudioStream(); |
163 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 169 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
164 // There is a potential race between HTMLMediaElement/WMPI shutdown and | 170 // There is a potential race between HTMLMediaElement/WMPI shutdown and |
165 // renderers being initialized which might result in DemuxerStreamProvider | 171 // renderers being initialized which might result in MediaResource |
166 // GetStream suddenly returning NULL (see crbug.com/668604). So we are going | 172 // GetStreams suddenly returning fewer streams than before or even returning |
167 // to check here that GetStream will be invoked exactly 3 times during | 173 // and empty stream collection (see crbug.com/668604). So we are going to |
174 // check here that GetStreams will be invoked exactly 3 times during | |
168 // RendererImpl initialization to help catch potential issues. Currently the | 175 // RendererImpl initialization to help catch potential issues. Currently the |
169 // GetStream is invoked once directly from RendererImpl::Initialize, once | 176 // GetStreams is invoked once from the RendererImpl::Initialize via |
170 // indirectly from RendererImpl::Initialize via HasEncryptedStream and once | 177 // HasEncryptedStream, once from the RendererImpl::InitializeAudioRenderer |
171 // from RendererImpl::InitializeAudioRenderer. | 178 // and once from the RendererImpl::InitializeVideoRenderer. |
172 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO)) | 179 std::vector<DemuxerStream*> streams; |
173 .Times(2) | 180 streams.push_back(audio_stream_.get()); |
174 .WillRepeatedly(Return(audio_stream_.get())); | 181 EXPECT_CALL(*demuxer_, GetStreams()) |
182 .Times(3) | |
183 .WillRepeatedly(Return(streams)); | |
175 InitializeAndExpect(PIPELINE_OK); | 184 InitializeAndExpect(PIPELINE_OK); |
176 } | 185 } |
177 | 186 |
178 void InitializeWithVideo() { | 187 void InitializeWithVideo() { |
179 CreateVideoStream(); | 188 CreateVideoStream(); |
180 SetVideoRendererInitializeExpectations(PIPELINE_OK); | 189 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
181 // There is a potential race between HTMLMediaElement/WMPI shutdown and | 190 // There is a potential race between HTMLMediaElement/WMPI shutdown and |
182 // renderers being initialized which might result in DemuxerStreamProvider | 191 // renderers being initialized which might result in MediaResource |
183 // GetStream suddenly returning NULL (see crbug.com/668604). So we are going | 192 // GetStreams suddenly returning fewer streams than before or even returning |
184 // to check here that GetStream will be invoked exactly 3 times during | 193 // and empty stream collection (see crbug.com/668604). So we are going to |
194 // check here that GetStreams will be invoked exactly 3 times during | |
185 // RendererImpl initialization to help catch potential issues. Currently the | 195 // RendererImpl initialization to help catch potential issues. Currently the |
186 // GetStream is invoked once directly from RendererImpl::Initialize, once | 196 // GetStreams is invoked once from the RendererImpl::Initialize via |
187 // indirectly from RendererImpl::Initialize via HasEncryptedStream and once | 197 // HasEncryptedStream, once from the RendererImpl::InitializeAudioRenderer |
188 // from RendererImpl::InitializeVideoRenderer. | 198 // and once from the RendererImpl::InitializeVideoRenderer. |
189 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO)) | 199 std::vector<DemuxerStream*> streams; |
190 .Times(2) | 200 streams.push_back(video_stream_.get()); |
191 .WillRepeatedly(Return(video_stream_.get())); | 201 EXPECT_CALL(*demuxer_, GetStreams()) |
202 .Times(3) | |
203 .WillRepeatedly(Return(streams)); | |
192 InitializeAndExpect(PIPELINE_OK); | 204 InitializeAndExpect(PIPELINE_OK); |
193 } | 205 } |
194 | 206 |
195 void InitializeWithAudioAndVideo() { | 207 void InitializeWithAudioAndVideo() { |
196 CreateAudioAndVideoStream(); | 208 CreateAudioAndVideoStream(); |
197 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 209 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
198 SetVideoRendererInitializeExpectations(PIPELINE_OK); | 210 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
199 InitializeAndExpect(PIPELINE_OK); | 211 InitializeAndExpect(PIPELINE_OK); |
200 } | 212 } |
201 | 213 |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 EXPECT_CALL(*video_renderer_, StartPlayingFrom(kStartTime)); | 756 EXPECT_CALL(*video_renderer_, StartPlayingFrom(kStartTime)); |
745 renderer_impl_->StartPlayingFrom(kStartTime); | 757 renderer_impl_->StartPlayingFrom(kStartTime); |
746 | 758 |
747 // Nothing else should primed on the message loop. | 759 // Nothing else should primed on the message loop. |
748 base::RunLoop().RunUntilIdle(); | 760 base::RunLoop().RunUntilIdle(); |
749 } | 761 } |
750 | 762 |
751 TEST_F(RendererImplTest, StreamStatusNotificationHandling) { | 763 TEST_F(RendererImplTest, StreamStatusNotificationHandling) { |
752 CreateAudioAndVideoStream(); | 764 CreateAudioAndVideoStream(); |
753 | 765 |
754 DemuxerStream::StreamStatusChangeCB audio_stream_status_change_cb; | 766 StreamStatusChangeCB stream_status_change_cb; |
755 DemuxerStream::StreamStatusChangeCB video_stream_status_change_cb; | 767 EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) |
756 EXPECT_CALL(*audio_stream_, SetStreamStatusChangeCB(_)) | 768 .WillOnce(SaveArg<0>(&stream_status_change_cb)); |
757 .WillOnce(SaveArg<0>(&audio_stream_status_change_cb)); | |
758 EXPECT_CALL(*video_stream_, SetStreamStatusChangeCB(_)) | |
759 .WillOnce(SaveArg<0>(&video_stream_status_change_cb)); | |
760 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 769 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
761 SetVideoRendererInitializeExpectations(PIPELINE_OK); | 770 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
762 InitializeAndExpect(PIPELINE_OK); | 771 InitializeAndExpect(PIPELINE_OK); |
763 Play(); | 772 Play(); |
764 | 773 |
765 // Verify that DemuxerStream status changes cause the corresponding | 774 // Verify that DemuxerStream status changes cause the corresponding |
766 // audio/video renderer to be flushed and restarted. | 775 // audio/video renderer to be flushed and restarted. |
767 EXPECT_CALL(time_source_, StopTicking()); | 776 EXPECT_CALL(time_source_, StopTicking()); |
768 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>()); | 777 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>()); |
769 EXPECT_CALL(*audio_renderer_, StartPlaying()) | 778 EXPECT_CALL(*audio_renderer_, StartPlaying()) |
770 .Times(1) | 779 .Times(1) |
771 .WillOnce( | 780 .WillOnce( |
772 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)); | 781 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)); |
773 audio_stream_status_change_cb.Run(false, base::TimeDelta()); | 782 stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta()); |
774 | 783 |
775 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>()); | 784 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>()); |
776 EXPECT_CALL(*video_renderer_, StartPlayingFrom(_)) | 785 EXPECT_CALL(*video_renderer_, StartPlayingFrom(_)) |
777 .Times(1) | 786 .Times(1) |
778 .WillOnce(DoAll( | 787 .WillOnce(DoAll( |
779 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH), | 788 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH), |
780 PostQuitWhenIdle())); | 789 PostQuitWhenIdle())); |
781 | 790 |
782 video_stream_status_change_cb.Run(false, base::TimeDelta()); | 791 stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); |
783 base::RunLoop().Run(); | 792 base::RunLoop().Run(); |
784 } | 793 } |
785 | 794 |
786 // Stream status changes are handled asynchronously by the renderer and may take | 795 // Stream status changes are handled asynchronously by the renderer and may take |
787 // some time to process. This test verifies that all status changes are | 796 // some time to process. This test verifies that all status changes are |
788 // processed correctly by the renderer even if status changes of the stream | 797 // processed correctly by the renderer even if status changes of the stream |
789 // happen much faster than the renderer can process them. In that case the | 798 // happen much faster than the renderer can process them. In that case the |
790 // renderer may postpone processing status changes, but still must process all | 799 // renderer may postpone processing status changes, but still must process all |
791 // of them eventually. | 800 // of them eventually. |
792 TEST_F(RendererImplTest, PostponedStreamStatusNotificationHandling) { | 801 TEST_F(RendererImplTest, PostponedStreamStatusNotificationHandling) { |
793 CreateAudioAndVideoStream(); | 802 CreateAudioAndVideoStream(); |
794 | 803 |
795 DemuxerStream::StreamStatusChangeCB audio_stream_status_change_cb; | 804 StreamStatusChangeCB stream_status_change_cb; |
796 DemuxerStream::StreamStatusChangeCB video_stream_status_change_cb; | 805 EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) |
797 EXPECT_CALL(*audio_stream_, SetStreamStatusChangeCB(_)) | 806 .WillOnce(SaveArg<0>(&stream_status_change_cb)); |
798 .WillOnce(SaveArg<0>(&audio_stream_status_change_cb)); | |
799 EXPECT_CALL(*video_stream_, SetStreamStatusChangeCB(_)) | |
800 .WillOnce(SaveArg<0>(&video_stream_status_change_cb)); | |
801 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 807 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
802 SetVideoRendererInitializeExpectations(PIPELINE_OK); | 808 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
803 InitializeAndExpect(PIPELINE_OK); | 809 InitializeAndExpect(PIPELINE_OK); |
804 Play(); | 810 Play(); |
805 | 811 |
806 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 812 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
807 .Times(2); | 813 .Times(2); |
808 | 814 |
809 EXPECT_CALL(time_source_, StopTicking()).Times(2); | 815 EXPECT_CALL(time_source_, StopTicking()).Times(2); |
810 EXPECT_CALL(time_source_, StartTicking()).Times(2); | 816 EXPECT_CALL(time_source_, StartTicking()).Times(2); |
811 EXPECT_CALL(*audio_renderer_, Flush(_)) | 817 EXPECT_CALL(*audio_renderer_, Flush(_)) |
812 .Times(2) | 818 .Times(2) |
813 .WillRepeatedly(DoAll( | 819 .WillRepeatedly(DoAll( |
814 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_NOTHING), | 820 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_NOTHING), |
815 WithArg<0>(PostCallback()))); | 821 WithArg<0>(PostCallback()))); |
816 EXPECT_CALL(*audio_renderer_, StartPlaying()) | 822 EXPECT_CALL(*audio_renderer_, StartPlaying()) |
817 .Times(2) | 823 .Times(2) |
818 .WillOnce( | 824 .WillOnce( |
819 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)) | 825 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)) |
820 .WillOnce(DoAll( | 826 .WillOnce(DoAll( |
821 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH), | 827 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH), |
822 PostQuitWhenIdle())); | 828 PostQuitWhenIdle())); |
823 // The first stream status change will be processed immediately. Each status | 829 // The first stream status change will be processed immediately. Each status |
824 // change processing involves Flush + StartPlaying when the Flush is done. The | 830 // change processing involves Flush + StartPlaying when the Flush is done. The |
825 // Flush operation is async in this case, so the second status change will be | 831 // Flush operation is async in this case, so the second status change will be |
826 // postponed by renderer until after processing the first one is finished. But | 832 // postponed by renderer until after processing the first one is finished. But |
827 // we must still get two pairs of Flush/StartPlaying calls eventually. | 833 // we must still get two pairs of Flush/StartPlaying calls eventually. |
828 audio_stream_status_change_cb.Run(false, base::TimeDelta()); | 834 stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta()); |
829 audio_stream_status_change_cb.Run(true, base::TimeDelta()); | 835 stream_status_change_cb.Run(audio_stream_.get(), true, base::TimeDelta()); |
830 base::RunLoop().Run(); | 836 base::RunLoop().Run(); |
831 | 837 |
832 EXPECT_CALL(*video_renderer_, Flush(_)) | 838 EXPECT_CALL(*video_renderer_, Flush(_)) |
833 .Times(2) | 839 .Times(2) |
834 .WillRepeatedly(DoAll( | 840 .WillRepeatedly(DoAll( |
835 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_NOTHING), | 841 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_NOTHING), |
836 WithArg<0>(PostCallback()))); | 842 WithArg<0>(PostCallback()))); |
837 EXPECT_CALL(*video_renderer_, StartPlayingFrom(base::TimeDelta())) | 843 EXPECT_CALL(*video_renderer_, StartPlayingFrom(base::TimeDelta())) |
838 .Times(2) | 844 .Times(2) |
839 .WillOnce( | 845 .WillOnce( |
840 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH)) | 846 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH)) |
841 .WillOnce(DoAll( | 847 .WillOnce(DoAll( |
842 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH), | 848 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH), |
843 PostQuitWhenIdle())); | 849 PostQuitWhenIdle())); |
844 // The first stream status change will be processed immediately. Each status | 850 // The first stream status change will be processed immediately. Each status |
845 // change processing involves Flush + StartPlaying when the Flush is done. The | 851 // change processing involves Flush + StartPlaying when the Flush is done. The |
846 // Flush operation is async in this case, so the second status change will be | 852 // Flush operation is async in this case, so the second status change will be |
847 // postponed by renderer until after processing the first one is finished. But | 853 // postponed by renderer until after processing the first one is finished. But |
848 // we must still get two pairs of Flush/StartPlaying calls eventually. | 854 // we must still get two pairs of Flush/StartPlaying calls eventually. |
849 video_stream_status_change_cb.Run(false, base::TimeDelta()); | 855 stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); |
850 video_stream_status_change_cb.Run(true, base::TimeDelta()); | 856 stream_status_change_cb.Run(video_stream_.get(), true, base::TimeDelta()); |
851 base::RunLoop().Run(); | 857 base::RunLoop().Run(); |
852 } | 858 } |
853 | 859 |
854 } // namespace media | 860 } // namespace media |
OLD | NEW |