OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <string> | 5 #include <string> |
6 | 6 |
| 7 #include "base/bind.h" |
7 #include "base/callback.h" | 8 #include "base/callback.h" |
8 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
9 #include "base/threading/simple_thread.h" | 10 #include "base/threading/simple_thread.h" |
10 #include "media/base/pipeline_impl.h" | 11 #include "media/base/pipeline_impl.h" |
11 #include "media/base/filters.h" | 12 #include "media/base/filters.h" |
12 #include "media/base/filter_host.h" | 13 #include "media/base/filter_host.h" |
13 #include "media/base/mock_callback.h" | 14 #include "media/base/mock_callback.h" |
14 #include "media/base/mock_filters.h" | 15 #include "media/base/mock_filters.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
16 | 17 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 // threads these test aren't flaky... why? It's because filters' Initialize() | 57 // threads these test aren't flaky... why? It's because filters' Initialize() |
57 // is executed on |message_loop_| and the mock filters instantly call | 58 // is executed on |message_loop_| and the mock filters instantly call |
58 // InitializationComplete(), which keeps the pipeline humming along. If | 59 // InitializationComplete(), which keeps the pipeline humming along. If |
59 // either filters don't call InitializationComplete() immediately or filter | 60 // either filters don't call InitializationComplete() immediately or filter |
60 // initialization is moved to a separate thread this test will become flaky. | 61 // initialization is moved to a separate thread this test will become flaky. |
61 class PipelineImplTest : public ::testing::Test { | 62 class PipelineImplTest : public ::testing::Test { |
62 public: | 63 public: |
63 PipelineImplTest() | 64 PipelineImplTest() |
64 : pipeline_(new PipelineImpl(&message_loop_)) { | 65 : pipeline_(new PipelineImpl(&message_loop_)) { |
65 pipeline_->Init( | 66 pipeline_->Init( |
66 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 67 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), |
67 &CallbackHelper::OnEnded), | 68 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), |
68 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 69 PipelineStatusCB()); |
69 &CallbackHelper::OnError), | |
70 static_cast<PipelineStatusCallback*>(NULL)); | |
71 mocks_.reset(new MockFilterCollection()); | 70 mocks_.reset(new MockFilterCollection()); |
72 | 71 |
73 // InitializeDemuxer adds overriding expectations for expected non-NULL | 72 // InitializeDemuxer adds overriding expectations for expected non-NULL |
74 // streams. | 73 // streams. |
75 DemuxerStream* null_pointer = NULL; | 74 DemuxerStream* null_pointer = NULL; |
76 EXPECT_CALL(*mocks_->demuxer(), GetStream(_)) | 75 EXPECT_CALL(*mocks_->demuxer(), GetStream(_)) |
77 .WillRepeatedly(Return(null_pointer)); | 76 .WillRepeatedly(Return(null_pointer)); |
78 | 77 |
79 EXPECT_CALL(*mocks_->demuxer(), GetStartTime()) | 78 EXPECT_CALL(*mocks_->demuxer(), GetStartTime()) |
80 .WillRepeatedly(Return(base::TimeDelta())); | 79 .WillRepeatedly(Return(base::TimeDelta())); |
81 } | 80 } |
82 | 81 |
83 virtual ~PipelineImplTest() { | 82 virtual ~PipelineImplTest() { |
84 if (!pipeline_->IsRunning()) { | 83 if (!pipeline_->IsRunning()) { |
85 return; | 84 return; |
86 } | 85 } |
87 | 86 |
88 // Expect a stop callback if we were started. | 87 // Expect a stop callback if we were started. |
89 EXPECT_CALL(callbacks_, OnStop(PIPELINE_OK)); | 88 EXPECT_CALL(callbacks_, OnStop(PIPELINE_OK)); |
90 pipeline_->Stop(NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 89 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop, |
91 &CallbackHelper::OnStop)); | 90 base::Unretained(&callbacks_))); |
92 message_loop_.RunAllPending(); | 91 message_loop_.RunAllPending(); |
93 | 92 |
94 mocks_.reset(); | 93 mocks_.reset(); |
95 } | 94 } |
96 | 95 |
97 protected: | 96 protected: |
98 // Sets up expectations to allow the demuxer to initialize. | 97 // Sets up expectations to allow the demuxer to initialize. |
99 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; | 98 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; |
100 void InitializeDemuxer(MockDemuxerStreamVector* streams, | 99 void InitializeDemuxer(MockDemuxerStreamVector* streams, |
101 const base::TimeDelta& duration) { | 100 const base::TimeDelta& duration) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 | 205 |
207 bool run_build = true; | 206 bool run_build = true; |
208 if (url.find(kRawMediaScheme) == 0) | 207 if (url.find(kRawMediaScheme) == 0) |
209 run_build = false; | 208 run_build = false; |
210 | 209 |
211 pipeline_->Start(mocks_->filter_collection(true, | 210 pipeline_->Start(mocks_->filter_collection(true, |
212 true, | 211 true, |
213 run_build, | 212 run_build, |
214 build_status), | 213 build_status), |
215 url, | 214 url, |
216 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 215 base::Bind(&CallbackHelper::OnStart, |
217 &CallbackHelper::OnStart)); | 216 base::Unretained(&callbacks_))); |
218 | 217 |
219 message_loop_.RunAllPending(); | 218 message_loop_.RunAllPending(); |
220 } | 219 } |
221 | 220 |
222 void CreateAudioStream() { | 221 void CreateAudioStream() { |
223 audio_stream_ = CreateStream(DemuxerStream::AUDIO); | 222 audio_stream_ = CreateStream(DemuxerStream::AUDIO); |
224 } | 223 } |
225 | 224 |
226 void CreateVideoStream() { | 225 void CreateVideoStream() { |
227 video_stream_ = CreateStream(DemuxerStream::VIDEO); | 226 video_stream_ = CreateStream(DemuxerStream::VIDEO); |
(...skipping 25 matching lines...) Expand all Loading... |
253 EXPECT_CALL(*mocks_->video_renderer(), Seek(seek_time, _)) | 252 EXPECT_CALL(*mocks_->video_renderer(), Seek(seek_time, _)) |
254 .WillOnce(Invoke(&RunFilterStatusCB)); | 253 .WillOnce(Invoke(&RunFilterStatusCB)); |
255 } | 254 } |
256 | 255 |
257 // We expect a successful seek callback. | 256 // We expect a successful seek callback. |
258 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); | 257 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK)); |
259 } | 258 } |
260 | 259 |
261 void DoSeek(const base::TimeDelta& seek_time) { | 260 void DoSeek(const base::TimeDelta& seek_time) { |
262 pipeline_->Seek(seek_time, | 261 pipeline_->Seek(seek_time, |
263 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 262 base::Bind(&CallbackHelper::OnSeek, |
264 &CallbackHelper::OnSeek)); | 263 base::Unretained(&callbacks_))); |
265 | 264 |
266 // We expect the time to be updated only after the seek has completed. | 265 // We expect the time to be updated only after the seek has completed. |
267 EXPECT_NE(seek_time, pipeline_->GetCurrentTime()); | 266 EXPECT_NE(seek_time, pipeline_->GetCurrentTime()); |
268 message_loop_.RunAllPending(); | 267 message_loop_.RunAllPending(); |
269 EXPECT_EQ(seek_time, pipeline_->GetCurrentTime()); | 268 EXPECT_EQ(seek_time, pipeline_->GetCurrentTime()); |
270 } | 269 } |
271 | 270 |
272 // Fixture members. | 271 // Fixture members. |
273 StrictMock<CallbackHelper> callbacks_; | 272 StrictMock<CallbackHelper> callbacks_; |
274 MessageLoop message_loop_; | 273 MessageLoop message_loop_; |
275 scoped_refptr<PipelineImpl> pipeline_; | 274 scoped_refptr<PipelineImpl> pipeline_; |
276 scoped_ptr<media::MockFilterCollection> mocks_; | 275 scoped_ptr<media::MockFilterCollection> mocks_; |
277 scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream_; | 276 scoped_refptr<StrictMock<MockDemuxerStream> > audio_stream_; |
278 scoped_refptr<StrictMock<MockDemuxerStream> > video_stream_; | 277 scoped_refptr<StrictMock<MockDemuxerStream> > video_stream_; |
279 | 278 |
280 private: | 279 private: |
281 DISALLOW_COPY_AND_ASSIGN(PipelineImplTest); | 280 DISALLOW_COPY_AND_ASSIGN(PipelineImplTest); |
282 }; | 281 }; |
283 | 282 |
284 // Test that playback controls methods no-op when the pipeline hasn't been | 283 // Test that playback controls methods no-op when the pipeline hasn't been |
285 // started. | 284 // started. |
286 TEST_F(PipelineImplTest, NotStarted) { | 285 TEST_F(PipelineImplTest, NotStarted) { |
287 const base::TimeDelta kZero; | 286 const base::TimeDelta kZero; |
288 | 287 |
289 // StrictMock<> will ensure these never get called, and valgrind/purify will | 288 // StrictMock<> will ensure these never get called, and valgrind/purify will |
290 // make sure the callbacks are instantly deleted. | 289 // make sure the callbacks are instantly deleted. |
291 pipeline_->Stop(NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 290 pipeline_->Stop(base::Bind(&CallbackHelper::OnStop, |
292 &CallbackHelper::OnStop)); | 291 base::Unretained(&callbacks_))); |
293 pipeline_->Seek(kZero, | 292 pipeline_->Seek(kZero, |
294 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 293 base::Bind(&CallbackHelper::OnSeek, |
295 &CallbackHelper::OnSeek)); | 294 base::Unretained(&callbacks_))); |
296 | 295 |
297 EXPECT_FALSE(pipeline_->IsRunning()); | 296 EXPECT_FALSE(pipeline_->IsRunning()); |
298 EXPECT_FALSE(pipeline_->IsInitialized()); | 297 EXPECT_FALSE(pipeline_->IsInitialized()); |
299 EXPECT_FALSE(pipeline_->HasAudio()); | 298 EXPECT_FALSE(pipeline_->HasAudio()); |
300 EXPECT_FALSE(pipeline_->HasVideo()); | 299 EXPECT_FALSE(pipeline_->HasVideo()); |
301 | 300 |
302 // Setting should still work. | 301 // Setting should still work. |
303 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate()); | 302 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate()); |
304 pipeline_->SetPlaybackRate(-1.0f); | 303 pipeline_->SetPlaybackRate(-1.0f); |
305 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate()); | 304 EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate()); |
(...skipping 24 matching lines...) Expand all Loading... |
330 | 329 |
331 TEST_F(PipelineImplTest, NeverInitializes) { | 330 TEST_F(PipelineImplTest, NeverInitializes) { |
332 // This test hangs during initialization by never calling | 331 // This test hangs during initialization by never calling |
333 // InitializationComplete(). StrictMock<> will ensure that the callback is | 332 // InitializationComplete(). StrictMock<> will ensure that the callback is |
334 // never executed. | 333 // never executed. |
335 pipeline_->Start(mocks_->filter_collection(false, | 334 pipeline_->Start(mocks_->filter_collection(false, |
336 false, | 335 false, |
337 true, | 336 true, |
338 PIPELINE_OK), | 337 PIPELINE_OK), |
339 "", | 338 "", |
340 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 339 base::Bind(&CallbackHelper::OnStart, |
341 &CallbackHelper::OnStart)); | 340 base::Unretained(&callbacks_))); |
342 message_loop_.RunAllPending(); | 341 message_loop_.RunAllPending(); |
343 | 342 |
344 EXPECT_FALSE(pipeline_->IsInitialized()); | 343 EXPECT_FALSE(pipeline_->IsInitialized()); |
345 | 344 |
346 // Because our callback will get executed when the test tears down, we'll | 345 // Because our callback will get executed when the test tears down, we'll |
347 // verify that nothing has been called, then set our expectation for the call | 346 // verify that nothing has been called, then set our expectation for the call |
348 // made during tear down. | 347 // made during tear down. |
349 Mock::VerifyAndClear(&callbacks_); | 348 Mock::VerifyAndClear(&callbacks_); |
350 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK)); | 349 EXPECT_CALL(callbacks_, OnStart(PIPELINE_OK)); |
351 } | 350 } |
352 | 351 |
353 TEST_F(PipelineImplTest, RequiredFilterMissing) { | 352 TEST_F(PipelineImplTest, RequiredFilterMissing) { |
354 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING)); | 353 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING)); |
355 | 354 |
356 // Sets up expectations on the callback and initializes the pipeline. Called | 355 // Sets up expectations on the callback and initializes the pipeline. Called |
357 // after tests have set expectations any filters they wish to use. | 356 // after tests have set expectations any filters they wish to use. |
358 // Expect an initialization callback. | 357 // Expect an initialization callback. |
359 EXPECT_CALL(callbacks_, OnStart(PIPELINE_ERROR_REQUIRED_FILTER_MISSING)); | 358 EXPECT_CALL(callbacks_, OnStart(PIPELINE_ERROR_REQUIRED_FILTER_MISSING)); |
360 | 359 |
361 // Create a filter collection with missing filter. | 360 // Create a filter collection with missing filter. |
362 FilterCollection* collection = | 361 FilterCollection* collection = |
363 mocks_->filter_collection(false, | 362 mocks_->filter_collection(false, |
364 true, | 363 true, |
365 true, | 364 true, |
366 PIPELINE_ERROR_REQUIRED_FILTER_MISSING); | 365 PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
367 pipeline_->Start(collection, "", | 366 pipeline_->Start(collection, "", |
368 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 367 base::Bind(&CallbackHelper::OnStart, |
369 &CallbackHelper::OnStart)); | 368 base::Unretained(&callbacks_))); |
370 message_loop_.RunAllPending(); | 369 message_loop_.RunAllPending(); |
371 | 370 |
372 EXPECT_FALSE(pipeline_->IsInitialized()); | 371 EXPECT_FALSE(pipeline_->IsInitialized()); |
373 } | 372 } |
374 | 373 |
375 TEST_F(PipelineImplTest, URLNotFound) { | 374 TEST_F(PipelineImplTest, URLNotFound) { |
376 // TODO(acolwell,fischman): Since OnStart() is getting called with an error | 375 // TODO(acolwell,fischman): Since OnStart() is getting called with an error |
377 // code already, OnError() doesn't also need to get called. Fix the pipeline | 376 // code already, OnError() doesn't also need to get called. Fix the pipeline |
378 // (and it's consumers!) so that OnError doesn't need to be called after | 377 // (and it's consumers!) so that OnError doesn't need to be called after |
379 // another callback has already reported the error. Same applies to NoStreams | 378 // another callback has already reported the error. Same applies to NoStreams |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 pipeline_->SetPlaybackRate(playback_rate); | 791 pipeline_->SetPlaybackRate(playback_rate); |
793 message_loop_.RunAllPending(); | 792 message_loop_.RunAllPending(); |
794 | 793 |
795 InSequence s; | 794 InSequence s; |
796 | 795 |
797 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); | 796 base::TimeDelta seek_time = base::TimeDelta::FromSeconds(5); |
798 | 797 |
799 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) | 798 EXPECT_CALL(*mocks_->demuxer(), Seek(seek_time, _)) |
800 .WillOnce(Invoke(&SendReadErrorToCB)); | 799 .WillOnce(Invoke(&SendReadErrorToCB)); |
801 | 800 |
802 pipeline_->Seek(seek_time, NewCallback( | 801 pipeline_->Seek(seek_time,base::Bind(&CallbackHelper::OnSeek, |
803 reinterpret_cast<CallbackHelper*>(&callbacks_), &CallbackHelper::OnSeek)); | 802 base::Unretained(&callbacks_))); |
804 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); | 803 EXPECT_CALL(callbacks_, OnSeek(PIPELINE_ERROR_READ)); |
805 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)); | 804 EXPECT_CALL(callbacks_, OnError(PIPELINE_ERROR_READ)); |
806 message_loop_.RunAllPending(); | 805 message_loop_.RunAllPending(); |
807 } | 806 } |
808 | 807 |
809 TEST_F(PipelineImplTest, StartTimeIsZero) { | 808 TEST_F(PipelineImplTest, StartTimeIsZero) { |
810 CreateVideoStream(); | 809 CreateVideoStream(); |
811 MockDemuxerStreamVector streams; | 810 MockDemuxerStreamVector streams; |
812 streams.push_back(video_stream()); | 811 streams.push_back(video_stream()); |
813 | 812 |
(...skipping 29 matching lines...) Expand all Loading... |
843 EXPECT_TRUE(pipeline_->IsInitialized()); | 842 EXPECT_TRUE(pipeline_->IsInitialized()); |
844 EXPECT_FALSE(pipeline_->HasAudio()); | 843 EXPECT_FALSE(pipeline_->HasAudio()); |
845 EXPECT_TRUE(pipeline_->HasVideo()); | 844 EXPECT_TRUE(pipeline_->HasVideo()); |
846 | 845 |
847 EXPECT_EQ(kStartTime, pipeline_->GetCurrentTime()); | 846 EXPECT_EQ(kStartTime, pipeline_->GetCurrentTime()); |
848 } | 847 } |
849 | 848 |
850 class FlexibleCallbackRunner : public base::DelegateSimpleThread::Delegate { | 849 class FlexibleCallbackRunner : public base::DelegateSimpleThread::Delegate { |
851 public: | 850 public: |
852 FlexibleCallbackRunner(int delayInMs, PipelineStatus status, | 851 FlexibleCallbackRunner(int delayInMs, PipelineStatus status, |
853 PipelineStatusCallback* callback) | 852 const PipelineStatusCB& callback) |
854 : delayInMs_(delayInMs), status_(status), callback_(callback) { | 853 : delayInMs_(delayInMs), status_(status), callback_(callback) { |
855 if (delayInMs_ < 0) { | 854 if (delayInMs_ < 0) { |
856 callback_->Run(status_); | 855 callback_.Run(status_); |
857 return; | 856 return; |
858 } | 857 } |
859 } | 858 } |
860 virtual void Run() { | 859 virtual void Run() { |
861 if (delayInMs_ < 0) return; | 860 if (delayInMs_ < 0) return; |
862 base::PlatformThread::Sleep(delayInMs_); | 861 base::PlatformThread::Sleep(delayInMs_); |
863 callback_->Run(status_); | 862 callback_.Run(status_); |
864 } | 863 } |
865 | 864 |
866 private: | 865 private: |
867 int delayInMs_; | 866 int delayInMs_; |
868 PipelineStatus status_; | 867 PipelineStatus status_; |
869 scoped_ptr<PipelineStatusCallback> callback_; | 868 PipelineStatusCB callback_; |
870 }; | 869 }; |
871 | 870 |
872 void TestPipelineStatusNotification(int delayInMs) { | 871 void TestPipelineStatusNotification(int delayInMs) { |
873 PipelineStatusNotification note; | 872 PipelineStatusNotification note; |
874 // Arbitrary error value we expect to fish out of the notification after the | 873 // Arbitrary error value we expect to fish out of the notification after the |
875 // callback is fired. | 874 // callback is fired. |
876 const PipelineStatus expected_error = PIPELINE_ERROR_URL_NOT_FOUND; | 875 const PipelineStatus expected_error = PIPELINE_ERROR_URL_NOT_FOUND; |
877 FlexibleCallbackRunner runner(delayInMs, expected_error, note.Callback()); | 876 FlexibleCallbackRunner runner(delayInMs, expected_error, note.Callback()); |
878 base::DelegateSimpleThread thread(&runner, "FlexibleCallbackRunner"); | 877 base::DelegateSimpleThread thread(&runner, "FlexibleCallbackRunner"); |
879 thread.Start(); | 878 thread.Start(); |
(...skipping 12 matching lines...) Expand all Loading... |
892 TestPipelineStatusNotification(0); | 891 TestPipelineStatusNotification(0); |
893 } | 892 } |
894 | 893 |
895 // Test that different-thread, some-delay callback (the expected common case) | 894 // Test that different-thread, some-delay callback (the expected common case) |
896 // works correctly. | 895 // works correctly. |
897 TEST(PipelineStatusNotificationTest, DelayedCallback) { | 896 TEST(PipelineStatusNotificationTest, DelayedCallback) { |
898 TestPipelineStatusNotification(20); | 897 TestPipelineStatusNotification(20); |
899 } | 898 } |
900 | 899 |
901 } // namespace media | 900 } // namespace media |
OLD | NEW |