| 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 "base/basictypes.h" | 5 #include "base/basictypes.h" |
| 6 #include "base/environment.h" | 6 #include "base/environment.h" |
| 7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
| 8 #include "base/run_loop.h" |
| 8 #include "base/test/test_timeouts.h" | 9 #include "base/test/test_timeouts.h" |
| 9 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
| 10 #include "media/audio/audio_io.h" | 11 #include "media/audio/audio_io.h" |
| 11 #include "media/audio/audio_manager_base.h" | 12 #include "media/audio/audio_manager_base.h" |
| 12 #include "media/audio/mac/audio_low_latency_input_mac.h" | 13 #include "media/audio/mac/audio_low_latency_input_mac.h" |
| 13 #include "media/base/seekable_buffer.h" | 14 #include "media/base/seekable_buffer.h" |
| 14 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 17 |
| 17 using ::testing::_; | 18 using ::testing::_; |
| 18 using ::testing::AnyNumber; | 19 using ::testing::AnyNumber; |
| 19 using ::testing::AtLeast; | 20 using ::testing::AtLeast; |
| 20 using ::testing::Ge; | 21 using ::testing::Ge; |
| 21 using ::testing::NotNull; | 22 using ::testing::NotNull; |
| 22 | 23 |
| 23 namespace media { | 24 namespace media { |
| 24 | 25 |
| 25 ACTION_P3(CheckCountAndPostQuitTask, count, limit, loop) { | 26 ACTION_P4(CheckCountAndPostQuitTask, count, limit, loop, closure) { |
| 26 if (++*count >= limit) { | 27 if (++*count >= limit) { |
| 27 loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); | 28 loop->PostTask(FROM_HERE, closure); |
| 28 } | 29 } |
| 29 } | 30 } |
| 30 | 31 |
| 31 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { | 32 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { |
| 32 public: | 33 public: |
| 33 MOCK_METHOD5(OnData, void(AudioInputStream* stream, | 34 MOCK_METHOD5(OnData, void(AudioInputStream* stream, |
| 34 const uint8* src, uint32 size, | 35 const uint8* src, uint32 size, |
| 35 uint32 hardware_delay_bytes, double volume)); | 36 uint32 hardware_delay_bytes, double volume)); |
| 36 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); | 37 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); |
| 37 }; | 38 }; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 virtual void OnError(AudioInputStream* stream) OVERRIDE {} | 87 virtual void OnError(AudioInputStream* stream) OVERRIDE {} |
| 87 | 88 |
| 88 private: | 89 private: |
| 89 media::SeekableBuffer buffer_; | 90 media::SeekableBuffer buffer_; |
| 90 FILE* file_; | 91 FILE* file_; |
| 91 int bytes_to_write_; | 92 int bytes_to_write_; |
| 92 }; | 93 }; |
| 93 | 94 |
| 94 class MacAudioInputTest : public testing::Test { | 95 class MacAudioInputTest : public testing::Test { |
| 95 protected: | 96 protected: |
| 96 MacAudioInputTest() : audio_manager_(AudioManager::CreateForTesting()) {} | 97 MacAudioInputTest() |
| 97 virtual ~MacAudioInputTest() {} | 98 : message_loop_(base::MessageLoop::TYPE_UI), |
| 99 audio_manager_(AudioManager::CreateForTesting()) { |
| 100 // Wait for the AudioManager to finish any initialization on the audio loop. |
| 101 base::RunLoop().RunUntilIdle(); |
| 102 } |
| 103 |
| 104 virtual ~MacAudioInputTest() { |
| 105 base::RunLoop().RunUntilIdle(); |
| 106 } |
| 98 | 107 |
| 99 // Convenience method which ensures that we are not running on the build | 108 // Convenience method which ensures that we are not running on the build |
| 100 // bots and that at least one valid input device can be found. | 109 // bots and that at least one valid input device can be found. |
| 101 bool CanRunAudioTests() { | 110 bool CanRunAudioTests() { |
| 102 bool has_input = audio_manager_->HasAudioInputDevices(); | 111 bool has_input = audio_manager_->HasAudioInputDevices(); |
| 103 if (!has_input) | 112 if (!has_input) |
| 104 LOG(WARNING) << "No input devices detected"; | 113 LOG(WARNING) << "No input devices detected"; |
| 105 return has_input; | 114 return has_input; |
| 106 } | 115 } |
| 107 | 116 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 125 int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); | 134 int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); |
| 126 int samples_per_packet = fs / 100; | 135 int samples_per_packet = fs / 100; |
| 127 AudioInputStream* ais = audio_manager_->MakeAudioInputStream( | 136 AudioInputStream* ais = audio_manager_->MakeAudioInputStream( |
| 128 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 137 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 129 channel_layout, fs, 16, samples_per_packet), | 138 channel_layout, fs, 16, samples_per_packet), |
| 130 AudioManagerBase::kDefaultDeviceId); | 139 AudioManagerBase::kDefaultDeviceId); |
| 131 EXPECT_TRUE(ais); | 140 EXPECT_TRUE(ais); |
| 132 return ais; | 141 return ais; |
| 133 } | 142 } |
| 134 | 143 |
| 144 base::MessageLoop message_loop_; |
| 135 scoped_ptr<AudioManager> audio_manager_; | 145 scoped_ptr<AudioManager> audio_manager_; |
| 136 }; | 146 }; |
| 137 | 147 |
| 138 // Test Create(), Close(). | 148 // Test Create(), Close(). |
| 139 TEST_F(MacAudioInputTest, AUAudioInputStreamCreateAndClose) { | 149 TEST_F(MacAudioInputTest, AUAudioInputStreamCreateAndClose) { |
| 140 if (!CanRunAudioTests()) | 150 if (!CanRunAudioTests()) |
| 141 return; | 151 return; |
| 142 AudioInputStream* ais = CreateDefaultAudioInputStream(); | 152 AudioInputStream* ais = CreateDefaultAudioInputStream(); |
| 143 ais->Close(); | 153 ais->Close(); |
| 144 } | 154 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 | 212 |
| 203 ais->Close(); | 213 ais->Close(); |
| 204 } | 214 } |
| 205 | 215 |
| 206 // Verify that recording starts and stops correctly in mono using mocked sink. | 216 // Verify that recording starts and stops correctly in mono using mocked sink. |
| 207 TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) { | 217 TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) { |
| 208 if (!CanRunAudioTests()) | 218 if (!CanRunAudioTests()) |
| 209 return; | 219 return; |
| 210 | 220 |
| 211 int count = 0; | 221 int count = 0; |
| 212 base::MessageLoopForUI loop; | |
| 213 | 222 |
| 214 // Create an audio input stream which records in mono. | 223 // Create an audio input stream which records in mono. |
| 215 AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_MONO); | 224 AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_MONO); |
| 216 EXPECT_TRUE(ais->Open()); | 225 EXPECT_TRUE(ais->Open()); |
| 217 | 226 |
| 218 int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); | 227 int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); |
| 219 int samples_per_packet = fs / 100; | 228 int samples_per_packet = fs / 100; |
| 220 int bits_per_sample = 16; | 229 int bits_per_sample = 16; |
| 221 uint32 bytes_per_packet = samples_per_packet * (bits_per_sample / 8); | 230 uint32 bytes_per_packet = samples_per_packet * (bits_per_sample / 8); |
| 222 | 231 |
| 223 MockAudioInputCallback sink; | 232 MockAudioInputCallback sink; |
| 224 | 233 |
| 225 // We use 10ms packets and will run the test until ten packets are received. | 234 // We use 10ms packets and will run the test until ten packets are received. |
| 226 // All should contain valid packets of the same size and a valid delay | 235 // All should contain valid packets of the same size and a valid delay |
| 227 // estimate. | 236 // estimate. |
| 237 base::RunLoop run_loop; |
| 228 EXPECT_CALL(sink, OnData(ais, NotNull(), bytes_per_packet, _, _)) | 238 EXPECT_CALL(sink, OnData(ais, NotNull(), bytes_per_packet, _, _)) |
| 229 .Times(AtLeast(10)) | 239 .Times(AtLeast(10)) |
| 230 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); | 240 .WillRepeatedly(CheckCountAndPostQuitTask( |
| 241 &count, 10, &message_loop_, run_loop.QuitClosure())); |
| 231 ais->Start(&sink); | 242 ais->Start(&sink); |
| 232 loop.Run(); | 243 run_loop.Run(); |
| 233 ais->Stop(); | 244 ais->Stop(); |
| 234 ais->Close(); | 245 ais->Close(); |
| 235 } | 246 } |
| 236 | 247 |
| 237 // Verify that recording starts and stops correctly in mono using mocked sink. | 248 // Verify that recording starts and stops correctly in mono using mocked sink. |
| 238 TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) { | 249 TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) { |
| 239 if (!CanRunAudioTests()) | 250 if (!CanRunAudioTests()) |
| 240 return; | 251 return; |
| 241 | 252 |
| 242 int count = 0; | 253 int count = 0; |
| 243 base::MessageLoopForUI loop; | |
| 244 | 254 |
| 245 // Create an audio input stream which records in stereo. | 255 // Create an audio input stream which records in stereo. |
| 246 AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_STEREO); | 256 AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_STEREO); |
| 247 EXPECT_TRUE(ais->Open()); | 257 EXPECT_TRUE(ais->Open()); |
| 248 | 258 |
| 249 int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); | 259 int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); |
| 250 int samples_per_packet = fs / 100; | 260 int samples_per_packet = fs / 100; |
| 251 int bits_per_sample = 16; | 261 int bits_per_sample = 16; |
| 252 uint32 bytes_per_packet = 2 * samples_per_packet * (bits_per_sample / 8); | 262 uint32 bytes_per_packet = 2 * samples_per_packet * (bits_per_sample / 8); |
| 253 | 263 |
| 254 MockAudioInputCallback sink; | 264 MockAudioInputCallback sink; |
| 255 | 265 |
| 256 // We use 10ms packets and will run the test until ten packets are received. | 266 // We use 10ms packets and will run the test until ten packets are received. |
| 257 // All should contain valid packets of the same size and a valid delay | 267 // All should contain valid packets of the same size and a valid delay |
| 258 // estimate. | 268 // estimate. |
| 259 // TODO(henrika): http://crbug.com/154352 forced us to run the capture side | 269 // TODO(henrika): http://crbug.com/154352 forced us to run the capture side |
| 260 // using a native buffer size of 128 audio frames and combine it with a FIFO | 270 // using a native buffer size of 128 audio frames and combine it with a FIFO |
| 261 // to match the requested size by the client. This change might also have | 271 // to match the requested size by the client. This change might also have |
| 262 // modified the delay estimates since the existing Ge(bytes_per_packet) for | 272 // modified the delay estimates since the existing Ge(bytes_per_packet) for |
| 263 // parameter #4 does no longer pass. I am removing this restriction here to | 273 // parameter #4 does no longer pass. I am removing this restriction here to |
| 264 // ensure that we can land the patch but will revisit this test again when | 274 // ensure that we can land the patch but will revisit this test again when |
| 265 // more analysis of the delay estimates are done. | 275 // more analysis of the delay estimates are done. |
| 276 base::RunLoop run_loop; |
| 266 EXPECT_CALL(sink, OnData(ais, NotNull(), bytes_per_packet, _, _)) | 277 EXPECT_CALL(sink, OnData(ais, NotNull(), bytes_per_packet, _, _)) |
| 267 .Times(AtLeast(10)) | 278 .Times(AtLeast(10)) |
| 268 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); | 279 .WillRepeatedly(CheckCountAndPostQuitTask( |
| 280 &count, 10, &message_loop_, run_loop.QuitClosure())); |
| 269 ais->Start(&sink); | 281 ais->Start(&sink); |
| 270 loop.Run(); | 282 run_loop.Run(); |
| 271 ais->Stop(); | 283 ais->Stop(); |
| 272 ais->Close(); | 284 ais->Close(); |
| 273 } | 285 } |
| 274 | 286 |
| 275 // This test is intended for manual tests and should only be enabled | 287 // This test is intended for manual tests and should only be enabled |
| 276 // when it is required to store the captured data on a local file. | 288 // when it is required to store the captured data on a local file. |
| 277 // By default, GTest will print out YOU HAVE 1 DISABLED TEST. | 289 // By default, GTest will print out YOU HAVE 1 DISABLED TEST. |
| 278 // To include disabled tests in test execution, just invoke the test program | 290 // To include disabled tests in test execution, just invoke the test program |
| 279 // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS | 291 // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS |
| 280 // environment variable to a value greater than 0. | 292 // environment variable to a value greater than 0. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 292 WriteToFileAudioSink file_sink(file_name); | 304 WriteToFileAudioSink file_sink(file_name); |
| 293 fprintf(stderr, " >> Speak into the mic while recording...\n"); | 305 fprintf(stderr, " >> Speak into the mic while recording...\n"); |
| 294 ais->Start(&file_sink); | 306 ais->Start(&file_sink); |
| 295 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); | 307 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); |
| 296 ais->Stop(); | 308 ais->Stop(); |
| 297 fprintf(stderr, " >> Recording has stopped.\n"); | 309 fprintf(stderr, " >> Recording has stopped.\n"); |
| 298 ais->Close(); | 310 ais->Close(); |
| 299 } | 311 } |
| 300 | 312 |
| 301 } // namespace media | 313 } // namespace media |
| OLD | NEW |