| 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 <windows.h> | 5 #include <windows.h> |
| 6 #include <mmsystem.h> | 6 #include <mmsystem.h> |
| 7 | 7 |
| 8 #include "base/basictypes.h" | |
| 9 #include "base/environment.h" | 8 #include "base/environment.h" |
| 10 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 11 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 13 #include "base/path_service.h" | 12 #include "base/path_service.h" |
| 14 #include "base/test/test_timeouts.h" | 13 #include "base/test/test_timeouts.h" |
| 15 #include "base/win/scoped_com_initializer.h" | 14 #include "base/win/scoped_com_initializer.h" |
| 16 #include "media/audio/audio_io.h" | 15 #include "media/audio/audio_io.h" |
| 17 #include "media/audio/audio_manager_base.h" | 16 #include "media/audio/audio_manager_base.h" |
| 18 #include "media/audio/audio_unittest_util.h" | 17 #include "media/audio/audio_unittest_util.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 34 if (++*count >= limit) { | 33 if (++*count >= limit) { |
| 35 loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); | 34 loop->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); |
| 36 } | 35 } |
| 37 } | 36 } |
| 38 | 37 |
| 39 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { | 38 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { |
| 40 public: | 39 public: |
| 41 MOCK_METHOD4(OnData, | 40 MOCK_METHOD4(OnData, |
| 42 void(AudioInputStream* stream, | 41 void(AudioInputStream* stream, |
| 43 const AudioBus* src, | 42 const AudioBus* src, |
| 44 uint32 hardware_delay_bytes, | 43 uint32_t hardware_delay_bytes, |
| 45 double volume)); | 44 double volume)); |
| 46 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); | 45 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); |
| 47 }; | 46 }; |
| 48 | 47 |
| 49 class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { | 48 class FakeAudioInputCallback : public AudioInputStream::AudioInputCallback { |
| 50 public: | 49 public: |
| 51 FakeAudioInputCallback() | 50 FakeAudioInputCallback() |
| 52 : num_received_audio_frames_(0), | 51 : num_received_audio_frames_(0), |
| 53 data_event_(false, false), | 52 data_event_(false, false), |
| 54 error_(false) {} | 53 error_(false) {} |
| 55 | 54 |
| 56 bool error() const { return error_; } | 55 bool error() const { return error_; } |
| 57 int num_received_audio_frames() const { return num_received_audio_frames_; } | 56 int num_received_audio_frames() const { return num_received_audio_frames_; } |
| 58 | 57 |
| 59 // Waits until OnData() is called on another thread. | 58 // Waits until OnData() is called on another thread. |
| 60 void WaitForData() { | 59 void WaitForData() { |
| 61 data_event_.Wait(); | 60 data_event_.Wait(); |
| 62 } | 61 } |
| 63 | 62 |
| 64 void OnData(AudioInputStream* stream, | 63 void OnData(AudioInputStream* stream, |
| 65 const AudioBus* src, | 64 const AudioBus* src, |
| 66 uint32 hardware_delay_bytes, | 65 uint32_t hardware_delay_bytes, |
| 67 double volume) override { | 66 double volume) override { |
| 68 EXPECT_GE(hardware_delay_bytes, 0u); | 67 EXPECT_GE(hardware_delay_bytes, 0u); |
| 69 EXPECT_LT(hardware_delay_bytes, 0xFFFFu); // Arbitrarily picked. | 68 EXPECT_LT(hardware_delay_bytes, 0xFFFFu); // Arbitrarily picked. |
| 70 num_received_audio_frames_ += src->frames(); | 69 num_received_audio_frames_ += src->frames(); |
| 71 data_event_.Signal(); | 70 data_event_.Signal(); |
| 72 } | 71 } |
| 73 | 72 |
| 74 void OnError(AudioInputStream* stream) override { | 73 void OnError(AudioInputStream* stream) override { |
| 75 error_ = true; | 74 error_ = true; |
| 76 } | 75 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 100 file_path = file_path.AppendASCII(file_name); | 99 file_path = file_path.AppendASCII(file_name); |
| 101 binary_file_ = base::OpenFile(file_path, "wb"); | 100 binary_file_ = base::OpenFile(file_path, "wb"); |
| 102 DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; | 101 DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; |
| 103 VLOG(0) << ">> Output file: " << file_path.value() << " has been created."; | 102 VLOG(0) << ">> Output file: " << file_path.value() << " has been created."; |
| 104 VLOG(0) << "bits_per_sample_:" << bits_per_sample_; | 103 VLOG(0) << "bits_per_sample_:" << bits_per_sample_; |
| 105 } | 104 } |
| 106 | 105 |
| 107 ~WriteToFileAudioSink() override { | 106 ~WriteToFileAudioSink() override { |
| 108 size_t bytes_written = 0; | 107 size_t bytes_written = 0; |
| 109 while (bytes_written < bytes_to_write_) { | 108 while (bytes_written < bytes_to_write_) { |
| 110 const uint8* chunk; | 109 const uint8_t* chunk; |
| 111 int chunk_size; | 110 int chunk_size; |
| 112 | 111 |
| 113 // Stop writing if no more data is available. | 112 // Stop writing if no more data is available. |
| 114 if (!buffer_.GetCurrentChunk(&chunk, &chunk_size)) | 113 if (!buffer_.GetCurrentChunk(&chunk, &chunk_size)) |
| 115 break; | 114 break; |
| 116 | 115 |
| 117 // Write recorded data chunk to the file and prepare for next chunk. | 116 // Write recorded data chunk to the file and prepare for next chunk. |
| 118 fwrite(chunk, 1, chunk_size, binary_file_); | 117 fwrite(chunk, 1, chunk_size, binary_file_); |
| 119 buffer_.Seek(chunk_size); | 118 buffer_.Seek(chunk_size); |
| 120 bytes_written += chunk_size; | 119 bytes_written += chunk_size; |
| 121 } | 120 } |
| 122 base::CloseFile(binary_file_); | 121 base::CloseFile(binary_file_); |
| 123 } | 122 } |
| 124 | 123 |
| 125 // AudioInputStream::AudioInputCallback implementation. | 124 // AudioInputStream::AudioInputCallback implementation. |
| 126 void OnData(AudioInputStream* stream, | 125 void OnData(AudioInputStream* stream, |
| 127 const AudioBus* src, | 126 const AudioBus* src, |
| 128 uint32 hardware_delay_bytes, | 127 uint32_t hardware_delay_bytes, |
| 129 double volume) override { | 128 double volume) override { |
| 130 EXPECT_EQ(bits_per_sample_, 16); | 129 EXPECT_EQ(bits_per_sample_, 16); |
| 131 const int num_samples = src->frames() * src->channels(); | 130 const int num_samples = src->frames() * src->channels(); |
| 132 scoped_ptr<int16> interleaved(new int16[num_samples]); | 131 scoped_ptr<int16_t> interleaved(new int16_t[num_samples]); |
| 133 const int bytes_per_sample = sizeof(*interleaved); | 132 const int bytes_per_sample = sizeof(*interleaved); |
| 134 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); | 133 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); |
| 135 | 134 |
| 136 // Store data data in a temporary buffer to avoid making blocking | 135 // Store data data in a temporary buffer to avoid making blocking |
| 137 // fwrite() calls in the audio callback. The complete buffer will be | 136 // fwrite() calls in the audio callback. The complete buffer will be |
| 138 // written to file in the destructor. | 137 // written to file in the destructor. |
| 139 const int size = bytes_per_sample * num_samples; | 138 const int size = bytes_per_sample * num_samples; |
| 140 if (buffer_.Append((const uint8*)interleaved.get(), size)) { | 139 if (buffer_.Append((const uint8_t*)interleaved.get(), size)) { |
| 141 bytes_to_write_ += size; | 140 bytes_to_write_ += size; |
| 142 } | 141 } |
| 143 } | 142 } |
| 144 | 143 |
| 145 void OnError(AudioInputStream* stream) override {} | 144 void OnError(AudioInputStream* stream) override {} |
| 146 | 145 |
| 147 private: | 146 private: |
| 148 int bits_per_sample_; | 147 int bits_per_sample_; |
| 149 media::SeekableBuffer buffer_; | 148 media::SeekableBuffer buffer_; |
| 150 FILE* binary_file_; | 149 FILE* binary_file_; |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 | 352 |
| 354 // Create default WASAPI input stream which records in stereo using | 353 // Create default WASAPI input stream which records in stereo using |
| 355 // the shared mixing rate. The default buffer size is 10ms. | 354 // the shared mixing rate. The default buffer size is 10ms. |
| 356 AudioInputStreamWrapper aisw(audio_manager.get()); | 355 AudioInputStreamWrapper aisw(audio_manager.get()); |
| 357 ScopedAudioInputStream ais(aisw.Create()); | 356 ScopedAudioInputStream ais(aisw.Create()); |
| 358 EXPECT_TRUE(ais->Open()); | 357 EXPECT_TRUE(ais->Open()); |
| 359 | 358 |
| 360 MockAudioInputCallback sink; | 359 MockAudioInputCallback sink; |
| 361 | 360 |
| 362 // Derive the expected size in bytes of each recorded packet. | 361 // Derive the expected size in bytes of each recorded packet. |
| 363 uint32 bytes_per_packet = aisw.channels() * aisw.frames_per_buffer() * | 362 uint32_t bytes_per_packet = |
| 364 (aisw.bits_per_sample() / 8); | 363 aisw.channels() * aisw.frames_per_buffer() * (aisw.bits_per_sample() / 8); |
| 365 | 364 |
| 366 // We use 10ms packets and will run the test until ten packets are received. | 365 // We use 10ms packets and will run the test until ten packets are received. |
| 367 // All should contain valid packets of the same size and a valid delay | 366 // All should contain valid packets of the same size and a valid delay |
| 368 // estimate. | 367 // estimate. |
| 369 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) | 368 EXPECT_CALL(sink, OnData(ais.get(), NotNull(), _, _)) |
| 370 .Times(AtLeast(10)) | 369 .Times(AtLeast(10)) |
| 371 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); | 370 .WillRepeatedly(CheckCountAndPostQuitTask(&count, 10, &loop)); |
| 372 ais->Start(&sink); | 371 ais->Start(&sink); |
| 373 loop.Run(); | 372 loop.Run(); |
| 374 ais->Stop(); | 373 ais->Stop(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); | 462 WriteToFileAudioSink file_sink(file_name, aisw.bits_per_sample()); |
| 464 VLOG(0) << ">> Speak into the default microphone while recording."; | 463 VLOG(0) << ">> Speak into the default microphone while recording."; |
| 465 ais->Start(&file_sink); | 464 ais->Start(&file_sink); |
| 466 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); | 465 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); |
| 467 ais->Stop(); | 466 ais->Stop(); |
| 468 VLOG(0) << ">> Recording has stopped."; | 467 VLOG(0) << ">> Recording has stopped."; |
| 469 ais.Close(); | 468 ais.Close(); |
| 470 } | 469 } |
| 471 | 470 |
| 472 } // namespace media | 471 } // namespace media |
| OLD | NEW |