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 <vector> | 5 #include <vector> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/threading/simple_thread.h" | 10 #include "base/threading/simple_thread.h" |
11 #include "media/base/clock.h" | 11 #include "media/base/clock.h" |
12 #include "media/base/media_log.h" | 12 #include "media/base/media_log.h" |
13 #include "media/base/pipeline.h" | 13 #include "media/base/pipeline.h" |
14 #include "media/base/mock_callback.h" | 14 #include "media/base/mock_callback.h" |
15 #include "media/base/mock_filters.h" | 15 #include "media/base/mock_filters.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
17 #include "ui/gfx/size.h" | 17 #include "ui/gfx/size.h" |
18 | 18 |
19 using ::testing::_; | 19 using ::testing::_; |
20 using ::testing::DeleteArg; | 20 using ::testing::DeleteArg; |
21 using ::testing::DoAll; | 21 using ::testing::DoAll; |
22 // TODO(scherkus): Remove InSequence after refactoring Pipeline. | |
22 using ::testing::InSequence; | 23 using ::testing::InSequence; |
23 using ::testing::Invoke; | 24 using ::testing::Invoke; |
24 using ::testing::InvokeWithoutArgs; | 25 using ::testing::InvokeWithoutArgs; |
25 using ::testing::Mock; | 26 using ::testing::Mock; |
26 using ::testing::NotNull; | 27 using ::testing::NotNull; |
27 using ::testing::Return; | 28 using ::testing::Return; |
28 using ::testing::ReturnRef; | 29 using ::testing::ReturnRef; |
29 using ::testing::SaveArg; | 30 using ::testing::SaveArg; |
30 using ::testing::StrictMock; | 31 using ::testing::StrictMock; |
31 using ::testing::WithArg; | 32 using ::testing::WithArg; |
32 | 33 |
33 namespace media { | 34 namespace media { |
34 | 35 |
35 // Demuxer properties. | 36 // Demuxer properties. |
36 static const int kTotalBytes = 1024; | 37 static const int kTotalBytes = 1024; |
37 static const int kBitrate = 1234; | 38 static const int kBitrate = 1234; |
38 | 39 |
39 ACTION_P(SetDemuxerProperties, duration) { | 40 ACTION_P(SetDemuxerProperties, duration) { |
40 arg0->SetTotalBytes(kTotalBytes); | 41 arg0->SetTotalBytes(kTotalBytes); |
41 arg0->SetDuration(duration); | 42 arg0->SetDuration(duration); |
42 } | 43 } |
43 | 44 |
44 ACTION(RunPipelineStatusCB1) { | 45 ACTION_P2(Stop, pipeline, stop_cb) { |
46 pipeline->Stop(stop_cb); | |
47 } | |
48 | |
49 ACTION_P2(SetError, pipeline, status) { | |
50 pipeline->SetErrorForTesting(status); | |
51 } | |
52 | |
53 ACTION(RunPipelineStatusCB) { | |
45 arg1.Run(PIPELINE_OK); | 54 arg1.Run(PIPELINE_OK); |
46 } | 55 } |
47 | 56 |
48 ACTION_P(RunPipelineStatusCB1WithStatus, status) { | 57 ACTION_P(RunPipelineStatusCBWithStatus, status) { |
49 arg1.Run(status); | 58 arg1.Run(status); |
50 } | 59 } |
51 | 60 |
52 // Used for setting expectations on pipeline callbacks. Using a StrictMock | 61 // Used for setting expectations on pipeline callbacks. Using a StrictMock |
53 // also lets us test for missing callbacks. | 62 // also lets us test for missing callbacks. |
54 class CallbackHelper { | 63 class CallbackHelper { |
55 public: | 64 public: |
56 CallbackHelper() {} | 65 CallbackHelper() {} |
57 virtual ~CallbackHelper() {} | 66 virtual ~CallbackHelper() {} |
58 | 67 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
91 virtual ~PipelineTest() { | 100 virtual ~PipelineTest() { |
92 if (!pipeline_->IsRunning()) { | 101 if (!pipeline_->IsRunning()) { |
93 return; | 102 return; |
94 } | 103 } |
95 | 104 |
96 // Shutdown sequence. | 105 // Shutdown sequence. |
97 if (pipeline_->IsInitialized()) { | 106 if (pipeline_->IsInitialized()) { |
98 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) | 107 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
99 .WillOnce(RunClosure()); | 108 .WillOnce(RunClosure()); |
100 | 109 |
110 // TODO(scherkus): Don't pause+flush on shutdown, | |
111 // see http://crbug.com/110228 | |
101 if (audio_stream_) { | 112 if (audio_stream_) { |
102 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) | 113 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) |
103 .WillOnce(RunClosure()); | 114 .WillOnce(RunClosure()); |
104 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) | 115 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) |
105 .WillOnce(RunClosure()); | 116 .WillOnce(RunClosure()); |
106 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) | 117 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) |
107 .WillOnce(RunClosure()); | 118 .WillOnce(RunClosure()); |
108 } | 119 } |
109 | 120 |
110 if (video_stream_) { | 121 if (video_stream_) { |
(...skipping 16 matching lines...) Expand all Loading... | |
127 mocks_.reset(); | 138 mocks_.reset(); |
128 } | 139 } |
129 | 140 |
130 protected: | 141 protected: |
131 // Sets up expectations to allow the demuxer to initialize. | 142 // Sets up expectations to allow the demuxer to initialize. |
132 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; | 143 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; |
133 void InitializeDemuxer(MockDemuxerStreamVector* streams, | 144 void InitializeDemuxer(MockDemuxerStreamVector* streams, |
134 const base::TimeDelta& duration) { | 145 const base::TimeDelta& duration) { |
135 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) | 146 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) |
136 .WillOnce(DoAll(SetDemuxerProperties(duration), | 147 .WillOnce(DoAll(SetDemuxerProperties(duration), |
137 RunPipelineStatusCB1())); | 148 RunPipelineStatusCB())); |
138 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f)); | 149 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f)); |
139 | 150 |
140 // Configure the demuxer to return the streams. | 151 // Configure the demuxer to return the streams. |
141 for (size_t i = 0; i < streams->size(); ++i) { | 152 for (size_t i = 0; i < streams->size(); ++i) { |
142 scoped_refptr<DemuxerStream> stream((*streams)[i]); | 153 scoped_refptr<DemuxerStream> stream((*streams)[i]); |
143 EXPECT_CALL(*mocks_->demuxer(), GetStream(stream->type())) | 154 EXPECT_CALL(*mocks_->demuxer(), GetStream(stream->type())) |
144 .WillRepeatedly(Return(stream)); | 155 .WillRepeatedly(Return(stream)); |
145 } | 156 } |
146 } | 157 } |
147 | 158 |
148 void InitializeDemuxer(MockDemuxerStreamVector* streams) { | 159 void InitializeDemuxer(MockDemuxerStreamVector* streams) { |
149 // Initialize with a default non-zero duration. | 160 // Initialize with a default non-zero duration. |
150 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10)); | 161 InitializeDemuxer(streams, base::TimeDelta::FromSeconds(10)); |
151 } | 162 } |
152 | 163 |
153 StrictMock<MockDemuxerStream>* CreateStream(DemuxerStream::Type type) { | 164 StrictMock<MockDemuxerStream>* CreateStream(DemuxerStream::Type type) { |
154 StrictMock<MockDemuxerStream>* stream = | 165 StrictMock<MockDemuxerStream>* stream = |
155 new StrictMock<MockDemuxerStream>(); | 166 new StrictMock<MockDemuxerStream>(); |
156 EXPECT_CALL(*stream, type()) | 167 EXPECT_CALL(*stream, type()) |
157 .WillRepeatedly(Return(type)); | 168 .WillRepeatedly(Return(type)); |
158 return stream; | 169 return stream; |
159 } | 170 } |
160 | 171 |
161 // Sets up expectations to allow the video decoder to initialize. | 172 // Sets up expectations to allow the video decoder to initialize. |
162 void InitializeVideoDecoder(const scoped_refptr<DemuxerStream>& stream) { | 173 void InitializeVideoDecoder(const scoped_refptr<DemuxerStream>& stream) { |
163 EXPECT_CALL(*mocks_->video_decoder(), | 174 EXPECT_CALL(*mocks_->video_decoder(), |
164 Initialize(stream, _, _)) | 175 Initialize(stream, _, _)) |
165 .WillOnce(RunPipelineStatusCB1()); | 176 .WillOnce(RunPipelineStatusCB()); |
166 } | 177 } |
167 | 178 |
168 // Sets up expectations to allow the audio decoder to initialize. | 179 // Sets up expectations to allow the audio decoder to initialize. |
169 void InitializeAudioDecoder(const scoped_refptr<DemuxerStream>& stream) { | 180 void InitializeAudioDecoder(const scoped_refptr<DemuxerStream>& stream) { |
170 EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream, _, _)) | 181 EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream, _, _)) |
171 .WillOnce(RunPipelineStatusCB1()); | 182 .WillOnce(RunPipelineStatusCB()); |
172 } | 183 } |
173 | 184 |
174 // Sets up expectations to allow the video renderer to initialize. | 185 // Sets up expectations to allow the video renderer to initialize. |
175 void InitializeVideoRenderer() { | 186 void InitializeVideoRenderer() { |
176 EXPECT_CALL(*mocks_->video_renderer(), Initialize( | 187 EXPECT_CALL(*mocks_->video_renderer(), Initialize( |
177 scoped_refptr<VideoDecoder>(mocks_->video_decoder()), | 188 scoped_refptr<VideoDecoder>(mocks_->video_decoder()), |
178 _, _, _, _, _, _, _, _)) | 189 _, _, _, _, _, _, _, _)) |
179 .WillOnce(RunPipelineStatusCB1()); | 190 .WillOnce(RunPipelineStatusCB()); |
180 EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(0.0f)); | 191 EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(0.0f)); |
181 | 192 |
182 // Startup sequence. | 193 // Startup sequence. |
183 EXPECT_CALL(*mocks_->video_renderer(), | 194 EXPECT_CALL(*mocks_->video_renderer(), |
184 Preroll(mocks_->demuxer()->GetStartTime(), _)) | 195 Preroll(mocks_->demuxer()->GetStartTime(), _)) |
185 .WillOnce(RunPipelineStatusCB1()); | 196 .WillOnce(RunPipelineStatusCB()); |
186 EXPECT_CALL(*mocks_->video_renderer(), Play(_)) | 197 EXPECT_CALL(*mocks_->video_renderer(), Play(_)) |
187 .WillOnce(RunClosure()); | 198 .WillOnce(RunClosure()); |
188 } | 199 } |
189 | 200 |
190 // Sets up expectations to allow the audio renderer to initialize. | 201 // Sets up expectations to allow the audio renderer to initialize. |
191 void InitializeAudioRenderer(bool disable_after_init_cb = false) { | 202 void InitializeAudioRenderer(bool disable_after_init_cb = false) { |
192 if (disable_after_init_cb) { | 203 if (disable_after_init_cb) { |
193 EXPECT_CALL(*mocks_->audio_renderer(), Initialize( | 204 EXPECT_CALL(*mocks_->audio_renderer(), Initialize( |
194 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), | 205 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), |
195 _, _, _, _, _, _)) | 206 _, _, _, _, _, _)) |
196 .WillOnce(DoAll(RunPipelineStatusCB1(), | 207 .WillOnce(DoAll(RunPipelineStatusCB(), |
197 WithArg<5>(RunClosure()))); // |disabled_cb|. | 208 WithArg<5>(RunClosure()))); // |disabled_cb|. |
198 } else { | 209 } else { |
199 EXPECT_CALL(*mocks_->audio_renderer(), Initialize( | 210 EXPECT_CALL(*mocks_->audio_renderer(), Initialize( |
200 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), | 211 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), |
201 _, _, _, _, _, _)) | 212 _, _, _, _, _, _)) |
202 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_), | 213 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_), |
203 RunPipelineStatusCB1())); | 214 RunPipelineStatusCB())); |
204 } | 215 } |
205 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f)); | 216 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f)); |
206 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f)); | 217 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f)); |
207 | 218 |
208 // Startup sequence. | 219 // Startup sequence. |
209 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(base::TimeDelta(), _)) | 220 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(base::TimeDelta(), _)) |
210 .WillOnce(RunPipelineStatusCB1()); | 221 .WillOnce(RunPipelineStatusCB()); |
211 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) | 222 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) |
212 .WillOnce(RunClosure()); | 223 .WillOnce(RunClosure()); |
213 } | 224 } |
214 | 225 |
215 // Sets up expectations on the callback and initializes the pipeline. Called | 226 // Sets up expectations on the callback and initializes the pipeline. Called |
216 // after tests have set expectations any filters they wish to use. | 227 // after tests have set expectations any filters they wish to use. |
217 void InitializePipeline(PipelineStatus start_status) { | 228 void InitializePipeline(PipelineStatus start_status) { |
218 EXPECT_CALL(callbacks_, OnStart(start_status)); | 229 EXPECT_CALL(callbacks_, OnStart(start_status)); |
219 | 230 |
220 pipeline_->Start( | 231 pipeline_->Start( |
(...skipping 16 matching lines...) Expand all Loading... | |
237 return audio_stream_; | 248 return audio_stream_; |
238 } | 249 } |
239 | 250 |
240 MockDemuxerStream* video_stream() { | 251 MockDemuxerStream* video_stream() { |
241 return video_stream_; | 252 return video_stream_; |
242 } | 253 } |
243 | 254 |
244 void ExpectSeek(const base::TimeDelta& seek_time) { | 255 void ExpectSeek(const base::TimeDelta& seek_time) { |
245 // Every filter should receive a call to Seek(). | 256 // Every filter should receive a call to Seek(). |
246 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) | 257 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) |
247 .WillOnce(RunPipelineStatusCB1()); | 258 .WillOnce(RunPipelineStatusCB()); |
248 | 259 |
249 if (audio_stream_) { | 260 if (audio_stream_) { |
250 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) | 261 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) |
251 .WillOnce(RunClosure()); | 262 .WillOnce(RunClosure()); |
252 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) | 263 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) |
253 .WillOnce(RunClosure()); | 264 .WillOnce(RunClosure()); |
254 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(seek_time, _)) | 265 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(seek_time, _)) |
255 .WillOnce(RunPipelineStatusCB1()); | 266 .WillOnce(RunPipelineStatusCB()); |
256 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) | 267 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) |
257 .WillOnce(RunClosure()); | 268 .WillOnce(RunClosure()); |
258 } | 269 } |
259 | 270 |
260 if (video_stream_) { | 271 if (video_stream_) { |
261 EXPECT_CALL(*mocks_->video_renderer(), Pause(_)) | 272 EXPECT_CALL(*mocks_->video_renderer(), Pause(_)) |
262 .WillOnce(RunClosure()); | 273 .WillOnce(RunClosure()); |
263 EXPECT_CALL(*mocks_->video_renderer(), Flush(_)) | 274 EXPECT_CALL(*mocks_->video_renderer(), Flush(_)) |
264 .WillOnce(RunClosure()); | 275 .WillOnce(RunClosure()); |
265 EXPECT_CALL(*mocks_->video_renderer(), Preroll(seek_time, _)) | 276 EXPECT_CALL(*mocks_->video_renderer(), Preroll(seek_time, _)) |
266 .WillOnce(RunPipelineStatusCB1()); | 277 .WillOnce(RunPipelineStatusCB()); |
267 EXPECT_CALL(*mocks_->video_renderer(), Play(_)) | 278 EXPECT_CALL(*mocks_->video_renderer(), Play(_)) |
268 .WillOnce(RunClosure()); | 279 .WillOnce(RunClosure()); |
269 } | 280 } |
270 | 281 |
271 // We expect a successful seek callback. | 282 // We expect a successful seek callback. |
272 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); | 283 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); |
273 } | 284 } |
274 | 285 |
275 void DoSeek(const base::TimeDelta& seek_time) { | 286 void DoSeek(const base::TimeDelta& seek_time) { |
276 pipeline_->Seek(seek_time, | 287 pipeline_->Seek(seek_time, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
368 collection.Pass(), | 379 collection.Pass(), |
369 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), | 380 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), |
370 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), | 381 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), |
371 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); | 382 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); |
372 message_loop_.RunAllPending(); | 383 message_loop_.RunAllPending(); |
373 EXPECT_FALSE(pipeline_->IsInitialized()); | 384 EXPECT_FALSE(pipeline_->IsInitialized()); |
374 } | 385 } |
375 | 386 |
376 TEST_F(PipelineTest, URLNotFound) { | 387 TEST_F(PipelineTest, URLNotFound) { |
377 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) | 388 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) |
378 .WillOnce(RunPipelineStatusCB1WithStatus(PIPELINE_ERROR_URL_NOT_FOUND)); | 389 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_URL_NOT_FOUND)); |
379 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) | 390 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
380 .WillOnce(RunClosure()); | 391 .WillOnce(RunClosure()); |
381 | 392 |
382 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND); | 393 InitializePipeline(PIPELINE_ERROR_URL_NOT_FOUND); |
383 EXPECT_FALSE(pipeline_->IsInitialized()); | 394 EXPECT_FALSE(pipeline_->IsInitialized()); |
384 } | 395 } |
385 | 396 |
386 TEST_F(PipelineTest, NoStreams) { | 397 TEST_F(PipelineTest, NoStreams) { |
387 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) | 398 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) |
388 .WillOnce(RunPipelineStatusCB1()); | 399 .WillOnce(RunPipelineStatusCB()); |
389 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) | 400 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
390 .WillOnce(RunClosure()); | 401 .WillOnce(RunClosure()); |
391 | 402 |
392 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER); | 403 InitializePipeline(PIPELINE_ERROR_COULD_NOT_RENDER); |
393 EXPECT_FALSE(pipeline_->IsInitialized()); | 404 EXPECT_FALSE(pipeline_->IsInitialized()); |
394 } | 405 } |
395 | 406 |
396 TEST_F(PipelineTest, AudioStream) { | 407 TEST_F(PipelineTest, AudioStream) { |
397 CreateAudioStream(); | 408 CreateAudioStream(); |
398 MockDemuxerStreamVector streams; | 409 MockDemuxerStreamVector streams; |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
730 | 741 |
731 // Seek() isn't called as the demuxer errors out first. | 742 // Seek() isn't called as the demuxer errors out first. |
732 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) | 743 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) |
733 .WillOnce(RunClosure()); | 744 .WillOnce(RunClosure()); |
734 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) | 745 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) |
735 .WillOnce(RunClosure()); | 746 .WillOnce(RunClosure()); |
736 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) | 747 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) |
737 .WillOnce(RunClosure()); | 748 .WillOnce(RunClosure()); |
738 | 749 |
739 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) | 750 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) |
740 .WillOnce(RunPipelineStatusCB1WithStatus(PIPELINE_ERROR_READ)); | 751 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_READ)); |
741 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) | 752 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
742 .WillOnce(RunClosure()); | 753 .WillOnce(RunClosure()); |
743 | 754 |
744 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, | 755 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, |
745 base::Unretained(&callbacks_))); | 756 base::Unretained(&callbacks_))); |
746 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); | 757 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); |
747 message_loop_.RunAllPending(); | 758 message_loop_.RunAllPending(); |
748 } | 759 } |
749 | 760 |
750 // Invoked function OnError. This asserts that the pipeline does not enqueue | 761 // Invoked function OnError. This asserts that the pipeline does not enqueue |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
786 | 797 |
787 // Seek() isn't called as the demuxer errors out first. | 798 // Seek() isn't called as the demuxer errors out first. |
788 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) | 799 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) |
789 .WillOnce(RunClosure()); | 800 .WillOnce(RunClosure()); |
790 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) | 801 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) |
791 .WillOnce(RunClosure()); | 802 .WillOnce(RunClosure()); |
792 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) | 803 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)) |
793 .WillOnce(RunClosure()); | 804 .WillOnce(RunClosure()); |
794 | 805 |
795 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) | 806 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) |
796 .WillOnce(RunPipelineStatusCB1WithStatus(PIPELINE_ERROR_READ)); | 807 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_READ)); |
797 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) | 808 EXPECT_CALL(*mocks_->demuxer(), Stop(_)) |
798 .WillOnce(RunClosure()); | 809 .WillOnce(RunClosure()); |
799 | 810 |
800 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, | 811 pipeline_->Seek(seek_time, base::Bind(&CallbackHelper::OnSeek, |
801 base::Unretained(&callbacks_))); | 812 base::Unretained(&callbacks_))); |
802 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); | 813 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); |
803 message_loop_.RunAllPending(); | 814 message_loop_.RunAllPending(); |
804 } | 815 } |
805 | 816 |
806 TEST_F(PipelineTest, StartTimeIsZero) { | 817 TEST_F(PipelineTest, StartTimeIsZero) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
873 base::TimeDelta::FromMilliseconds(500)); | 884 base::TimeDelta::FromMilliseconds(500)); |
874 | 885 |
875 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); | 886 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); |
876 | 887 |
877 // Arrange to trigger a time update while the demuxer is in the middle of | 888 // Arrange to trigger a time update while the demuxer is in the middle of |
878 // seeking. This update should be ignored by the pipeline and the clock should | 889 // seeking. This update should be ignored by the pipeline and the clock should |
879 // not get updated. | 890 // not get updated. |
880 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700); | 891 base::Closure closure = base::Bind(&RunTimeCB, audio_time_cb_, 300, 700); |
881 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) | 892 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) |
882 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run), | 893 .WillOnce(DoAll(InvokeWithoutArgs(&closure, &base::Closure::Run), |
883 RunPipelineStatusCB1())); | 894 RunPipelineStatusCB())); |
884 | 895 |
885 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) | 896 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) |
886 .WillOnce(RunClosure()); | 897 .WillOnce(RunClosure()); |
887 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) | 898 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) |
888 .WillOnce(RunClosure()); | 899 .WillOnce(RunClosure()); |
889 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(seek_time, _)) | 900 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(seek_time, _)) |
890 .WillOnce(RunPipelineStatusCB1()); | 901 .WillOnce(RunPipelineStatusCB()); |
891 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) | 902 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) |
892 .WillOnce(RunClosure()); | 903 .WillOnce(RunClosure()); |
893 | 904 |
894 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); | 905 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); |
895 DoSeek(seek_time); | 906 DoSeek(seek_time); |
896 | 907 |
897 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time); | 908 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time); |
898 | 909 |
899 // Now that the seek is complete, verify that time updates advance the current | 910 // Now that the seek is complete, verify that time updates advance the current |
900 // time. | 911 // time. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
950 TEST(PipelineStatusNotificationTest, ImmediateCallback) { | 961 TEST(PipelineStatusNotificationTest, ImmediateCallback) { |
951 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(0)); | 962 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(0)); |
952 } | 963 } |
953 | 964 |
954 // Test that different-thread, some-delay callback (the expected common case) | 965 // Test that different-thread, some-delay callback (the expected common case) |
955 // works correctly. | 966 // works correctly. |
956 TEST(PipelineStatusNotificationTest, DelayedCallback) { | 967 TEST(PipelineStatusNotificationTest, DelayedCallback) { |
957 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(20)); | 968 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(20)); |
958 } | 969 } |
959 | 970 |
971 class PipelineTeardownTest : public PipelineTest { | |
972 public: | |
973 enum TeardownState { | |
974 kPausing, | |
975 kFlushing, | |
976 kSeeking, | |
977 kPrerolling, | |
978 kStarting, | |
979 kPlaying, | |
980 }; | |
981 | |
982 enum StopOrError { | |
983 kStop, | |
984 kError, | |
985 }; | |
986 | |
987 PipelineTeardownTest() { | |
988 CreateAudioStream(); | |
989 MockDemuxerStreamVector streams; | |
990 streams.push_back(audio_stream()); | |
991 | |
992 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(3000)); | |
993 InitializeAudioDecoder(audio_stream()); | |
994 InitializeAudioRenderer(); | |
995 InitializePipeline(PIPELINE_OK); | |
996 } | |
997 | |
998 void RunTest(TeardownState state, StopOrError stop_or_error) { | |
999 InSequence s; | |
1000 switch (state) { | |
1001 case kPausing: | |
1002 case kFlushing: | |
1003 case kSeeking: | |
1004 case kPrerolling: | |
1005 case kStarting: | |
1006 if (stop_or_error == kStop) { | |
1007 ExpectSeekStop(state); | |
1008 } else { | |
1009 ExpectSeekError(state); | |
1010 } | |
1011 DoSeek(); | |
1012 break; | |
1013 | |
1014 case kPlaying: | |
1015 if (stop_or_error == kStop) { | |
1016 ExpectStop(); | |
1017 DoStop(); | |
1018 } else { | |
1019 ExpectPlaybackError(); | |
1020 DoPlaybackError(); | |
1021 } | |
1022 break; | |
1023 } | |
1024 } | |
1025 | |
1026 private: | |
1027 // TODO(scherkus): Why separate stop/error enums and helper functions? We do | |
Ami GONE FROM CHROMIUM
2012/08/09 04:41:43
rewrite comment.
scherkus (not reviewing)
2012/08/09 16:52:39
Done.
| |
1028 // radically different things whether teardown is invoked via stop vs error. | |
1029 // The teardown path should be the same, see http://crbug.com/110228 | |
1030 void ExpectSeekStop(TeardownState state) { | |
1031 base::Closure stop_cb = base::Bind( | |
1032 &CallbackHelper::OnStop, base::Unretained(&callbacks_)); | |
1033 | |
1034 if (state == kPausing) { | |
1035 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) | |
1036 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunClosure())); | |
1037 } else { | |
1038 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); | |
1039 } | |
1040 | |
1041 if (state == kFlushing) { | |
1042 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) | |
1043 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunClosure())); | |
1044 } else { | |
1045 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); | |
1046 } | |
1047 | |
1048 if (state == kSeeking) { | |
1049 EXPECT_CALL(*mocks_->demuxer(), Seek(_, _)) | |
1050 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunPipelineStatusCB())); | |
1051 } else { | |
1052 EXPECT_CALL(*mocks_->demuxer(), Seek(_, _)) | |
1053 .WillOnce(RunPipelineStatusCB()); | |
1054 } | |
1055 | |
1056 if (state == kPrerolling) { | |
1057 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _)) | |
1058 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunPipelineStatusCB())); | |
1059 } else { | |
1060 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _)) | |
1061 .WillOnce(RunPipelineStatusCB()); | |
1062 } | |
1063 | |
1064 if (state == kStarting) { | |
1065 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) | |
1066 .WillOnce(DoAll(Stop(pipeline_, stop_cb), RunClosure())); | |
1067 } else { | |
1068 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)).WillOnce(RunClosure()); | |
1069 } | |
1070 | |
1071 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); | |
1072 ExpectStop(); | |
1073 } | |
1074 | |
1075 void ExpectSeekError(TeardownState state) { | |
1076 SetSeekErrorExpectations(state); | |
1077 | |
1078 // Executed after the error is raised. | |
1079 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); | |
1080 EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure()); | |
1081 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure()); | |
1082 } | |
1083 | |
1084 void SetSeekErrorExpectations(TeardownState state) { | |
1085 if (state == kPausing) { | |
1086 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)) | |
1087 .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ), | |
1088 RunClosure())); | |
1089 return; | |
1090 } | |
1091 | |
1092 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); | |
1093 | |
1094 if (state == kFlushing) { | |
1095 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)) | |
1096 .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ), | |
1097 RunClosure())); | |
1098 return; | |
1099 } | |
1100 | |
1101 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); | |
1102 | |
1103 if (state == kSeeking) { | |
1104 EXPECT_CALL(*mocks_->demuxer(), Seek(_, _)) | |
1105 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_READ)); | |
1106 return; | |
1107 } | |
1108 | |
1109 EXPECT_CALL(*mocks_->demuxer(), Seek(_, _)) | |
1110 .WillOnce(RunPipelineStatusCB()); | |
1111 | |
1112 if (state == kPrerolling) { | |
1113 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _)) | |
1114 .WillOnce(RunPipelineStatusCBWithStatus(PIPELINE_ERROR_READ)); | |
1115 return; | |
1116 } | |
1117 | |
1118 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(_, _)) | |
1119 .WillOnce(RunPipelineStatusCB()); | |
1120 | |
1121 if (state == kStarting) { | |
1122 EXPECT_CALL(*mocks_->audio_renderer(), Play(_)) | |
1123 .WillOnce(DoAll(SetError(pipeline_, PIPELINE_ERROR_READ), | |
1124 RunClosure())); | |
1125 return; | |
1126 } | |
1127 | |
1128 NOTREACHED() << "Unexpected TeardownState: " << state; | |
1129 } | |
1130 | |
1131 void ExpectStop() { | |
1132 // TODO(scherkus): Don't pause+flush, see http://crbug.com/110228 | |
1133 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); | |
1134 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); | |
1135 EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure()); | |
1136 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure()); | |
1137 | |
1138 EXPECT_CALL(callbacks_, OnStop()); | |
1139 } | |
1140 | |
1141 void ExpectPlaybackError() { | |
1142 // TODO(scherkus): Don't pause+flush, see http://crbug.com/110228 | |
1143 EXPECT_CALL(*mocks_->audio_renderer(), Pause(_)).WillOnce(RunClosure()); | |
1144 EXPECT_CALL(*mocks_->audio_renderer(), Flush(_)).WillOnce(RunClosure()); | |
1145 EXPECT_CALL(*mocks_->demuxer(), Stop(_)).WillOnce(RunClosure()); | |
1146 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_)).WillOnce(RunClosure()); | |
1147 | |
1148 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)); | |
1149 } | |
1150 | |
1151 void DoSeek() { | |
1152 pipeline_->Seek(base::TimeDelta::FromSeconds(10), base::Bind( | |
1153 &CallbackHelper::OnSeek, base::Unretained(&callbacks_))); | |
1154 message_loop_.RunAllPending(); | |
1155 } | |
1156 | |
1157 void DoStop() { | |
1158 pipeline_->Stop(base::Bind( | |
1159 &CallbackHelper::OnStop, base::Unretained(&callbacks_))); | |
1160 message_loop_.RunAllPending(); | |
1161 } | |
1162 | |
1163 void DoPlaybackError() { | |
1164 pipeline_->SetErrorForTesting(PIPELINE_ERROR_READ); | |
1165 message_loop_.RunAllPending(); | |
1166 } | |
1167 | |
1168 DISALLOW_COPY_AND_ASSIGN(PipelineTeardownTest); | |
1169 }; | |
1170 | |
1171 #define INSTANTIATE_TEARDOWN_TEST(stop_or_error, state) \ | |
1172 TEST_F(PipelineTeardownTest, stop_or_error##_##state) { \ | |
1173 RunTest(k##state, k##stop_or_error); \ | |
1174 } | |
1175 | |
1176 INSTANTIATE_TEARDOWN_TEST(Stop, Pausing); | |
1177 INSTANTIATE_TEARDOWN_TEST(Stop, Flushing); | |
1178 INSTANTIATE_TEARDOWN_TEST(Stop, Seeking); | |
1179 INSTANTIATE_TEARDOWN_TEST(Stop, Prerolling); | |
1180 INSTANTIATE_TEARDOWN_TEST(Stop, Starting); | |
1181 INSTANTIATE_TEARDOWN_TEST(Stop, Playing); | |
1182 | |
1183 INSTANTIATE_TEARDOWN_TEST(Error, Pausing); | |
1184 INSTANTIATE_TEARDOWN_TEST(Error, Flushing); | |
1185 INSTANTIATE_TEARDOWN_TEST(Error, Seeking); | |
1186 INSTANTIATE_TEARDOWN_TEST(Error, Prerolling); | |
1187 INSTANTIATE_TEARDOWN_TEST(Error, Starting); | |
1188 INSTANTIATE_TEARDOWN_TEST(Error, Playing); | |
1189 | |
960 } // namespace media | 1190 } // namespace media |
OLD | NEW |