OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/android/build_info.h" | 5 #include "base/android/build_info.h" |
6 #include "base/basictypes.h" | |
7 #include "base/bind.h" | 6 #include "base/bind.h" |
8 #include "base/files/file_util.h" | 7 #include "base/files/file_util.h" |
9 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
10 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
11 #include "base/path_service.h" | 10 #include "base/path_service.h" |
12 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
13 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
14 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
15 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
16 #include "base/test/test_timeouts.h" | 15 #include "base/test/test_timeouts.h" |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 << (params.effects() & AudioParameters::ECHO_CANCELLER); | 145 << (params.effects() & AudioParameters::ECHO_CANCELLER); |
147 return os; | 146 return os; |
148 } | 147 } |
149 | 148 |
150 // Gmock implementation of AudioInputStream::AudioInputCallback. | 149 // Gmock implementation of AudioInputStream::AudioInputCallback. |
151 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { | 150 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback { |
152 public: | 151 public: |
153 MOCK_METHOD4(OnData, | 152 MOCK_METHOD4(OnData, |
154 void(AudioInputStream* stream, | 153 void(AudioInputStream* stream, |
155 const AudioBus* src, | 154 const AudioBus* src, |
156 uint32 hardware_delay_bytes, | 155 uint32_t hardware_delay_bytes, |
157 double volume)); | 156 double volume)); |
158 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); | 157 MOCK_METHOD1(OnError, void(AudioInputStream* stream)); |
159 }; | 158 }; |
160 | 159 |
161 // Implements AudioOutputStream::AudioSourceCallback and provides audio data | 160 // Implements AudioOutputStream::AudioSourceCallback and provides audio data |
162 // by reading from a data file. | 161 // by reading from a data file. |
163 class FileAudioSource : public AudioOutputStream::AudioSourceCallback { | 162 class FileAudioSource : public AudioOutputStream::AudioSourceCallback { |
164 public: | 163 public: |
165 explicit FileAudioSource(base::WaitableEvent* event, const std::string& name) | 164 explicit FileAudioSource(base::WaitableEvent* event, const std::string& name) |
166 : event_(event), pos_(0) { | 165 : event_(event), pos_(0) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); | 240 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); |
242 file_path = file_path.AppendASCII(file_name.c_str()); | 241 file_path = file_path.AppendASCII(file_name.c_str()); |
243 binary_file_ = base::OpenFile(file_path, "wb"); | 242 binary_file_ = base::OpenFile(file_path, "wb"); |
244 DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; | 243 DLOG_IF(ERROR, !binary_file_) << "Failed to open binary PCM data file."; |
245 DVLOG(0) << "Writing to file: " << file_path.value().c_str(); | 244 DVLOG(0) << "Writing to file: " << file_path.value().c_str(); |
246 } | 245 } |
247 | 246 |
248 ~FileAudioSink() override { | 247 ~FileAudioSink() override { |
249 int bytes_written = 0; | 248 int bytes_written = 0; |
250 while (bytes_written < buffer_->forward_capacity()) { | 249 while (bytes_written < buffer_->forward_capacity()) { |
251 const uint8* chunk; | 250 const uint8_t* chunk; |
252 int chunk_size; | 251 int chunk_size; |
253 | 252 |
254 // Stop writing if no more data is available. | 253 // Stop writing if no more data is available. |
255 if (!buffer_->GetCurrentChunk(&chunk, &chunk_size)) | 254 if (!buffer_->GetCurrentChunk(&chunk, &chunk_size)) |
256 break; | 255 break; |
257 | 256 |
258 // Write recorded data chunk to the file and prepare for next chunk. | 257 // Write recorded data chunk to the file and prepare for next chunk. |
259 // TODO(henrika): use file_util:: instead. | 258 // TODO(henrika): use file_util:: instead. |
260 fwrite(chunk, 1, chunk_size, binary_file_); | 259 fwrite(chunk, 1, chunk_size, binary_file_); |
261 buffer_->Seek(chunk_size); | 260 buffer_->Seek(chunk_size); |
262 bytes_written += chunk_size; | 261 bytes_written += chunk_size; |
263 } | 262 } |
264 base::CloseFile(binary_file_); | 263 base::CloseFile(binary_file_); |
265 } | 264 } |
266 | 265 |
267 // AudioInputStream::AudioInputCallback implementation. | 266 // AudioInputStream::AudioInputCallback implementation. |
268 void OnData(AudioInputStream* stream, | 267 void OnData(AudioInputStream* stream, |
269 const AudioBus* src, | 268 const AudioBus* src, |
270 uint32 hardware_delay_bytes, | 269 uint32_t hardware_delay_bytes, |
271 double volume) override { | 270 double volume) override { |
272 const int num_samples = src->frames() * src->channels(); | 271 const int num_samples = src->frames() * src->channels(); |
273 scoped_ptr<int16> interleaved(new int16[num_samples]); | 272 scoped_ptr<int16_t> interleaved(new int16_t[num_samples]); |
274 const int bytes_per_sample = sizeof(*interleaved); | 273 const int bytes_per_sample = sizeof(*interleaved); |
275 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); | 274 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); |
276 | 275 |
277 // Store data data in a temporary buffer to avoid making blocking | 276 // Store data data in a temporary buffer to avoid making blocking |
278 // fwrite() calls in the audio callback. The complete buffer will be | 277 // fwrite() calls in the audio callback. The complete buffer will be |
279 // written to file in the destructor. | 278 // written to file in the destructor. |
280 const int size = bytes_per_sample * num_samples; | 279 const int size = bytes_per_sample * num_samples; |
281 if (!buffer_->Append((const uint8*)interleaved.get(), size)) | 280 if (!buffer_->Append((const uint8_t*)interleaved.get(), size)) |
282 event_->Signal(); | 281 event_->Signal(); |
283 } | 282 } |
284 | 283 |
285 void OnError(AudioInputStream* stream) override {} | 284 void OnError(AudioInputStream* stream) override {} |
286 | 285 |
287 private: | 286 private: |
288 base::WaitableEvent* event_; | 287 base::WaitableEvent* event_; |
289 AudioParameters params_; | 288 AudioParameters params_; |
290 scoped_ptr<media::SeekableBuffer> buffer_; | 289 scoped_ptr<media::SeekableBuffer> buffer_; |
291 FILE* binary_file_; | 290 FILE* binary_file_; |
292 | 291 |
293 DISALLOW_COPY_AND_ASSIGN(FileAudioSink); | 292 DISALLOW_COPY_AND_ASSIGN(FileAudioSink); |
294 }; | 293 }; |
295 | 294 |
296 // Implements AudioInputCallback and AudioSourceCallback to support full | 295 // Implements AudioInputCallback and AudioSourceCallback to support full |
297 // duplex audio where captured samples are played out in loopback after | 296 // duplex audio where captured samples are played out in loopback after |
298 // reading from a temporary FIFO storage. | 297 // reading from a temporary FIFO storage. |
299 class FullDuplexAudioSinkSource | 298 class FullDuplexAudioSinkSource |
300 : public AudioInputStream::AudioInputCallback, | 299 : public AudioInputStream::AudioInputCallback, |
301 public AudioOutputStream::AudioSourceCallback { | 300 public AudioOutputStream::AudioSourceCallback { |
302 public: | 301 public: |
303 explicit FullDuplexAudioSinkSource(const AudioParameters& params) | 302 explicit FullDuplexAudioSinkSource(const AudioParameters& params) |
304 : params_(params), | 303 : params_(params), |
305 previous_time_(base::TimeTicks::Now()), | 304 previous_time_(base::TimeTicks::Now()), |
306 started_(false) { | 305 started_(false) { |
307 // Start with a reasonably small FIFO size. It will be increased | 306 // Start with a reasonably small FIFO size. It will be increased |
308 // dynamically during the test if required. | 307 // dynamically during the test if required. |
309 fifo_.reset(new media::SeekableBuffer(0, 2 * params.GetBytesPerBuffer())); | 308 fifo_.reset(new media::SeekableBuffer(0, 2 * params.GetBytesPerBuffer())); |
310 buffer_.reset(new uint8[params_.GetBytesPerBuffer()]); | 309 buffer_.reset(new uint8_t[params_.GetBytesPerBuffer()]); |
311 } | 310 } |
312 | 311 |
313 ~FullDuplexAudioSinkSource() override {} | 312 ~FullDuplexAudioSinkSource() override {} |
314 | 313 |
315 // AudioInputStream::AudioInputCallback implementation | 314 // AudioInputStream::AudioInputCallback implementation |
316 void OnData(AudioInputStream* stream, | 315 void OnData(AudioInputStream* stream, |
317 const AudioBus* src, | 316 const AudioBus* src, |
318 uint32 hardware_delay_bytes, | 317 uint32_t hardware_delay_bytes, |
319 double volume) override { | 318 double volume) override { |
320 const base::TimeTicks now_time = base::TimeTicks::Now(); | 319 const base::TimeTicks now_time = base::TimeTicks::Now(); |
321 const int diff = (now_time - previous_time_).InMilliseconds(); | 320 const int diff = (now_time - previous_time_).InMilliseconds(); |
322 | 321 |
323 EXPECT_EQ(params_.bits_per_sample(), 16); | 322 EXPECT_EQ(params_.bits_per_sample(), 16); |
324 const int num_samples = src->frames() * src->channels(); | 323 const int num_samples = src->frames() * src->channels(); |
325 scoped_ptr<int16> interleaved(new int16[num_samples]); | 324 scoped_ptr<int16_t> interleaved(new int16_t[num_samples]); |
326 const int bytes_per_sample = sizeof(*interleaved); | 325 const int bytes_per_sample = sizeof(*interleaved); |
327 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); | 326 src->ToInterleaved(src->frames(), bytes_per_sample, interleaved.get()); |
328 const int size = bytes_per_sample * num_samples; | 327 const int size = bytes_per_sample * num_samples; |
329 | 328 |
330 base::AutoLock lock(lock_); | 329 base::AutoLock lock(lock_); |
331 if (diff > 1000) { | 330 if (diff > 1000) { |
332 started_ = true; | 331 started_ = true; |
333 previous_time_ = now_time; | 332 previous_time_ = now_time; |
334 | 333 |
335 // Log out the extra delay added by the FIFO. This is a best effort | 334 // Log out the extra delay added by the FIFO. This is a best effort |
336 // estimate. We might be +- 10ms off here. | 335 // estimate. We might be +- 10ms off here. |
337 int extra_fifo_delay = | 336 int extra_fifo_delay = |
338 static_cast<int>(BytesToMilliseconds(fifo_->forward_bytes() + size)); | 337 static_cast<int>(BytesToMilliseconds(fifo_->forward_bytes() + size)); |
339 DVLOG(1) << extra_fifo_delay; | 338 DVLOG(1) << extra_fifo_delay; |
340 } | 339 } |
341 | 340 |
342 // We add an initial delay of ~1 second before loopback starts to ensure | 341 // We add an initial delay of ~1 second before loopback starts to ensure |
343 // a stable callback sequence and to avoid initial bursts which might add | 342 // a stable callback sequence and to avoid initial bursts which might add |
344 // to the extra FIFO delay. | 343 // to the extra FIFO delay. |
345 if (!started_) | 344 if (!started_) |
346 return; | 345 return; |
347 | 346 |
348 // Append new data to the FIFO and extend the size if the max capacity | 347 // Append new data to the FIFO and extend the size if the max capacity |
349 // was exceeded. Flush the FIFO when extended just in case. | 348 // was exceeded. Flush the FIFO when extended just in case. |
350 if (!fifo_->Append((const uint8*)interleaved.get(), size)) { | 349 if (!fifo_->Append((const uint8_t*)interleaved.get(), size)) { |
351 fifo_->set_forward_capacity(2 * fifo_->forward_capacity()); | 350 fifo_->set_forward_capacity(2 * fifo_->forward_capacity()); |
352 fifo_->Clear(); | 351 fifo_->Clear(); |
353 } | 352 } |
354 } | 353 } |
355 | 354 |
356 void OnError(AudioInputStream* stream) override {} | 355 void OnError(AudioInputStream* stream) override {} |
357 | 356 |
358 // AudioOutputStream::AudioSourceCallback implementation | 357 // AudioOutputStream::AudioSourceCallback implementation |
359 int OnMoreData(AudioBus* dest, | 358 int OnMoreData(AudioBus* dest, |
360 uint32_t total_bytes_delay, | 359 uint32_t total_bytes_delay, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 const int frames = bytes / params_.GetBytesPerFrame(); | 394 const int frames = bytes / params_.GetBytesPerFrame(); |
396 return (base::TimeDelta::FromMicroseconds( | 395 return (base::TimeDelta::FromMicroseconds( |
397 frames * base::Time::kMicrosecondsPerSecond / | 396 frames * base::Time::kMicrosecondsPerSecond / |
398 static_cast<double>(params_.sample_rate()))).InMillisecondsF(); | 397 static_cast<double>(params_.sample_rate()))).InMillisecondsF(); |
399 } | 398 } |
400 | 399 |
401 AudioParameters params_; | 400 AudioParameters params_; |
402 base::TimeTicks previous_time_; | 401 base::TimeTicks previous_time_; |
403 base::Lock lock_; | 402 base::Lock lock_; |
404 scoped_ptr<media::SeekableBuffer> fifo_; | 403 scoped_ptr<media::SeekableBuffer> fifo_; |
405 scoped_ptr<uint8[]> buffer_; | 404 scoped_ptr<uint8_t[]> buffer_; |
406 bool started_; | 405 bool started_; |
407 | 406 |
408 DISALLOW_COPY_AND_ASSIGN(FullDuplexAudioSinkSource); | 407 DISALLOW_COPY_AND_ASSIGN(FullDuplexAudioSinkSource); |
409 }; | 408 }; |
410 | 409 |
411 // Test fixture class for tests which only exercise the output path. | 410 // Test fixture class for tests which only exercise the output path. |
412 class AudioAndroidOutputTest : public testing::Test { | 411 class AudioAndroidOutputTest : public testing::Test { |
413 public: | 412 public: |
414 AudioAndroidOutputTest() | 413 AudioAndroidOutputTest() |
415 : loop_(new base::MessageLoopForUI()), | 414 : loop_(new base::MessageLoopForUI()), |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20)); | 950 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20)); |
952 printf("\n"); | 951 printf("\n"); |
953 StopAndCloseAudioOutputStreamOnAudioThread(); | 952 StopAndCloseAudioOutputStreamOnAudioThread(); |
954 StopAndCloseAudioInputStreamOnAudioThread(); | 953 StopAndCloseAudioInputStreamOnAudioThread(); |
955 } | 954 } |
956 | 955 |
957 INSTANTIATE_TEST_CASE_P(AudioAndroidInputTest, AudioAndroidInputTest, | 956 INSTANTIATE_TEST_CASE_P(AudioAndroidInputTest, AudioAndroidInputTest, |
958 testing::ValuesIn(RunAudioRecordInputPathTests())); | 957 testing::ValuesIn(RunAudioRecordInputPathTests())); |
959 | 958 |
960 } // namespace media | 959 } // namespace media |
OLD | NEW |