OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <vector> |
| 6 |
| 7 #include "base/message_loop.h" |
| 8 #include "base/synchronization/waitable_event.h" |
| 9 #include "media/audio/audio_manager.h" |
| 10 #include "media/audio/simple_sources.h" |
| 11 #include "media/audio/virtual_audio_input_stream.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 |
| 14 namespace media { |
| 15 |
| 16 class MockInputCallback : public AudioInputStream::AudioInputCallback { |
| 17 public: |
| 18 MockInputCallback() {} |
| 19 virtual void OnData(AudioInputStream* stream, const uint8* data, |
| 20 uint32 size, uint32 hardware_delay_bytes, |
| 21 double volume) {} |
| 22 virtual void OnClose(AudioInputStream* stream) {} |
| 23 virtual void OnError(AudioInputStream* stream, int code) {} |
| 24 |
| 25 private: |
| 26 DISALLOW_COPY_AND_ASSIGN(MockInputCallback); |
| 27 }; |
| 28 |
| 29 class VirtualAudioInputStreamTest : public testing::Test { |
| 30 public: |
| 31 VirtualAudioInputStreamTest() |
| 32 : audio_manager_(AudioManager::Create()), |
| 33 params_( |
| 34 AudioParameters::AUDIO_VIRTUAL,CHANNEL_LAYOUT_MONO, 8000, 8, 128), |
| 35 output_params_( |
| 36 AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 8000, 8, |
| 37 128), |
| 38 stream_(NULL), |
| 39 source_(CHANNEL_LAYOUT_STEREO, 200.0, 128), |
| 40 done_(false, false) { |
| 41 } |
| 42 |
| 43 void StartStreamAndRunTestsOnAudioThread(int num_output_streams, |
| 44 int num_callback_iterations, |
| 45 int num_streams_removed_per_round, |
| 46 int num_expected_source_callbacks) { |
| 47 ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
| 48 stream_->Open(); |
| 49 stream_->Start(&input_callback_); |
| 50 AddStreamsAndDoCallbacks(num_output_streams, |
| 51 num_callback_iterations, |
| 52 num_streams_removed_per_round, |
| 53 num_expected_source_callbacks); |
| 54 } |
| 55 |
| 56 void AddStreamsAndDoCallbacks(int num_output_streams, |
| 57 int num_callback_iterations, |
| 58 int num_streams_removed_per_round, |
| 59 int num_expected_source_callbacks) { |
| 60 ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
| 61 |
| 62 for (int i = 0; i < num_output_streams; ++i) { |
| 63 AudioOutputStream* output_stream = |
| 64 audio_manager_->MakeAudioOutputStream(output_params_); |
| 65 DCHECK(output_stream); |
| 66 output_streams_.push_back(output_stream); |
| 67 |
| 68 output_stream->Open(); |
| 69 output_stream->Start(&source_); |
| 70 } |
| 71 |
| 72 if (num_output_streams == 0 && num_streams_removed_per_round > 0) { |
| 73 AudioOutputStream* output_stream = output_streams_.back(); |
| 74 output_streams_.pop_back(); |
| 75 output_stream->Stop(); |
| 76 output_stream->Close(); |
| 77 } |
| 78 |
| 79 if (num_callback_iterations > 0) { |
| 80 // Force the next callback to be immediate. |
| 81 stream_->buffer_duration_ms_ = base::TimeDelta(); |
| 82 audio_manager_->GetMessageLoop()->PostTask( |
| 83 FROM_HERE, base::Bind( |
| 84 &VirtualAudioInputStreamTest::AddStreamsAndDoCallbacks, |
| 85 base::Unretained(this), |
| 86 0, |
| 87 --num_callback_iterations, |
| 88 num_streams_removed_per_round, |
| 89 num_expected_source_callbacks)); |
| 90 } else { |
| 91 // Finish the test. |
| 92 EXPECT_EQ(num_expected_source_callbacks, source_.callbacks()); |
| 93 EXPECT_EQ(0, source_.errors()); |
| 94 |
| 95 for (std::vector<AudioOutputStream*>::iterator it = |
| 96 output_streams_.begin(); it != output_streams_.end(); ++it) |
| 97 (*it)->Stop(); |
| 98 |
| 99 stream_->Stop(); |
| 100 |
| 101 audio_manager_->GetMessageLoop()->PostTask( |
| 102 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, |
| 103 base::Unretained(this))); |
| 104 } |
| 105 } |
| 106 |
| 107 void OpenAndCloseOnAudioThread() { |
| 108 ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
| 109 stream_->Open(); |
| 110 |
| 111 // Create 2 output streams, which we just open and close without starting. |
| 112 const int num_output_stream = 2; |
| 113 |
| 114 for (int i = 0; i < num_output_stream; ++i) { |
| 115 AudioOutputStream* output_stream = |
| 116 audio_manager_->MakeAudioOutputStream(output_params_); |
| 117 DCHECK(output_stream); |
| 118 output_streams_.push_back(output_stream); |
| 119 |
| 120 output_stream->Open(); |
| 121 } |
| 122 |
| 123 audio_manager_->GetMessageLoop()->PostTask( |
| 124 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, |
| 125 base::Unretained(this))); |
| 126 } |
| 127 |
| 128 void StartStopOnAudioThread(int num_output_streams, |
| 129 int num_callback_iterations, |
| 130 int num_expected_source_callbacks) { |
| 131 ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
| 132 stream_->Open(); |
| 133 stream_->Start(&input_callback_); |
| 134 StartStopCallback(true, num_output_streams, num_callback_iterations, |
| 135 num_expected_source_callbacks); |
| 136 } |
| 137 |
| 138 void StartStopCallback(bool init, |
| 139 int num_output_streams, |
| 140 int num_callback_iterations, |
| 141 int num_expected_source_callbacks) { |
| 142 ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
| 143 |
| 144 if (init) { |
| 145 for (int i = 0; i < num_output_streams; ++i) { |
| 146 AudioOutputStream* output_stream = |
| 147 audio_manager_->MakeAudioOutputStream(output_params_); |
| 148 DCHECK(output_stream); |
| 149 output_streams_.push_back(output_stream); |
| 150 |
| 151 output_stream->Open(); |
| 152 output_stream->Start(&source_); |
| 153 } |
| 154 |
| 155 // Start with an odd iteration number so we call Stop() first below. |
| 156 DCHECK_NE(0, num_callback_iterations % 2); |
| 157 } |
| 158 |
| 159 // Start or stop half the streams. |
| 160 for (int i = 0; i < num_output_streams / 2; ++i) { |
| 161 if (num_callback_iterations % 2 != 0) |
| 162 output_streams_[i]->Stop(); |
| 163 else |
| 164 output_streams_[i]->Start(&source_); |
| 165 } |
| 166 |
| 167 if (num_callback_iterations > 0) { |
| 168 // Force the next callback to be immediate. |
| 169 stream_->buffer_duration_ms_ = base::TimeDelta::FromMilliseconds(0); |
| 170 audio_manager_->GetMessageLoop()->PostTask( |
| 171 FROM_HERE, base::Bind( |
| 172 &VirtualAudioInputStreamTest::StartStopCallback, |
| 173 base::Unretained(this), |
| 174 false, |
| 175 num_output_streams, |
| 176 --num_callback_iterations, |
| 177 num_expected_source_callbacks)); |
| 178 } else { |
| 179 // Finish the test. |
| 180 EXPECT_EQ(num_expected_source_callbacks, source_.callbacks()); |
| 181 EXPECT_EQ(0, source_.errors()); |
| 182 |
| 183 for (std::vector<AudioOutputStream*>::iterator it = |
| 184 output_streams_.begin(); it != output_streams_.end(); ++it) |
| 185 (*it)->Stop(); |
| 186 |
| 187 stream_->Stop(); |
| 188 |
| 189 audio_manager_->GetMessageLoop()->PostTask(FROM_HERE, |
| 190 base::Bind(&VirtualAudioInputStreamTest::EndTest, |
| 191 base::Unretained(this))); |
| 192 } |
| 193 } |
| 194 |
| 195 void EndTest() { |
| 196 for (std::vector<AudioOutputStream*>::iterator it = |
| 197 output_streams_.begin(); it != output_streams_.end(); ++it) |
| 198 (*it)->Close(); |
| 199 |
| 200 stream_->Close(); |
| 201 |
| 202 done_.Signal(); |
| 203 } |
| 204 |
| 205 protected: |
| 206 scoped_ptr<AudioManager> audio_manager_; |
| 207 AudioParameters params_; |
| 208 AudioParameters output_params_; |
| 209 VirtualAudioInputStream* stream_; |
| 210 MockInputCallback input_callback_; |
| 211 std::vector<AudioOutputStream*> output_streams_; |
| 212 SineWaveAudioSource source_; |
| 213 base::WaitableEvent done_; |
| 214 |
| 215 private: |
| 216 DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest); |
| 217 }; |
| 218 |
| 219 TEST_F(VirtualAudioInputStreamTest, AttachAndDriveSingleStream) { |
| 220 stream_ = static_cast<VirtualAudioInputStream*>( |
| 221 audio_manager_->MakeAudioInputStream(params_, "1")); |
| 222 DCHECK(stream_); |
| 223 |
| 224 const int num_output_streams = 1; |
| 225 const int num_callback_iterations = 1; |
| 226 const int num_streams_removed_per_round = 0; |
| 227 const int num_expected_source_callbacks = 1; |
| 228 |
| 229 audio_manager_->GetMessageLoop()->PostTask( |
| 230 FROM_HERE, base::Bind( |
| 231 &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, |
| 232 base::Unretained(this), |
| 233 num_output_streams, |
| 234 num_callback_iterations, |
| 235 num_streams_removed_per_round, |
| 236 num_expected_source_callbacks)); |
| 237 |
| 238 done_.Wait(); |
| 239 } |
| 240 |
| 241 TEST_F(VirtualAudioInputStreamTest, AttachAndDriveMultipleStreams) { |
| 242 stream_ = static_cast<VirtualAudioInputStream*>( |
| 243 audio_manager_->MakeAudioInputStream(params_, "1")); |
| 244 DCHECK(stream_); |
| 245 |
| 246 const int num_output_streams = 5; |
| 247 const int num_callback_iterations = 5; |
| 248 const int num_streams_removed_per_round = 0; |
| 249 const int num_expected_source_callbacks = 25; |
| 250 |
| 251 audio_manager_->GetMessageLoop()->PostTask( |
| 252 FROM_HERE, base::Bind( |
| 253 &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, |
| 254 base::Unretained(this), |
| 255 num_output_streams, |
| 256 num_callback_iterations, |
| 257 num_streams_removed_per_round, |
| 258 num_expected_source_callbacks)); |
| 259 |
| 260 done_.Wait(); |
| 261 } |
| 262 |
| 263 TEST_F(VirtualAudioInputStreamTest, AttachAndRemoveStreams) { |
| 264 stream_ = static_cast<VirtualAudioInputStream*>( |
| 265 audio_manager_->MakeAudioInputStream(params_, "1")); |
| 266 DCHECK(stream_); |
| 267 |
| 268 const int num_output_streams = 8; |
| 269 const int num_callback_iterations = 5; |
| 270 const int num_streams_removed_per_round = 1; |
| 271 const int num_expected_source_callbacks = 8 + 7 + 6 + 5 + 4; |
| 272 |
| 273 audio_manager_->GetMessageLoop()->PostTask( |
| 274 FROM_HERE, base::Bind( |
| 275 &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, |
| 276 base::Unretained(this), |
| 277 num_output_streams, |
| 278 num_callback_iterations, |
| 279 num_streams_removed_per_round, |
| 280 num_expected_source_callbacks)); |
| 281 |
| 282 done_.Wait(); |
| 283 } |
| 284 |
| 285 // Opens/closes a VirtualAudioInputStream and a number of attached |
| 286 // VirtualAudioOutputStreams without calling Start()/Stop(). |
| 287 TEST_F(VirtualAudioInputStreamTest, OpenAndClose) { |
| 288 stream_ = static_cast<VirtualAudioInputStream*>( |
| 289 audio_manager_->MakeAudioInputStream(params_, "1")); |
| 290 DCHECK(stream_); |
| 291 |
| 292 audio_manager_->GetMessageLoop()->PostTask( |
| 293 FROM_HERE, base::Bind( |
| 294 &VirtualAudioInputStreamTest::OpenAndCloseOnAudioThread, |
| 295 base::Unretained(this))); |
| 296 |
| 297 done_.Wait(); |
| 298 } |
| 299 |
| 300 // Creates and closes and VirtualAudioInputStream. |
| 301 TEST_F(VirtualAudioInputStreamTest, CreateAndClose) { |
| 302 stream_ = static_cast<VirtualAudioInputStream*>( |
| 303 audio_manager_->MakeAudioInputStream(params_, "1")); |
| 304 DCHECK(stream_); |
| 305 |
| 306 audio_manager_->GetMessageLoop()->PostTask( |
| 307 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, |
| 308 base::Unretained(this))); |
| 309 |
| 310 done_.Wait(); |
| 311 } |
| 312 |
| 313 // Starts and stops VirtualAudioOutputStreams while attached to a |
| 314 // VirtualAudioInputStream. |
| 315 TEST_F(VirtualAudioInputStreamTest, AttachAndStartStopStreams) { |
| 316 stream_ = static_cast<VirtualAudioInputStream*>( |
| 317 audio_manager_->MakeAudioInputStream(params_, "1")); |
| 318 DCHECK(stream_); |
| 319 |
| 320 const int num_output_streams = 4; |
| 321 const int num_callback_iterations = 5; |
| 322 const int num_expected_source_callbacks = 2 + 4 + 2 + 4 + 2; |
| 323 |
| 324 audio_manager_->GetMessageLoop()->PostTask( |
| 325 FROM_HERE, base::Bind( |
| 326 &VirtualAudioInputStreamTest::StartStopOnAudioThread, |
| 327 base::Unretained(this), |
| 328 num_output_streams, |
| 329 num_callback_iterations, |
| 330 num_expected_source_callbacks)); |
| 331 |
| 332 done_.Wait(); |
| 333 } |
| 334 |
| 335 } // namespace media |
OLD | NEW |