| 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/run_loop.h" |
| 9 #include "base/test/test_timeouts.h" | 9 #include "base/test/test_timeouts.h" |
| 10 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 namespace media { | 24 namespace media { |
| 25 | 25 |
| 26 ACTION_P4(CheckCountAndPostQuitTask, count, limit, loop, closure) { | 26 ACTION_P4(CheckCountAndPostQuitTask, count, limit, loop, closure) { |
| 27 if (++*count >= limit) { | 27 if (++*count >= limit) { |
| 28 loop->PostTask(FROM_HERE, closure); | 28 loop->PostTask(FROM_HERE, closure); |
| 29 } | 29 } |
| 30 } | 30 } |
| 31 | 31 |
| 32 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { | 32 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { |
| 33 public: | 33 public: |
| 34 MOCK_METHOD5(OnData, void(AudioInputStream* stream, | 34 MOCK_METHOD4(OnData, |
| 35 const uint8* src, uint32 size, | 35 void(AudioInputStream* stream, |
| 36 uint32 hardware_delay_bytes, double volume)); | 36 const AudioBus* src, |
| 37 uint32 hardware_delay_bytes, |
| 38 double volume)); |
| 37 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); | 39 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); |
| 38 }; | 40 }; |
| 39 | 41 |
| 40 // This audio sink implementation should be used for manual tests only since | 42 // This audio sink implementation should be used for manual tests only since |
| 41 // the recorded data is stored on a raw binary data file. | 43 // the recorded data is stored on a raw binary data file. |
| 42 // The last test (WriteToFileAudioSink) - which is disabled by default - | 44 // The last test (WriteToFileAudioSink) - which is disabled by default - |
| 43 // can use this audio sink to store the captured data on a file for offline | 45 // can use this audio sink to store the captured data on a file for offline |
| 44 // analysis. | 46 // analysis. |
| 45 class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback { | 47 class WriteToFileAudioSink : public AudioInputStream::AudioInputCallback { |
| 46 public: | 48 public: |
| (...skipping 20 matching lines...) Expand all Loading... |
| 67 // Write recorded data chunk to the file and prepare for next chunk. | 69 // Write recorded data chunk to the file and prepare for next chunk. |
| 68 fwrite(chunk, 1, chunk_size, file_); | 70 fwrite(chunk, 1, chunk_size, file_); |
| 69 buffer_.Seek(chunk_size); | 71 buffer_.Seek(chunk_size); |
| 70 bytes_written += chunk_size; | 72 bytes_written += chunk_size; |
| 71 } | 73 } |
| 72 fclose(file_); | 74 fclose(file_); |
| 73 } | 75 } |
| 74 | 76 |
| 75 // AudioInputStream::AudioInputCallback implementation. | 77 // AudioInputStream::AudioInputCallback implementation. |
| 76 virtual void OnData(AudioInputStream* stream, | 78 virtual void OnData(AudioInputStream* stream, |
| 77 const uint8* src, uint32 size, | 79 const AudioBus* src, |
| 78 uint32 hardware_delay_bytes, double volume) OVERRIDE { | 80 uint32 hardware_delay_bytes, |
| 81 double volume) OVERRIDE { |
| 82 const int num_samples = src->frames() * src->channels(); |
| 83 scoped_ptr<int16> interleaved(new int16[num_samples]); |
| 84 const int bytes_per_sample = sizeof(*interleaved); |
| 85 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); |
| 86 |
| 79 // Store data data in a temporary buffer to avoid making blocking | 87 // Store data data in a temporary buffer to avoid making blocking |
| 80 // fwrite() calls in the audio callback. The complete buffer will be | 88 // fwrite() calls in the audio callback. The complete buffer will be |
| 81 // written to file in the destructor. | 89 // written to file in the destructor. |
| 82 if (buffer_.Append(src, size)) { | 90 const int size = bytes_per_sample * num_samples; |
| 91 if (buffer_.Append((const uint8*)interleaved.get(), size)) { |
| 83 bytes_to_write_ += size; | 92 bytes_to_write_ += size; |
| 84 } | 93 } |
| 85 } | 94 } |
| 86 | 95 |
| 87 virtual void OnError(AudioInputStream* stream) OVERRIDE {} | 96 virtual void OnError(AudioInputStream* stream) OVERRIDE {} |
| 88 | 97 |
| 89 private: | 98 private: |
| 90 media::SeekableBuffer buffer_; | 99 media::SeekableBuffer buffer_; |
| 91 FILE* file_; | 100 FILE* file_; |
| 92 int bytes_to_write_; | 101 int bytes_to_write_; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) { | 226 TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyMonoRecording) { |
| 218 if (!CanRunAudioTests()) | 227 if (!CanRunAudioTests()) |
| 219 return; | 228 return; |
| 220 | 229 |
| 221 int count = 0; | 230 int count = 0; |
| 222 | 231 |
| 223 // Create an audio input stream which records in mono. | 232 // Create an audio input stream which records in mono. |
| 224 AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_MONO); | 233 AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_MONO); |
| 225 EXPECT_TRUE(ais->Open()); | 234 EXPECT_TRUE(ais->Open()); |
| 226 | 235 |
| 227 int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); | |
| 228 int samples_per_packet = fs / 100; | |
| 229 int bits_per_sample = 16; | |
| 230 uint32 bytes_per_packet = samples_per_packet * (bits_per_sample / 8); | |
| 231 | |
| 232 MockAudioInputCallback sink; | 236 MockAudioInputCallback sink; |
| 233 | 237 |
| 234 // We use 10ms packets and will run the test until ten packets are received. | 238 // We use 10ms packets and will run the test until ten packets are received. |
| 235 // All should contain valid packets of the same size and a valid delay | 239 // All should contain valid packets of the same size and a valid delay |
| 236 // estimate. | 240 // estimate. |
| 237 base::RunLoop run_loop; | 241 base::RunLoop run_loop; |
| 238 EXPECT_CALL(sink, OnData(ais, NotNull(), bytes_per_packet, _, _)) | 242 EXPECT_CALL(sink, OnData(ais, NotNull(), _, _)) |
| 239 .Times(AtLeast(10)) | 243 .Times(AtLeast(10)) |
| 240 .WillRepeatedly(CheckCountAndPostQuitTask( | 244 .WillRepeatedly(CheckCountAndPostQuitTask( |
| 241 &count, 10, &message_loop_, run_loop.QuitClosure())); | 245 &count, 10, &message_loop_, run_loop.QuitClosure())); |
| 242 ais->Start(&sink); | 246 ais->Start(&sink); |
| 243 run_loop.Run(); | 247 run_loop.Run(); |
| 244 ais->Stop(); | 248 ais->Stop(); |
| 245 ais->Close(); | 249 ais->Close(); |
| 246 } | 250 } |
| 247 | 251 |
| 248 // Verify that recording starts and stops correctly in mono using mocked sink. | 252 // Verify that recording starts and stops correctly in mono using mocked sink. |
| 249 TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) { | 253 TEST_F(MacAudioInputTest, AUAudioInputStreamVerifyStereoRecording) { |
| 250 if (!CanRunAudioTests()) | 254 if (!CanRunAudioTests()) |
| 251 return; | 255 return; |
| 252 | 256 |
| 253 int count = 0; | 257 int count = 0; |
| 254 | 258 |
| 255 // Create an audio input stream which records in stereo. | 259 // Create an audio input stream which records in stereo. |
| 256 AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_STEREO); | 260 AudioInputStream* ais = CreateAudioInputStream(CHANNEL_LAYOUT_STEREO); |
| 257 EXPECT_TRUE(ais->Open()); | 261 EXPECT_TRUE(ais->Open()); |
| 258 | 262 |
| 259 int fs = static_cast<int>(AUAudioInputStream::HardwareSampleRate()); | |
| 260 int samples_per_packet = fs / 100; | |
| 261 int bits_per_sample = 16; | |
| 262 uint32 bytes_per_packet = 2 * samples_per_packet * (bits_per_sample / 8); | |
| 263 | |
| 264 MockAudioInputCallback sink; | 263 MockAudioInputCallback sink; |
| 265 | 264 |
| 266 // We use 10ms packets and will run the test until ten packets are received. | 265 // We use 10ms packets and will run the test until ten packets are received. |
| 267 // All should contain valid packets of the same size and a valid delay | 266 // All should contain valid packets of the same size and a valid delay |
| 268 // estimate. | 267 // estimate. |
| 269 // TODO(henrika): http://crbug.com/154352 forced us to run the capture side | 268 // TODO(henrika): http://crbug.com/154352 forced us to run the capture side |
| 270 // using a native buffer size of 128 audio frames and combine it with a FIFO | 269 // using a native buffer size of 128 audio frames and combine it with a FIFO |
| 271 // to match the requested size by the client. This change might also have | 270 // to match the requested size by the client. This change might also have |
| 272 // modified the delay estimates since the existing Ge(bytes_per_packet) for | 271 // modified the delay estimates since the existing Ge(bytes_per_packet) for |
| 273 // parameter #4 does no longer pass. I am removing this restriction here to | 272 // parameter #4 does no longer pass. I am removing this restriction here to |
| 274 // ensure that we can land the patch but will revisit this test again when | 273 // ensure that we can land the patch but will revisit this test again when |
| 275 // more analysis of the delay estimates are done. | 274 // more analysis of the delay estimates are done. |
| 276 base::RunLoop run_loop; | 275 base::RunLoop run_loop; |
| 277 EXPECT_CALL(sink, OnData(ais, NotNull(), bytes_per_packet, _, _)) | 276 EXPECT_CALL(sink, OnData(ais, NotNull(), _, _)) |
| 278 .Times(AtLeast(10)) | 277 .Times(AtLeast(10)) |
| 279 .WillRepeatedly(CheckCountAndPostQuitTask( | 278 .WillRepeatedly(CheckCountAndPostQuitTask( |
| 280 &count, 10, &message_loop_, run_loop.QuitClosure())); | 279 &count, 10, &message_loop_, run_loop.QuitClosure())); |
| 281 ais->Start(&sink); | 280 ais->Start(&sink); |
| 282 run_loop.Run(); | 281 run_loop.Run(); |
| 283 ais->Stop(); | 282 ais->Stop(); |
| 284 ais->Close(); | 283 ais->Close(); |
| 285 } | 284 } |
| 286 | 285 |
| 287 // This test is intended for manual tests and should only be enabled | 286 // This test is intended for manual tests and should only be enabled |
| (...skipping 16 matching lines...) Expand all Loading... |
| 304 WriteToFileAudioSink file_sink(file_name); | 303 WriteToFileAudioSink file_sink(file_name); |
| 305 fprintf(stderr, " >> Speak into the mic while recording...\n"); | 304 fprintf(stderr, " >> Speak into the mic while recording...\n"); |
| 306 ais->Start(&file_sink); | 305 ais->Start(&file_sink); |
| 307 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); | 306 base::PlatformThread::Sleep(TestTimeouts::action_timeout()); |
| 308 ais->Stop(); | 307 ais->Stop(); |
| 309 fprintf(stderr, " >> Recording has stopped.\n"); | 308 fprintf(stderr, " >> Recording has stopped.\n"); |
| 310 ais->Close(); | 309 ais->Close(); |
| 311 } | 310 } |
| 312 | 311 |
| 313 } // namespace media | 312 } // namespace media |
| OLD | NEW |