| OLD | NEW |
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 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/waitable_event.h" | 7 #include "base/waitable_event.h" |
| 8 #include "media/base/pipeline_impl.h" | 8 #include "media/base/pipeline_impl.h" |
| 9 #include "media/base/media_format.h" | 9 #include "media/base/media_format.h" |
| 10 #include "media/base/filters.h" | 10 #include "media/base/filters.h" |
| 11 #include "media/base/factory.h" | 11 #include "media/base/factory.h" |
| 12 #include "media/base/filter_host.h" | 12 #include "media/base/filter_host.h" |
| 13 #include "media/base/mock_filters.h" | 13 #include "media/base/mock_filters.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 15 |
| 16 using ::testing::DoAll; | 16 using ::testing::DoAll; |
| 17 using ::testing::Mock; | 17 using ::testing::Mock; |
| 18 using ::testing::Return; | 18 using ::testing::Return; |
| 19 using ::testing::StrictMock; | 19 using ::testing::StrictMock; |
| 20 | 20 |
| 21 namespace media { | 21 namespace media { |
| 22 | 22 |
| 23 // Used for setting expectations on pipeline callbacks. Using a StrictMock | 23 // Used for setting expectations on pipeline callbacks. Using a StrictMock |
| 24 // also lets us test for missing callbacks. | 24 // also lets us test for missing callbacks. |
| 25 class CallbackHelper { | 25 class CallbackHelper { |
| 26 public: | 26 public: |
| 27 CallbackHelper() {} | 27 CallbackHelper() {} |
| 28 virtual ~CallbackHelper() {} | 28 virtual ~CallbackHelper() {} |
| 29 | 29 |
| 30 MOCK_METHOD1(OnInitialize, void(bool result)); | 30 MOCK_METHOD1(OnStart, void(bool result)); |
| 31 MOCK_METHOD1(OnSeek, void(bool result)); | 31 MOCK_METHOD1(OnSeek, void(bool result)); |
| 32 MOCK_METHOD1(OnStop, void(bool result)); | 32 MOCK_METHOD1(OnStop, void(bool result)); |
| 33 | 33 |
| 34 private: | 34 private: |
| 35 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); | 35 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); |
| 36 }; | 36 }; |
| 37 | 37 |
| 38 // TODO(scherkus): even though some filters are initialized on separate | 38 // TODO(scherkus): even though some filters are initialized on separate |
| 39 // threads these test aren't flaky... why? It's because filters' Initialize() | 39 // threads these test aren't flaky... why? It's because filters' Initialize() |
| 40 // is executed on |message_loop_| and the mock filters instantly call | 40 // is executed on |message_loop_| and the mock filters instantly call |
| (...skipping 18 matching lines...) Expand all Loading... |
| 59 &CallbackHelper::OnStop)); | 59 &CallbackHelper::OnStop)); |
| 60 message_loop_.RunAllPending(); | 60 message_loop_.RunAllPending(); |
| 61 } | 61 } |
| 62 | 62 |
| 63 protected: | 63 protected: |
| 64 // Sets up expectations to allow the data source to initialize. | 64 // Sets up expectations to allow the data source to initialize. |
| 65 void InitializeDataSource() { | 65 void InitializeDataSource() { |
| 66 EXPECT_CALL(*mocks_->data_source(), Initialize("")) | 66 EXPECT_CALL(*mocks_->data_source(), Initialize("")) |
| 67 .WillOnce(DoAll(InitializationComplete(mocks_->data_source()), | 67 .WillOnce(DoAll(InitializationComplete(mocks_->data_source()), |
| 68 Return(true))); | 68 Return(true))); |
| 69 EXPECT_CALL(*mocks_->data_source(), SetPlaybackRate(0.0f)); |
| 69 EXPECT_CALL(*mocks_->data_source(), Stop()); | 70 EXPECT_CALL(*mocks_->data_source(), Stop()); |
| 70 } | 71 } |
| 71 | 72 |
| 72 // Sets up expectations to allow the demuxer to initialize. | 73 // Sets up expectations to allow the demuxer to initialize. |
| 73 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; | 74 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; |
| 74 void InitializeDemuxer(MockDemuxerStreamVector* streams) { | 75 void InitializeDemuxer(MockDemuxerStreamVector* streams) { |
| 75 EXPECT_CALL(*mocks_->demuxer(), Initialize(mocks_->data_source())) | 76 EXPECT_CALL(*mocks_->demuxer(), Initialize(mocks_->data_source())) |
| 76 .WillOnce(DoAll(InitializationComplete(mocks_->demuxer()), | 77 .WillOnce(DoAll(InitializationComplete(mocks_->demuxer()), |
| 77 Return(true))); | 78 Return(true))); |
| 78 EXPECT_CALL(*mocks_->demuxer(), GetNumberOfStreams()) | 79 EXPECT_CALL(*mocks_->demuxer(), GetNumberOfStreams()) |
| 79 .WillRepeatedly(Return(streams->size())); | 80 .WillRepeatedly(Return(streams->size())); |
| 81 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f)); |
| 80 EXPECT_CALL(*mocks_->demuxer(), Stop()); | 82 EXPECT_CALL(*mocks_->demuxer(), Stop()); |
| 81 | 83 |
| 82 // Configure the demuxer to return the streams. | 84 // Configure the demuxer to return the streams. |
| 83 for (size_t i = 0; i < streams->size(); ++i) { | 85 for (size_t i = 0; i < streams->size(); ++i) { |
| 84 scoped_refptr<DemuxerStream> stream = (*streams)[i]; | 86 scoped_refptr<DemuxerStream> stream = (*streams)[i]; |
| 85 EXPECT_CALL(*mocks_->demuxer(), GetStream(i)) | 87 EXPECT_CALL(*mocks_->demuxer(), GetStream(i)) |
| 86 .WillRepeatedly(Return(stream)); | 88 .WillRepeatedly(Return(stream)); |
| 87 } | 89 } |
| 88 } | 90 } |
| 89 | 91 |
| 90 // Sets up expectations to allow the video decoder to initialize. | 92 // Sets up expectations to allow the video decoder to initialize. |
| 91 void InitializeVideoDecoder(MockDemuxerStream* stream) { | 93 void InitializeVideoDecoder(MockDemuxerStream* stream) { |
| 92 EXPECT_CALL(*mocks_->video_decoder(), Initialize(stream)) | 94 EXPECT_CALL(*mocks_->video_decoder(), Initialize(stream)) |
| 93 .WillOnce(DoAll(InitializationComplete(mocks_->video_decoder()), | 95 .WillOnce(DoAll(InitializationComplete(mocks_->video_decoder()), |
| 94 Return(true))); | 96 Return(true))); |
| 97 EXPECT_CALL(*mocks_->video_decoder(), SetPlaybackRate(0.0f)); |
| 95 EXPECT_CALL(*mocks_->video_decoder(), Stop()); | 98 EXPECT_CALL(*mocks_->video_decoder(), Stop()); |
| 96 } | 99 } |
| 97 | 100 |
| 98 // Sets up expectations to allow the audio decoder to initialize. | 101 // Sets up expectations to allow the audio decoder to initialize. |
| 99 void InitializeAudioDecoder(MockDemuxerStream* stream) { | 102 void InitializeAudioDecoder(MockDemuxerStream* stream) { |
| 100 EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream)) | 103 EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream)) |
| 101 .WillOnce(DoAll(InitializationComplete(mocks_->audio_decoder()), | 104 .WillOnce(DoAll(InitializationComplete(mocks_->audio_decoder()), |
| 102 Return(true))); | 105 Return(true))); |
| 106 EXPECT_CALL(*mocks_->audio_decoder(), SetPlaybackRate(0.0f)); |
| 103 EXPECT_CALL(*mocks_->audio_decoder(), Stop()); | 107 EXPECT_CALL(*mocks_->audio_decoder(), Stop()); |
| 104 } | 108 } |
| 105 | 109 |
| 106 // Sets up expectations to allow the video renderer to initialize. | 110 // Sets up expectations to allow the video renderer to initialize. |
| 107 void InitializeVideoRenderer() { | 111 void InitializeVideoRenderer() { |
| 108 EXPECT_CALL(*mocks_->video_renderer(), Initialize(mocks_->video_decoder())) | 112 EXPECT_CALL(*mocks_->video_renderer(), Initialize(mocks_->video_decoder())) |
| 109 .WillOnce(DoAll(InitializationComplete(mocks_->video_renderer()), | 113 .WillOnce(DoAll(InitializationComplete(mocks_->video_renderer()), |
| 110 Return(true))); | 114 Return(true))); |
| 115 EXPECT_CALL(*mocks_->video_renderer(), SetPlaybackRate(0.0f)); |
| 111 EXPECT_CALL(*mocks_->video_renderer(), Stop()); | 116 EXPECT_CALL(*mocks_->video_renderer(), Stop()); |
| 112 } | 117 } |
| 113 | 118 |
| 114 // Sets up expectations to allow the audio renderer to initialize. | 119 // Sets up expectations to allow the audio renderer to initialize. |
| 115 void InitializeAudioRenderer() { | 120 void InitializeAudioRenderer() { |
| 116 EXPECT_CALL(*mocks_->audio_renderer(), Initialize(mocks_->audio_decoder())) | 121 EXPECT_CALL(*mocks_->audio_renderer(), Initialize(mocks_->audio_decoder())) |
| 117 .WillOnce(DoAll(InitializationComplete(mocks_->audio_renderer()), | 122 .WillOnce(DoAll(InitializationComplete(mocks_->audio_renderer()), |
| 118 Return(true))); | 123 Return(true))); |
| 124 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f)); |
| 125 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(0.0f)); |
| 119 EXPECT_CALL(*mocks_->audio_renderer(), Stop()); | 126 EXPECT_CALL(*mocks_->audio_renderer(), Stop()); |
| 120 } | 127 } |
| 121 | 128 |
| 122 // Sets up expectations on the callback and initializes the pipeline. Called | 129 // Sets up expectations on the callback and initializes the pipeline. Called |
| 123 // afters tests have set expectations any filters they wish to use. | 130 // afters tests have set expectations any filters they wish to use. |
| 124 void InitializePipeline(bool callback_result) { | 131 void InitializePipeline(bool callback_result) { |
| 125 // Expect an initialization callback. | 132 // Expect an initialization callback. |
| 126 EXPECT_CALL(callbacks_, OnInitialize(callback_result)); | 133 EXPECT_CALL(callbacks_, OnStart(callback_result)); |
| 127 pipeline_.Start(mocks_, "", | 134 pipeline_.Start(mocks_, "", |
| 128 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 135 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), |
| 129 &CallbackHelper::OnInitialize)); | 136 &CallbackHelper::OnStart)); |
| 130 message_loop_.RunAllPending(); | 137 message_loop_.RunAllPending(); |
| 131 } | 138 } |
| 132 | 139 |
| 133 // Fixture members. | 140 // Fixture members. |
| 134 StrictMock<CallbackHelper> callbacks_; | 141 StrictMock<CallbackHelper> callbacks_; |
| 135 MessageLoop message_loop_; | 142 MessageLoop message_loop_; |
| 136 PipelineImpl pipeline_; | 143 PipelineImpl pipeline_; |
| 137 scoped_refptr<media::MockFilterFactory> mocks_; | 144 scoped_refptr<media::MockFilterFactory> mocks_; |
| 138 | 145 |
| 139 private: | 146 private: |
| 140 DISALLOW_COPY_AND_ASSIGN(PipelineImplTest); | 147 DISALLOW_COPY_AND_ASSIGN(PipelineImplTest); |
| 141 }; | 148 }; |
| 142 | 149 |
| 150 // Test that playback controls methods no-op when the pipeline hasn't been |
| 151 // started. |
| 152 TEST_F(PipelineImplTest, NotStarted) { |
| 153 const base::TimeDelta kZero; |
| 154 |
| 155 // StrictMock<> will ensure these never get called, and valgrind/purify will |
| 156 // make sure the callbacks are instantly deleted. |
| 157 pipeline_.Start(NULL, "", |
| 158 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), |
| 159 &CallbackHelper::OnStart)); |
| 160 pipeline_.Stop(NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), |
| 161 &CallbackHelper::OnStop)); |
| 162 pipeline_.Seek(kZero, |
| 163 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), |
| 164 &CallbackHelper::OnSeek)); |
| 165 |
| 166 EXPECT_FALSE(pipeline_.IsRunning()); |
| 167 EXPECT_FALSE(pipeline_.IsInitialized()); |
| 168 EXPECT_FALSE(pipeline_.IsRendered("")); |
| 169 EXPECT_FALSE(pipeline_.IsRendered(AudioDecoder::major_mime_type())); |
| 170 EXPECT_FALSE(pipeline_.IsRendered(VideoDecoder::major_mime_type())); |
| 171 |
| 172 // Setting should still work. |
| 173 EXPECT_EQ(0.0f, pipeline_.GetPlaybackRate()); |
| 174 pipeline_.SetPlaybackRate(-1.0f); |
| 175 EXPECT_EQ(0.0f, pipeline_.GetPlaybackRate()); |
| 176 pipeline_.SetPlaybackRate(1.0f); |
| 177 EXPECT_EQ(1.0f, pipeline_.GetPlaybackRate()); |
| 178 |
| 179 // Setting should still work. |
| 180 EXPECT_EQ(0.0f, pipeline_.GetVolume()); |
| 181 pipeline_.SetVolume(-1.0f); |
| 182 EXPECT_EQ(0.0f, pipeline_.GetVolume()); |
| 183 pipeline_.SetVolume(1.0f); |
| 184 EXPECT_EQ(1.0f, pipeline_.GetVolume()); |
| 185 |
| 186 EXPECT_TRUE(kZero == pipeline_.GetTime()); |
| 187 EXPECT_TRUE(kZero == pipeline_.GetBufferedTime()); |
| 188 EXPECT_TRUE(kZero == pipeline_.GetDuration()); |
| 189 |
| 190 EXPECT_EQ(0, pipeline_.GetBufferedBytes()); |
| 191 EXPECT_EQ(0, pipeline_.GetTotalBytes()); |
| 192 |
| 193 // Should always get set to zero. |
| 194 size_t width = 1u; |
| 195 size_t height = 1u; |
| 196 pipeline_.GetVideoSize(&width, &height); |
| 197 EXPECT_EQ(0u, width); |
| 198 EXPECT_EQ(0u, height); |
| 199 |
| 200 EXPECT_EQ(PIPELINE_OK, pipeline_.GetError()); |
| 201 } |
| 202 |
| 143 TEST_F(PipelineImplTest, NeverInitializes) { | 203 TEST_F(PipelineImplTest, NeverInitializes) { |
| 144 EXPECT_CALL(*mocks_->data_source(), Initialize("")) | 204 EXPECT_CALL(*mocks_->data_source(), Initialize("")) |
| 145 .WillOnce(Return(true)); | 205 .WillOnce(Return(true)); |
| 146 EXPECT_CALL(*mocks_->data_source(), Stop()); | 206 EXPECT_CALL(*mocks_->data_source(), Stop()); |
| 147 | 207 |
| 148 // This test hangs during initialization by never calling | 208 // This test hangs during initialization by never calling |
| 149 // InitializationComplete(). StrictMock<> will ensure that the callback is | 209 // InitializationComplete(). StrictMock<> will ensure that the callback is |
| 150 // never executed. | 210 // never executed. |
| 151 pipeline_.Start(mocks_, "", | 211 pipeline_.Start(mocks_, "", |
| 152 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), | 212 NewCallback(reinterpret_cast<CallbackHelper*>(&callbacks_), |
| 153 &CallbackHelper::OnInitialize)); | 213 &CallbackHelper::OnStart)); |
| 154 message_loop_.RunAllPending(); | 214 message_loop_.RunAllPending(); |
| 155 | 215 |
| 156 EXPECT_FALSE(pipeline_.IsInitialized()); | 216 EXPECT_FALSE(pipeline_.IsInitialized()); |
| 157 EXPECT_EQ(PIPELINE_OK, pipeline_.GetError()); | 217 EXPECT_EQ(PIPELINE_OK, pipeline_.GetError()); |
| 158 | 218 |
| 159 // Because our callback will get executed when the test tears down, we'll | 219 // Because our callback will get executed when the test tears down, we'll |
| 160 // verify that nothing has been called, then set our expectation for the call | 220 // verify that nothing has been called, then set our expectation for the call |
| 161 // made during tear down. | 221 // made during tear down. |
| 162 Mock::VerifyAndClear(&callbacks_); | 222 Mock::VerifyAndClear(&callbacks_); |
| 163 EXPECT_CALL(callbacks_, OnInitialize(false)); | 223 EXPECT_CALL(callbacks_, OnStart(false)); |
| 164 } | 224 } |
| 165 | 225 |
| 166 TEST_F(PipelineImplTest, RequiredFilterMissing) { | 226 TEST_F(PipelineImplTest, RequiredFilterMissing) { |
| 167 mocks_->set_creation_successful(false); | 227 mocks_->set_creation_successful(false); |
| 168 | 228 |
| 169 InitializePipeline(false); | 229 InitializePipeline(false); |
| 170 EXPECT_FALSE(pipeline_.IsInitialized()); | 230 EXPECT_FALSE(pipeline_.IsInitialized()); |
| 171 EXPECT_EQ(PIPELINE_ERROR_REQUIRED_FILTER_MISSING, | 231 EXPECT_EQ(PIPELINE_ERROR_REQUIRED_FILTER_MISSING, |
| 172 pipeline_.GetError()); | 232 pipeline_.GetError()); |
| 173 } | 233 } |
| 174 | 234 |
| 175 TEST_F(PipelineImplTest, URLNotFound) { | 235 TEST_F(PipelineImplTest, URLNotFound) { |
| 176 EXPECT_CALL(*mocks_->data_source(), Initialize("")) | 236 EXPECT_CALL(*mocks_->data_source(), Initialize("")) |
| 177 .WillOnce(DoAll(Error(mocks_->data_source(), | 237 .WillOnce(DoAll(Error(mocks_->data_source(), |
| 178 PIPELINE_ERROR_URL_NOT_FOUND), | 238 PIPELINE_ERROR_URL_NOT_FOUND), |
| 179 Return(false))); | 239 Return(false))); |
| 180 EXPECT_CALL(*mocks_->data_source(), Stop()); | 240 EXPECT_CALL(*mocks_->data_source(), Stop()); |
| 181 | 241 |
| 182 InitializePipeline(false); | 242 InitializePipeline(false); |
| 183 EXPECT_FALSE(pipeline_.IsInitialized()); | 243 EXPECT_FALSE(pipeline_.IsInitialized()); |
| 184 EXPECT_EQ(PIPELINE_ERROR_URL_NOT_FOUND, pipeline_.GetError()); | 244 EXPECT_EQ(PIPELINE_ERROR_URL_NOT_FOUND, pipeline_.GetError()); |
| 185 } | 245 } |
| 186 | 246 |
| 187 TEST_F(PipelineImplTest, NoStreams) { | 247 TEST_F(PipelineImplTest, NoStreams) { |
| 188 MockDemuxerStreamVector streams; | 248 // Manually set these expecations because SetPlaybackRate() is not called if |
| 189 InitializeDataSource(); | 249 // we cannot fully initialize the pipeline. |
| 190 InitializeDemuxer(&streams); | 250 EXPECT_CALL(*mocks_->data_source(), Initialize("")) |
| 251 .WillOnce(DoAll(InitializationComplete(mocks_->data_source()), |
| 252 Return(true))); |
| 253 EXPECT_CALL(*mocks_->data_source(), Stop()); |
| 254 |
| 255 EXPECT_CALL(*mocks_->demuxer(), Initialize(mocks_->data_source())) |
| 256 .WillOnce(DoAll(InitializationComplete(mocks_->demuxer()), |
| 257 Return(true))); |
| 258 EXPECT_CALL(*mocks_->demuxer(), GetNumberOfStreams()) |
| 259 .WillRepeatedly(Return(0)); |
| 260 EXPECT_CALL(*mocks_->demuxer(), Stop()); |
| 191 | 261 |
| 192 InitializePipeline(false); | 262 InitializePipeline(false); |
| 193 EXPECT_FALSE(pipeline_.IsInitialized()); | 263 EXPECT_FALSE(pipeline_.IsInitialized()); |
| 194 EXPECT_EQ(PIPELINE_ERROR_COULD_NOT_RENDER, pipeline_.GetError()); | 264 EXPECT_EQ(PIPELINE_ERROR_COULD_NOT_RENDER, pipeline_.GetError()); |
| 195 } | 265 } |
| 196 | 266 |
| 197 TEST_F(PipelineImplTest, AudioStream) { | 267 TEST_F(PipelineImplTest, AudioStream) { |
| 198 scoped_refptr<StrictMock<MockDemuxerStream> > stream = | 268 scoped_refptr<StrictMock<MockDemuxerStream> > stream = |
| 199 new StrictMock<MockDemuxerStream>("audio/x-foo"); | 269 new StrictMock<MockDemuxerStream>("audio/x-foo"); |
| 200 MockDemuxerStreamVector streams; | 270 MockDemuxerStreamVector streams; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 // The audio renderer should receive a call to SetVolume(). | 373 // The audio renderer should receive a call to SetVolume(). |
| 304 float expected = 0.5f; | 374 float expected = 0.5f; |
| 305 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(expected)); | 375 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(expected)); |
| 306 | 376 |
| 307 // Initialize then set volume! | 377 // Initialize then set volume! |
| 308 InitializePipeline(true); | 378 InitializePipeline(true); |
| 309 pipeline_.SetVolume(expected); | 379 pipeline_.SetVolume(expected); |
| 310 } | 380 } |
| 311 | 381 |
| 312 } // namespace media | 382 } // namespace media |
| OLD | NEW |