Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(576)

Side by Side Diff: media/audio/win/audio_low_latency_input_win_unittest.cc

Issue 1097553003: Switch to STA mode for audio thread and WASAPI I/O streams. (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <windows.h> 5 #include <windows.h>
6 #include <mmsystem.h> 6 #include <mmsystem.h>
7 7
8 #include "base/basictypes.h" 8 #include "base/basictypes.h"
9 #include "base/environment.h" 9 #include "base/environment.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 // TODO(henrika): note that we use Wave today to query the number of 156 // TODO(henrika): note that we use Wave today to query the number of
157 // existing input devices. 157 // existing input devices.
158 return CoreAudioUtil::IsSupported() && audio_man->HasAudioInputDevices(); 158 return CoreAudioUtil::IsSupported() && audio_man->HasAudioInputDevices();
159 } 159 }
160 160
161 // Convenience method which creates a default AudioInputStream object but 161 // Convenience method which creates a default AudioInputStream object but
162 // also allows the user to modify the default settings. 162 // also allows the user to modify the default settings.
163 class AudioInputStreamWrapper { 163 class AudioInputStreamWrapper {
164 public: 164 public:
165 explicit AudioInputStreamWrapper(AudioManager* audio_manager) 165 explicit AudioInputStreamWrapper(AudioManager* audio_manager)
166 : com_init_(ScopedCOMInitializer::kMTA), 166 : audio_man_(audio_manager),
167 audio_man_(audio_manager), 167 default_params_(audio_man_->GetInputStreamParameters(
168 default_params_( 168 AudioManagerBase::kDefaultDeviceId)) {
169 audio_manager->GetInputStreamParameters(
170 AudioManagerBase::kDefaultDeviceId)) {
171 EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); 169 EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY);
172 frames_per_buffer_ = default_params_.frames_per_buffer(); 170 frames_per_buffer_ = default_params_.frames_per_buffer();
173 // We expect the default buffer size to be a 10ms buffer. 171 // We expect the default buffer size to be a 10ms buffer.
174 EXPECT_EQ(frames_per_buffer_, sample_rate() / 100); 172 EXPECT_EQ(frames_per_buffer_, sample_rate() / 100);
175 } 173 }
176 174
177 ~AudioInputStreamWrapper() {} 175 ~AudioInputStreamWrapper() {}
178 176
179 // Creates AudioInputStream object using default parameters. 177 // Creates AudioInputStream object using default parameters.
180 AudioInputStream* Create() { 178 AudioInputStream* Create() {
(...skipping 19 matching lines...) Expand all
200 AudioInputStream* CreateInputStream() { 198 AudioInputStream* CreateInputStream() {
201 AudioInputStream* ais = audio_man_->MakeAudioInputStream( 199 AudioInputStream* ais = audio_man_->MakeAudioInputStream(
202 AudioParameters(format(), default_params_.channel_layout(), 200 AudioParameters(format(), default_params_.channel_layout(),
203 sample_rate(), bits_per_sample(), frames_per_buffer_, 201 sample_rate(), bits_per_sample(), frames_per_buffer_,
204 default_params_.effects()), 202 default_params_.effects()),
205 AudioManagerBase::kDefaultDeviceId); 203 AudioManagerBase::kDefaultDeviceId);
206 EXPECT_TRUE(ais); 204 EXPECT_TRUE(ais);
207 return ais; 205 return ais;
208 } 206 }
209 207
210 ScopedCOMInitializer com_init_;
211 AudioManager* audio_man_; 208 AudioManager* audio_man_;
212 const AudioParameters default_params_; 209 const AudioParameters default_params_;
213 int frames_per_buffer_; 210 int frames_per_buffer_;
214 }; 211 };
215 212
216 // Convenience method which creates a default AudioInputStream object. 213 // Convenience method which creates a default AudioInputStream object.
217 static AudioInputStream* CreateDefaultAudioInputStream( 214 static AudioInputStream* CreateDefaultAudioInputStream(
218 AudioManager* audio_manager) { 215 AudioManager* audio_manager) {
219 AudioInputStreamWrapper aisw(audio_manager); 216 AudioInputStreamWrapper aisw(audio_manager);
220 AudioInputStream* ais = aisw.Create(); 217 AudioInputStream* ais = aisw.Create();
(...skipping 26 matching lines...) Expand all
247 Close(); 244 Close();
248 stream_ = new_stream; 245 stream_ = new_stream;
249 } 246 }
250 247
251 private: 248 private:
252 AudioInputStream* stream_; 249 AudioInputStream* stream_;
253 250
254 DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream); 251 DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream);
255 }; 252 };
256 253
254 class WinAudioInputTest : public testing::Test {
255 public:
256 WinAudioInputTest() : audio_manager_(AudioManager::CreateForTesting()) {}
257 ~WinAudioInputTest() override {}
258
259 protected:
260 ScopedCOMInitializer com_init_;
261 scoped_ptr<AudioManager> audio_manager_;
262 };
263
257 // Verify that we can retrieve the current hardware/mixing sample rate 264 // Verify that we can retrieve the current hardware/mixing sample rate
258 // for all available input devices. 265 // for all available input devices.
259 TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) { 266 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) {
260 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 267 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
261 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
262
263 ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
264 268
265 // Retrieve a list of all available input devices. 269 // Retrieve a list of all available input devices.
266 media::AudioDeviceNames device_names; 270 media::AudioDeviceNames device_names;
267 audio_manager->GetAudioInputDeviceNames(&device_names); 271 audio_manager_->GetAudioInputDeviceNames(&device_names);
268 272
269 // Scan all available input devices and repeat the same test for all of them. 273 // Scan all available input devices and repeat the same test for all of them.
270 for (media::AudioDeviceNames::const_iterator it = device_names.begin(); 274 for (media::AudioDeviceNames::const_iterator it = device_names.begin();
271 it != device_names.end(); ++it) { 275 it != device_names.end(); ++it) {
272 // Retrieve the hardware sample rate given a specified audio input device. 276 // Retrieve the hardware sample rate given a specified audio input device.
273 AudioParameters params = WASAPIAudioInputStream::GetInputStreamParameters( 277 AudioParameters params = WASAPIAudioInputStream::GetInputStreamParameters(
274 it->unique_id); 278 it->unique_id);
275 EXPECT_GE(params.sample_rate(), 0); 279 EXPECT_GE(params.sample_rate(), 0);
276 } 280 }
277 } 281 }
278 282
279 // Test Create(), Close() calling sequence. 283 // Test Create(), Close() calling sequence.
280 TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) { 284 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) {
281 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 285 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
282 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
283 ScopedAudioInputStream ais( 286 ScopedAudioInputStream ais(
284 CreateDefaultAudioInputStream(audio_manager.get())); 287 CreateDefaultAudioInputStream(audio_manager_.get()));
285 ais.Close(); 288 ais.Close();
286 } 289 }
287 290
288 // Test Open(), Close() calling sequence. 291 // Test Open(), Close() calling sequence.
289 TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) { 292 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) {
290 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 293 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
291 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
292 ScopedAudioInputStream ais( 294 ScopedAudioInputStream ais(
293 CreateDefaultAudioInputStream(audio_manager.get())); 295 CreateDefaultAudioInputStream(audio_manager_.get()));
294 EXPECT_TRUE(ais->Open()); 296 EXPECT_TRUE(ais->Open());
295 ais.Close(); 297 ais.Close();
296 } 298 }
297 299
298 // Test Open(), Start(), Close() calling sequence. 300 // Test Open(), Start(), Close() calling sequence.
299 TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) { 301 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) {
300 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 302 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
301 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
302 ScopedAudioInputStream ais( 303 ScopedAudioInputStream ais(
303 CreateDefaultAudioInputStream(audio_manager.get())); 304 CreateDefaultAudioInputStream(audio_manager_.get()));
304 EXPECT_TRUE(ais->Open()); 305 EXPECT_TRUE(ais->Open());
305 MockAudioInputCallback sink; 306 MockAudioInputCallback sink;
306 ais->Start(&sink); 307 ais->Start(&sink);
307 ais.Close(); 308 ais.Close();
308 } 309 }
309 310
310 // Test Open(), Start(), Stop(), Close() calling sequence. 311 // Test Open(), Start(), Stop(), Close() calling sequence.
311 TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) { 312 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) {
312 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 313 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
313 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
314 ScopedAudioInputStream ais( 314 ScopedAudioInputStream ais(
315 CreateDefaultAudioInputStream(audio_manager.get())); 315 CreateDefaultAudioInputStream(audio_manager_.get()));
316 EXPECT_TRUE(ais->Open()); 316 EXPECT_TRUE(ais->Open());
317 MockAudioInputCallback sink; 317 MockAudioInputCallback sink;
318 ais->Start(&sink); 318 ais->Start(&sink);
319 ais->Stop(); 319 ais->Stop();
320 ais.Close(); 320 ais.Close();
321 } 321 }
322 322
323 // Test some additional calling sequences. 323 // Test some additional calling sequences.
324 TEST(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) { 324 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) {
325 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 325 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
326 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
327 ScopedAudioInputStream ais( 326 ScopedAudioInputStream ais(
328 CreateDefaultAudioInputStream(audio_manager.get())); 327 CreateDefaultAudioInputStream(audio_manager_.get()));
329 WASAPIAudioInputStream* wais = 328 WASAPIAudioInputStream* wais =
330 static_cast<WASAPIAudioInputStream*>(ais.get()); 329 static_cast<WASAPIAudioInputStream*>(ais.get());
331 330
332 // Open(), Open() should fail the second time. 331 // Open(), Open() should fail the second time.
333 EXPECT_TRUE(ais->Open()); 332 EXPECT_TRUE(ais->Open());
334 EXPECT_FALSE(ais->Open()); 333 EXPECT_FALSE(ais->Open());
335 334
336 MockAudioInputCallback sink; 335 MockAudioInputCallback sink;
337 336
338 // Start(), Start() is a valid calling sequence (second call does nothing). 337 // Start(), Start() is a valid calling sequence (second call does nothing).
339 ais->Start(&sink); 338 ais->Start(&sink);
340 EXPECT_TRUE(wais->started()); 339 EXPECT_TRUE(wais->started());
341 ais->Start(&sink); 340 ais->Start(&sink);
342 EXPECT_TRUE(wais->started()); 341 EXPECT_TRUE(wais->started());
343 342
344 // Stop(), Stop() is a valid calling sequence (second call does nothing). 343 // Stop(), Stop() is a valid calling sequence (second call does nothing).
345 ais->Stop(); 344 ais->Stop();
346 EXPECT_FALSE(wais->started()); 345 EXPECT_FALSE(wais->started());
347 ais->Stop(); 346 ais->Stop();
348 EXPECT_FALSE(wais->started()); 347 EXPECT_FALSE(wais->started());
349 ais.Close(); 348 ais.Close();
350 } 349 }
351 350
352 TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { 351 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) {
353 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 352 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
354 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
355 353
356 int count = 0; 354 int count = 0;
357 base::MessageLoopForUI loop; 355 base::MessageLoopForUI loop;
358 356
359 // 10 ms packet size. 357 // 10 ms packet size.
360 358
361 // Create default WASAPI input stream which records in stereo using 359 // Create default WASAPI input stream which records in stereo using
362 // the shared mixing rate. The default buffer size is 10ms. 360 // the shared mixing rate. The default buffer size is 10ms.
363 AudioInputStreamWrapper aisw(audio_manager.get()); 361 AudioInputStreamWrapper aisw(audio_manager_.get());
364 ScopedAudioInputStream ais(aisw.Create()); 362 ScopedAudioInputStream ais(aisw.Create());
365 EXPECT_TRUE(ais->Open()); 363 EXPECT_TRUE(ais->Open());
366 364
367 MockAudioInputCallback sink; 365 MockAudioInputCallback sink;
368 366
369 // Derive the expected size in bytes of each recorded packet. 367 // Derive the expected size in bytes of each recorded packet.
370 uint32 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * 368 uint32 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() *
371 (aisw.bits_per_sample() / 8); 369 (aisw.bits_per_sample() / 8);
372 370
373 // We use 10ms packets and will run the test until ten packets are received. 371 // We use 10ms packets and will run the test until ten packets are received.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), Gt(bytes_per_packet), _)) 410 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), Gt(bytes_per_packet), _))
413 .Times(AtLeast(10)) 411 .Times(AtLeast(10))
414 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); 412 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop));
415 ais->Start(&sink); 413 ais->Start(&sink);
416 loop.Run(); 414 loop.Run();
417 ais->Stop(); 415 ais->Stop();
418 ais.Close(); 416 ais.Close();
419 } 417 }
420 418
421 // Test that we can capture a stream in loopback. 419 // Test that we can capture a stream in loopback.
422 TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { 420 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamLoopback) {
423 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 421 ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices() &&
424 ABORT_AUDIO_TEST_IF_NOT(audio_manager->HasAudioOutputDevices() &&
425 CoreAudioUtil::IsSupported()); 422 CoreAudioUtil::IsSupported());
426 423
427 AudioParameters params = audio_manager->GetInputStreamParameters( 424 AudioParameters params = audio_manager_->GetInputStreamParameters(
428 AudioManagerBase::kLoopbackInputDeviceId); 425 AudioManagerBase::kLoopbackInputDeviceId);
429 EXPECT_EQ(params.effects(), 0); 426 EXPECT_EQ(params.effects(), 0);
430 427
431 AudioParameters output_params = 428 AudioParameters output_params =
432 audio_manager->GetOutputStreamParameters(std::string()); 429 audio_manager_->GetOutputStreamParameters(std::string());
433 EXPECT_EQ(params.sample_rate(), output_params.sample_rate()); 430 EXPECT_EQ(params.sample_rate(), output_params.sample_rate());
434 EXPECT_EQ(params.channel_layout(), output_params.channel_layout()); 431 EXPECT_EQ(params.channel_layout(), output_params.channel_layout());
435 432
436 ScopedAudioInputStream stream(audio_manager->MakeAudioInputStream( 433 ScopedAudioInputStream stream(audio_manager_->MakeAudioInputStream(
437 params, AudioManagerBase::kLoopbackInputDeviceId)); 434 params, AudioManagerBase::kLoopbackInputDeviceId));
438 ASSERT_TRUE(stream->Open()); 435 ASSERT_TRUE(stream->Open());
439 FakeAudioInputCallback sink; 436 FakeAudioInputCallback sink;
440 stream->Start(&sink); 437 stream->Start(&sink);
441 ASSERT_FALSE(sink.error()); 438 ASSERT_FALSE(sink.error());
442 439
443 sink.WaitForData(); 440 sink.WaitForData();
444 stream.Close(); 441 stream.Close();
445 442
446 EXPECT_GT(sink.num_received_audio_frames(), 0); 443 EXPECT_GT(sink.num_received_audio_frames(), 0);
447 EXPECT_FALSE(sink.error()); 444 EXPECT_FALSE(sink.error());
448 } 445 }
449 446
450 // This test is intended for manual tests and should only be enabled 447 // This test is intended for manual tests and should only be enabled
451 // when it is required to store the captured data on a local file. 448 // when it is required to store the captured data on a local file.
452 // By default, GTest will print out YOU HAVE 1 DISABLED TEST. 449 // By default, GTest will print out YOU HAVE 1 DISABLED TEST.
453 // To include disabled tests in test execution, just invoke the test program 450 // To include disabled tests in test execution, just invoke the test program
454 // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS 451 // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
455 // environment variable to a value greater than 0. 452 // environment variable to a value greater than 0.
456 TEST(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { 453 TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) {
457 scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); 454 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get()));
458 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get()));
459 455
460 // Name of the output PCM file containing captured data. The output file 456 // Name of the output PCM file containing captured data. The output file
461 // will be stored in the directory containing 'media_unittests.exe'. 457 // will be stored in the directory containing 'media_unittests.exe'.
462 // Example of full name: \src\build\Debug\out_stereo_10sec.pcm. 458 // Example of full name: \src\build\Debug\out_stereo_10sec.pcm.
463 const char* file_name = "out_stereo_10sec.pcm"; 459 const char* file_name = "out_stereo_10sec.pcm";
464 460
465 AudioInputStreamWrapper aisw(audio_manager.get()); 461 AudioInputStreamWrapper aisw(audio_manager_.get());
466 ScopedAudioInputStream ais(aisw.Create()); 462 ScopedAudioInputStream ais(aisw.Create());
467 EXPECT_TRUE(ais->Open()); 463 EXPECT_TRUE(ais->Open());
468 464
469 VLOG(0) << ">> Sample rate: " << aisw.sample_rate() << " [Hz]"; 465 VLOG(0) << ">> Sample rate: " << aisw.sample_rate() << " [Hz]";
470 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); 466 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample());
471 VLOG(0) << ">> Speak into the default microphone while recording."; 467 VLOG(0) << ">> Speak into the default microphone while recording.";
472 ais->Start(&file_sink); 468 ais->Start(&file_sink);
473 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); 469 base::PlatformThread::Sleep(TestTimeouts::action_timeout());
474 ais->Stop(); 470 ais->Stop();
475 VLOG(0) << ">> Recording has stopped."; 471 VLOG(0) << ">> Recording has stopped.";
476 ais.Close(); 472 ais.Close();
477 } 473 }
478 474
479 } // namespace media 475 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698