| 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 "media/audio/win/audio_low_latency_input_win.h" | 5 #include "media/audio/win/audio_low_latency_input_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <mmsystem.h> | 8 #include <mmsystem.h> |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 #include <stdint.h> | 10 #include <stdint.h> |
| 11 | 11 |
| 12 #include <memory> | 12 #include <memory> |
| 13 | 13 |
| 14 #include "base/environment.h" | 14 #include "base/environment.h" |
| 15 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 16 #include "base/macros.h" | 16 #include "base/macros.h" |
| 17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 18 #include "base/path_service.h" | 18 #include "base/path_service.h" |
| 19 #include "base/run_loop.h" | 19 #include "base/run_loop.h" |
| 20 #include "base/single_thread_task_runner.h" |
| 20 #include "base/test/test_timeouts.h" | 21 #include "base/test/test_timeouts.h" |
| 21 #include "base/win/scoped_com_initializer.h" | 22 #include "base/win/scoped_com_initializer.h" |
| 22 #include "media/audio/audio_device_description.h" | 23 #include "media/audio/audio_device_description.h" |
| 23 #include "media/audio/audio_io.h" | 24 #include "media/audio/audio_io.h" |
| 24 #include "media/audio/audio_manager.h" | 25 #include "media/audio/audio_manager.h" |
| 25 #include "media/audio/audio_unittest_util.h" | 26 #include "media/audio/audio_unittest_util.h" |
| 26 #include "media/audio/win/core_audio_util_win.h" | 27 #include "media/audio/win/core_audio_util_win.h" |
| 27 #include "media/base/seekable_buffer.h" | 28 #include "media/base/seekable_buffer.h" |
| 28 #include "testing/gmock/include/gmock/gmock.h" | 29 #include "testing/gmock/include/gmock/gmock.h" |
| 29 #include "testing/gtest/include/gtest/gtest.h" | 30 #include "testing/gtest/include/gtest/gtest.h" |
| 30 | 31 |
| 31 using ::testing::_; | 32 using ::testing::_; |
| 32 using ::testing::AnyNumber; | 33 using ::testing::AnyNumber; |
| 33 using ::testing::AtLeast; | 34 using ::testing::AtLeast; |
| 34 using ::testing::Gt; | 35 using ::testing::Gt; |
| 35 using ::testing::NotNull; | 36 using ::testing::NotNull; |
| 36 | 37 |
| 37 namespace media { | 38 namespace media { |
| 38 | 39 |
| 39 ACTION_P3(CheckCountAndPostQuitTask, count, limit, run_loop) { | 40 ACTION_P4(CheckCountAndPostQuitTask, count, limit, task_runner, quit_closure) { |
| 40 if (++*count >= limit) | 41 if (++*count >= limit) |
| 41 run_loop->QuitWhenIdle(); | 42 task_runner->PostTask(FROM_HERE, quit_closure); |
| 42 } | 43 } |
| 43 | 44 |
| 44 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { | 45 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { |
| 45 public: | 46 public: |
| 46 MOCK_METHOD4(OnData, | 47 MOCK_METHOD4(OnData, |
| 47 void(AudioInputStream* stream, | 48 void(AudioInputStream* stream, |
| 48 const AudioBus* src, | 49 const AudioBus* src, |
| 49 uint32_t hardware_delay_bytes, | 50 uint32_t hardware_delay_bytes, |
| 50 double volume)); | 51 double volume)); |
| 51 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); | 52 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 EXPECT_TRUE(wais->started()); | 354 EXPECT_TRUE(wais->started()); |
| 354 | 355 |
| 355 // Stop(), Stop() is a valid calling sequence (second call does nothing). | 356 // Stop(), Stop() is a valid calling sequence (second call does nothing). |
| 356 ais->Stop(); | 357 ais->Stop(); |
| 357 EXPECT_FALSE(wais->started()); | 358 EXPECT_FALSE(wais->started()); |
| 358 ais->Stop(); | 359 ais->Stop(); |
| 359 EXPECT_FALSE(wais->started()); | 360 EXPECT_FALSE(wais->started()); |
| 360 ais.Close(); | 361 ais.Close(); |
| 361 } | 362 } |
| 362 | 363 |
| 363 // TODO(fdoray): investigate failure and re-enable. crbug.com/641142 | 364 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { |
| 364 TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamTestPacketSizes) { | |
| 365 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); | 365 ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); |
| 366 | 366 |
| 367 int count = 0; | 367 int count = 0; |
| 368 | 368 |
| 369 // 10 ms packet size. | 369 // 10 ms packet size. |
| 370 | 370 |
| 371 // Create default WASAPI input stream which records in stereo using | 371 // Create default WASAPI input stream which records in stereo using |
| 372 // the shared mixing rate. The default buffer size is 10ms. | 372 // the shared mixing rate. The default buffer size is 10ms. |
| 373 AudioInputStreamWrapper aisw(audio_manager_.get()); | 373 AudioInputStreamWrapper aisw(audio_manager_.get()); |
| 374 ScopedAudioInputStream ais(aisw.Create()); | 374 ScopedAudioInputStream ais(aisw.Create()); |
| 375 EXPECT_TRUE(ais->Open()); | 375 EXPECT_TRUE(ais->Open()); |
| 376 | 376 |
| 377 MockAudioInputCallback sink; | 377 MockAudioInputCallback sink; |
| 378 | 378 |
| 379 // Derive the expected size in bytes of each recorded packet. | 379 // Derive the expected size in bytes of each recorded packet. |
| 380 uint32_t bytes_per_packet = | 380 uint32_t bytes_per_packet = |
| 381 aisw.channels() * aisw.frames_per_buffer() * (aisw.bits_per_sample() / 8); | 381 aisw.channels() * aisw.frames_per_buffer() * (aisw.bits_per_sample() / 8); |
| 382 | 382 |
| 383 { | 383 { |
| 384 // We use 10ms packets and will run the test until ten packets are received. | 384 // We use 10ms packets and will run the test until ten packets are received. |
| 385 // All should contain valid packets of the same size and a valid delay | 385 // All should contain valid packets of the same size and a valid delay |
| 386 // estimate. | 386 // estimate. |
| 387 base::RunLoop run_loop; | 387 base::RunLoop run_loop; |
| 388 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) | 388 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) |
| 389 .Times(AtLeast(10)) | 389 .Times(AtLeast(10)) |
| 390 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &run_loop)); | 390 .WillRepeatedly( |
| 391 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), |
| 392 run_loop.QuitWhenIdleClosure())); |
| 391 ais->Start(&sink); | 393 ais->Start(&sink); |
| 392 run_loop.Run(); | 394 run_loop.Run(); |
| 393 ais->Stop(); | 395 ais->Stop(); |
| 394 } | 396 } |
| 395 | 397 |
| 396 // Store current packet size (to be used in the subsequent tests). | 398 // Store current packet size (to be used in the subsequent tests). |
| 397 int frames_per_buffer_10ms = aisw.frames_per_buffer(); | 399 int frames_per_buffer_10ms = aisw.frames_per_buffer(); |
| 398 | 400 |
| 399 ais.Close(); | 401 ais.Close(); |
| 400 | 402 |
| 401 // 20 ms packet size. | 403 // 20 ms packet size. |
| 402 | 404 |
| 403 count = 0; | 405 count = 0; |
| 404 ais.Reset(aisw.Create(2 * frames_per_buffer_10ms)); | 406 ais.Reset(aisw.Create(2 * frames_per_buffer_10ms)); |
| 405 EXPECT_TRUE(ais->Open()); | 407 EXPECT_TRUE(ais->Open()); |
| 406 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * | 408 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
| 407 (aisw.bits_per_sample() / 8); | 409 (aisw.bits_per_sample() / 8); |
| 408 | 410 |
| 409 { | 411 { |
| 410 base::RunLoop run_loop; | 412 base::RunLoop run_loop; |
| 411 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) | 413 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) |
| 412 .Times(AtLeast(10)) | 414 .Times(AtLeast(10)) |
| 413 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &run_loop)); | 415 .WillRepeatedly( |
| 416 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), |
| 417 run_loop.QuitWhenIdleClosure())); |
| 414 ais->Start(&sink); | 418 ais->Start(&sink); |
| 415 run_loop.Run(); | 419 run_loop.Run(); |
| 416 ais->Stop(); | 420 ais->Stop(); |
| 417 ais.Close(); | 421 ais.Close(); |
| 418 } | 422 } |
| 419 | 423 |
| 420 // 5 ms packet size. | 424 // 5 ms packet size. |
| 421 | 425 |
| 422 count = 0; | 426 count = 0; |
| 423 ais.Reset(aisw.Create(frames_per_buffer_10ms / 2)); | 427 ais.Reset(aisw.Create(frames_per_buffer_10ms / 2)); |
| 424 EXPECT_TRUE(ais->Open()); | 428 EXPECT_TRUE(ais->Open()); |
| 425 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * | 429 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
| 426 (aisw.bits_per_sample() / 8); | 430 (aisw.bits_per_sample() / 8); |
| 427 | 431 |
| 428 { | 432 { |
| 429 base::RunLoop run_loop; | 433 base::RunLoop run_loop; |
| 430 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) | 434 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) |
| 431 .Times(AtLeast(10)) | 435 .Times(AtLeast(10)) |
| 432 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &run_loop)); | 436 .WillRepeatedly( |
| 437 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), |
| 438 run_loop.QuitWhenIdleClosure())); |
| 433 ais->Start(&sink); | 439 ais->Start(&sink); |
| 434 run_loop.Run(); | 440 run_loop.Run(); |
| 435 ais->Stop(); | 441 ais->Stop(); |
| 436 ais.Close(); | 442 ais.Close(); |
| 437 } | 443 } |
| 438 } | 444 } |
| 439 | 445 |
| 440 // Test that we can capture a stream in loopback. | 446 // Test that we can capture a stream in loopback. |
| 441 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { | 447 TEST_F(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { |
| 442 ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices() && | 448 ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices() && |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); | 494 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); |
| 489 VLOG(0) << ">> Speak into the default microphone while recording."; | 495 VLOG(0) << ">> Speak into the default microphone while recording."; |
| 490 ais->Start(&file_sink); | 496 ais->Start(&file_sink); |
| 491 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); | 497 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); |
| 492 ais->Stop(); | 498 ais->Stop(); |
| 493 VLOG(0) << ">> Recording has stopped."; | 499 VLOG(0) << ">> Recording has stopped."; |
| 494 ais.Close(); | 500 ais.Close(); |
| 495 } | 501 } |
| 496 | 502 |
| 497 } // namespace media | 503 } // namespace media |
| OLD | NEW |