| 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> |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 namespace media { | 38 namespace media { |
| 39 | 39 |
| 40 ACTION_P4(CheckCountAndPostQuitTask, count, limit, task_runner, quit_closure) { | 40 ACTION_P4(CheckCountAndPostQuitTask, count, limit, task_runner, quit_closure) { |
| 41 if (++*count >= limit) | 41 if (++*count >= limit) |
| 42 task_runner->PostTask(FROM_HERE, quit_closure); | 42 task_runner->PostTask(FROM_HERE, quit_closure); |
| 43 } | 43 } |
| 44 | 44 |
| 45 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { | 45 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { |
| 46 public: | 46 public: |
| 47 MOCK_METHOD4(OnData, | 47 MOCK_METHOD5(OnData, |
| 48 void(AudioInputStream* stream, | 48 void(AudioInputStream* stream, |
| 49 const AudioBus* src, | 49 const AudioBus* src, |
| 50 uint32_t hardware_delay_bytes, | 50 base::TimeDelta delay, |
| 51 base::TimeTicks delay_timestamp, |
| 51 double volume)); | 52 double volume)); |
| 52 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); | 53 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); |
| 53 }; | 54 }; |
| 54 | 55 |
| 55 class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { | 56 class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { |
| 56 public: | 57 public: |
| 57 FakeAudioInputCallback() | 58 FakeAudioInputCallback() |
| 58 : num_received_audio_frames_(0), | 59 : num_received_audio_frames_(0), |
| 59 data_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 60 data_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 60 base::WaitableEvent::InitialState::NOT_SIGNALED), | 61 base::WaitableEvent::InitialState::NOT_SIGNALED), |
| 61 error_(false) {} | 62 error_(false) {} |
| 62 | 63 |
| 63 bool error() const { return error_; } | 64 bool error() const { return error_; } |
| 64 int num_received_audio_frames() const { return num_received_audio_frames_; } | 65 int num_received_audio_frames() const { return num_received_audio_frames_; } |
| 65 | 66 |
| 66 // Waits until OnData() is called on another thread. | 67 // Waits until OnData() is called on another thread. |
| 67 void WaitForData() { | 68 void WaitForData() { |
| 68 data_event_.Wait(); | 69 data_event_.Wait(); |
| 69 } | 70 } |
| 70 | 71 |
| 71 void OnData(AudioInputStream* stream, | 72 void OnData(AudioInputStream* stream, |
| 72 const AudioBus* src, | 73 const AudioBus* src, |
| 73 uint32_t hardware_delay_bytes, | 74 base::TimeDelta delay, |
| 75 base::TimeTicks delay_timestamp, |
| 74 double volume) override { | 76 double volume) override { |
| 75 EXPECT_GE(hardware_delay_bytes, 0u); | 77 EXPECT_GE(delay, base::TimeDelta()); |
| 76 EXPECT_LT(hardware_delay_bytes, 0xFFFFu); // Arbitrarily picked. | |
| 77 num_received_audio_frames_ += src->frames(); | 78 num_received_audio_frames_ += src->frames(); |
| 78 data_event_.Signal(); | 79 data_event_.Signal(); |
| 79 } | 80 } |
| 80 | 81 |
| 81 void OnError(AudioInputStream* stream) override { | 82 void OnError(AudioInputStream* stream) override { |
| 82 error_ = true; | 83 error_ = true; |
| 83 } | 84 } |
| 84 | 85 |
| 85 private: | 86 private: |
| 86 int num_received_audio_frames_; | 87 int num_received_audio_frames_; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 fwrite(chunk, 1, chunk_size, binary_file_); | 126 fwrite(chunk, 1, chunk_size, binary_file_); |
| 126 buffer_.Seek(chunk_size); | 127 buffer_.Seek(chunk_size); |
| 127 bytes_written += chunk_size; | 128 bytes_written += chunk_size; |
| 128 } | 129 } |
| 129 base::CloseFile(binary_file_); | 130 base::CloseFile(binary_file_); |
| 130 } | 131 } |
| 131 | 132 |
| 132 // AudioInputStream::AudioInputCallback implementation. | 133 // AudioInputStream::AudioInputCallback implementation. |
| 133 void OnData(AudioInputStream* stream, | 134 void OnData(AudioInputStream* stream, |
| 134 const AudioBus* src, | 135 const AudioBus* src, |
| 135 uint32_t hardware_delay_bytes, | 136 base::TimeDelta delay, |
| 137 base::TimeTicks delay_timestamp, |
| 136 double volume) override { | 138 double volume) override { |
| 137 EXPECT_EQ(bits_per_sample_, 16); | 139 EXPECT_EQ(bits_per_sample_, 16); |
| 138 const int num_samples = src->frames() * src->channels(); | 140 const int num_samples = src->frames() * src->channels(); |
| 139 std::unique_ptr<int16_t> interleaved(new int16_t[num_samples]); | 141 std::unique_ptr<int16_t> interleaved(new int16_t[num_samples]); |
| 140 const int bytes_per_sample = sizeof(*interleaved); | 142 const int bytes_per_sample = sizeof(*interleaved); |
| 141 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); | 143 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); |
| 142 | 144 |
| 143 // Store data data in a temporary buffer to avoid making blocking | 145 // Store data data in a temporary buffer to avoid making blocking |
| 144 // fwrite() calls in the audio callback. The complete buffer will be | 146 // fwrite() calls in the audio callback. The complete buffer will be |
| 145 // written to file in the destructor. | 147 // written to file in the destructor. |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 | 379 |
| 378 // Derive the expected size in bytes of each recorded packet. | 380 // Derive the expected size in bytes of each recorded packet. |
| 379 uint32_t bytes_per_packet = | 381 uint32_t bytes_per_packet = |
| 380 aisw.channels() * aisw.frames_per_buffer() * (aisw.bits_per_sample() / 8); | 382 aisw.channels() * aisw.frames_per_buffer() * (aisw.bits_per_sample() / 8); |
| 381 | 383 |
| 382 { | 384 { |
| 383 // We use 10ms packets and will run the test until ten packets are received. | 385 // We use 10ms packets and will run the test until ten packets are received. |
| 384 // All should contain valid packets of the same size and a valid delay | 386 // All should contain valid packets of the same size and a valid delay |
| 385 // estimate. | 387 // estimate. |
| 386 base::RunLoop run_loop; | 388 base::RunLoop run_loop; |
| 387 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) | 389 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _, _)) |
| 388 .Times(AtLeast(10)) | 390 .Times(AtLeast(10)) |
| 389 .WillRepeatedly( | 391 .WillRepeatedly( |
| 390 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), | 392 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), |
| 391 run_loop.QuitWhenIdleClosure())); | 393 run_loop.QuitWhenIdleClosure())); |
| 392 ais->Start(&sink); | 394 ais->Start(&sink); |
| 393 run_loop.Run(); | 395 run_loop.Run(); |
| 394 ais->Stop(); | 396 ais->Stop(); |
| 395 } | 397 } |
| 396 | 398 |
| 397 // Store current packet size (to be used in the subsequent tests). | 399 // Store current packet size (to be used in the subsequent tests). |
| 398 int frames_per_buffer_10ms = aisw.frames_per_buffer(); | 400 int frames_per_buffer_10ms = aisw.frames_per_buffer(); |
| 399 | 401 |
| 400 ais.Close(); | 402 ais.Close(); |
| 401 | 403 |
| 402 // 20 ms packet size. | 404 // 20 ms packet size. |
| 403 | 405 |
| 404 count = 0; | 406 count = 0; |
| 405 ais.Reset(aisw.Create(2 * frames_per_buffer_10ms)); | 407 ais.Reset(aisw.Create(2 * frames_per_buffer_10ms)); |
| 406 EXPECT_TRUE(ais->Open()); | 408 EXPECT_TRUE(ais->Open()); |
| 407 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * | 409 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
| 408 (aisw.bits_per_sample() / 8); | 410 (aisw.bits_per_sample() / 8); |
| 409 | 411 |
| 410 { | 412 { |
| 411 base::RunLoop run_loop; | 413 base::RunLoop run_loop; |
| 412 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) | 414 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _, _)) |
| 413 .Times(AtLeast(10)) | 415 .Times(AtLeast(10)) |
| 414 .WillRepeatedly( | 416 .WillRepeatedly( |
| 415 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), | 417 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), |
| 416 run_loop.QuitWhenIdleClosure())); | 418 run_loop.QuitWhenIdleClosure())); |
| 417 ais->Start(&sink); | 419 ais->Start(&sink); |
| 418 run_loop.Run(); | 420 run_loop.Run(); |
| 419 ais->Stop(); | 421 ais->Stop(); |
| 420 ais.Close(); | 422 ais.Close(); |
| 421 } | 423 } |
| 422 | 424 |
| 423 // 5 ms packet size. | 425 // 5 ms packet size. |
| 424 | 426 |
| 425 count = 0; | 427 count = 0; |
| 426 ais.Reset(aisw.Create(frames_per_buffer_10ms / 2)); | 428 ais.Reset(aisw.Create(frames_per_buffer_10ms / 2)); |
| 427 EXPECT_TRUE(ais->Open()); | 429 EXPECT_TRUE(ais->Open()); |
| 428 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * | 430 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * |
| 429 (aisw.bits_per_sample() / 8); | 431 (aisw.bits_per_sample() / 8); |
| 430 | 432 |
| 431 { | 433 { |
| 432 base::RunLoop run_loop; | 434 base::RunLoop run_loop; |
| 433 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) | 435 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _, _)) |
| 434 .Times(AtLeast(10)) | 436 .Times(AtLeast(10)) |
| 435 .WillRepeatedly( | 437 .WillRepeatedly( |
| 436 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), | 438 CheckCountAndPostQuitTask(&count, 10, message_loop_.task_runner(), |
| 437 run_loop.QuitWhenIdleClosure())); | 439 run_loop.QuitWhenIdleClosure())); |
| 438 ais->Start(&sink); | 440 ais->Start(&sink); |
| 439 run_loop.Run(); | 441 run_loop.Run(); |
| 440 ais->Stop(); | 442 ais->Stop(); |
| 441 ais.Close(); | 443 ais.Close(); |
| 442 } | 444 } |
| 443 } | 445 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); | 495 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); |
| 494 VLOG(0) << ">> Speak into the default microphone while recording."; | 496 VLOG(0) << ">> Speak into the default microphone while recording."; |
| 495 ais->Start(&file_sink); | 497 ais->Start(&file_sink); |
| 496 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); | 498 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); |
| 497 ais->Stop(); | 499 ais->Stop(); |
| 498 VLOG(0) << ">> Recording has stopped."; | 500 VLOG(0) << ">> Recording has stopped."; |
| 499 ais.Close(); | 501 ais.Close(); |
| 500 } | 502 } |
| 501 | 503 |
| 502 } // namespace media | 504 } // namespace media |
| OLD | NEW |