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