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/mac/audio_low_latency_input_mac.h" | 5 #include "media/audio/mac/audio_low_latency_input_mac.h" |
6 | 6 |
7 #include <CoreServices/CoreServices.h> | 7 #include <CoreServices/CoreServices.h> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/mac/mac_logging.h" | 11 #include "base/mac/mac_logging.h" |
12 #include "media/audio/mac/audio_manager_mac.h" | 12 #include "media/audio/mac/audio_manager_mac.h" |
13 #include "media/base/audio_bus.h" | 13 #include "media/base/audio_bus.h" |
14 #include "media/base/audio_fifo.h" | |
15 #include "media/base/data_buffer.h" | 14 #include "media/base/data_buffer.h" |
16 | 15 |
17 namespace media { | 16 namespace media { |
18 | 17 |
| 18 // Number of blocks of buffers used in the |fifo_|. |
| 19 const int kNumberOfBlocksBufferInFifo = 2; |
| 20 |
19 static std::ostream& operator<<(std::ostream& os, | 21 static std::ostream& operator<<(std::ostream& os, |
20 const AudioStreamBasicDescription& format) { | 22 const AudioStreamBasicDescription& format) { |
21 os << "sample rate : " << format.mSampleRate << std::endl | 23 os << "sample rate : " << format.mSampleRate << std::endl |
22 << "format ID : " << format.mFormatID << std::endl | 24 << "format ID : " << format.mFormatID << std::endl |
23 << "format flags : " << format.mFormatFlags << std::endl | 25 << "format flags : " << format.mFormatFlags << std::endl |
24 << "bytes per packet : " << format.mBytesPerPacket << std::endl | 26 << "bytes per packet : " << format.mBytesPerPacket << std::endl |
25 << "frames per packet : " << format.mFramesPerPacket << std::endl | 27 << "frames per packet : " << format.mFramesPerPacket << std::endl |
26 << "bytes per frame : " << format.mBytesPerFrame << std::endl | 28 << "bytes per frame : " << format.mBytesPerFrame << std::endl |
27 << "channels per frame: " << format.mChannelsPerFrame << std::endl | 29 << "channels per frame: " << format.mChannelsPerFrame << std::endl |
28 << "bits per channel : " << format.mBitsPerChannel; | 30 << "bits per channel : " << format.mBitsPerChannel; |
29 return os; | 31 return os; |
30 } | 32 } |
31 | 33 |
32 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" | 34 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" |
33 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html | 35 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html |
34 // for more details and background regarding this implementation. | 36 // for more details and background regarding this implementation. |
35 | 37 |
36 AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager, | 38 AUAudioInputStream::AUAudioInputStream(AudioManagerMac* manager, |
37 const AudioParameters& input_params, | 39 const AudioParameters& input_params, |
38 AudioDeviceID audio_device_id) | 40 AudioDeviceID audio_device_id) |
39 : manager_(manager), | 41 : manager_(manager), |
40 number_of_frames_(input_params.frames_per_buffer()), | 42 number_of_frames_(input_params.frames_per_buffer()), |
41 sink_(NULL), | 43 sink_(NULL), |
42 audio_unit_(0), | 44 audio_unit_(0), |
43 input_device_id_(audio_device_id), | 45 input_device_id_(audio_device_id), |
44 started_(false), | 46 started_(false), |
45 hardware_latency_frames_(0), | 47 hardware_latency_frames_(0), |
46 number_of_channels_in_frame_(0), | 48 number_of_channels_in_frame_(0), |
47 audio_bus_(media::AudioBus::Create(input_params)), | 49 fifo_(input_params.channels(), |
48 audio_wrapper_(media::AudioBus::Create(input_params)) { | 50 number_of_frames_, |
| 51 kNumberOfBlocksBufferInFifo) { |
49 DCHECK(manager_); | 52 DCHECK(manager_); |
50 | 53 |
51 // Set up the desired (output) format specified by the client. | 54 // Set up the desired (output) format specified by the client. |
52 format_.mSampleRate = input_params.sample_rate(); | 55 format_.mSampleRate = input_params.sample_rate(); |
53 format_.mFormatID = kAudioFormatLinearPCM; | 56 format_.mFormatID = kAudioFormatLinearPCM; |
54 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | | 57 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | |
55 kLinearPCMFormatFlagIsSignedInteger; | 58 kLinearPCMFormatFlagIsSignedInteger; |
56 format_.mBitsPerChannel = input_params.bits_per_sample(); | 59 format_.mBitsPerChannel = input_params.bits_per_sample(); |
57 format_.mChannelsPerFrame = input_params.channels(); | 60 format_.mChannelsPerFrame = input_params.channels(); |
58 format_.mFramesPerPacket = 1; // uncompressed audio | 61 format_.mFramesPerPacket = 1; // uncompressed audio |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 GetAgcVolume(&normalized_volume); | 490 GetAgcVolume(&normalized_volume); |
488 | 491 |
489 AudioBuffer& buffer = io_data->mBuffers[0]; | 492 AudioBuffer& buffer = io_data->mBuffers[0]; |
490 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); | 493 uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); |
491 uint32 capture_delay_bytes = static_cast<uint32> | 494 uint32 capture_delay_bytes = static_cast<uint32> |
492 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); | 495 ((capture_latency_frames + 0.5) * format_.mBytesPerFrame); |
493 DCHECK(audio_data); | 496 DCHECK(audio_data); |
494 if (!audio_data) | 497 if (!audio_data) |
495 return kAudioUnitErr_InvalidElement; | 498 return kAudioUnitErr_InvalidElement; |
496 | 499 |
497 if (number_of_frames != number_of_frames_) { | 500 // Copy captured (and interleaved) data into FIFO. |
498 // Create a FIFO on the fly to handle any discrepancies in callback rates. | 501 fifo_.Push(audio_data, number_of_frames, format_.mBitsPerChannel / 8); |
499 if (!fifo_) { | |
500 VLOG(1) << "Audio frame size changed from " << number_of_frames_ << " to " | |
501 << number_of_frames << "; adding FIFO to compensate."; | |
502 fifo_.reset(new AudioFifo( | |
503 format_.mChannelsPerFrame, number_of_frames_ + number_of_frames)); | |
504 } | |
505 | 502 |
506 if (audio_wrapper_->frames() != static_cast<int>(number_of_frames)) { | 503 // Consume and deliver the data when the FIFO has a block of available data. |
507 audio_wrapper_ = media::AudioBus::Create(format_.mChannelsPerFrame, | 504 while (fifo_.available_blocks()) { |
508 number_of_frames); | 505 const AudioBus* audio_bus = fifo_.Consume(); |
509 } | 506 DCHECK_EQ(audio_bus->frames(), static_cast<int>(number_of_frames_)); |
510 } | |
511 | 507 |
512 // Copy captured (and interleaved) data into deinterleaved audio bus. | 508 // Compensate the audio delay caused by the FIFO. |
513 audio_wrapper_->FromInterleaved( | 509 capture_delay_bytes += fifo_.GetAvailableFrames() * format_.mBytesPerFrame; |
514 audio_data, audio_wrapper_->frames(), format_.mBitsPerChannel / 8); | 510 sink_->OnData(this, audio_bus, capture_delay_bytes, normalized_volume); |
515 | |
516 // When FIFO does not kick in, data will be directly passed to the callback. | |
517 if (!fifo_) { | |
518 CHECK_EQ(audio_wrapper_->frames(), static_cast<int>(number_of_frames_)); | |
519 sink_->OnData( | |
520 this, audio_wrapper_.get(), capture_delay_bytes, normalized_volume); | |
521 return noErr; | |
522 } | |
523 | |
524 // Compensate the audio delay caused by the FIFO. | |
525 capture_delay_bytes += fifo_->frames() * format_.mBytesPerFrame; | |
526 fifo_->Push(audio_wrapper_.get()); | |
527 if (fifo_->frames() >= static_cast<int>(number_of_frames_)) { | |
528 // Consume the audio from the FIFO. | |
529 fifo_->Consume(audio_bus_.get(), 0, audio_bus_->frames()); | |
530 DCHECK(fifo_->frames() < static_cast<int>(number_of_frames_)); | |
531 | |
532 sink_->OnData( | |
533 this, audio_bus_.get(), capture_delay_bytes, normalized_volume); | |
534 } | 511 } |
535 | 512 |
536 return noErr; | 513 return noErr; |
537 } | 514 } |
538 | 515 |
539 int AUAudioInputStream::HardwareSampleRate() { | 516 int AUAudioInputStream::HardwareSampleRate() { |
540 // Determine the default input device's sample-rate. | 517 // Determine the default input device's sample-rate. |
541 AudioDeviceID device_id = kAudioObjectUnknown; | 518 AudioDeviceID device_id = kAudioObjectUnknown; |
542 UInt32 info_size = sizeof(device_id); | 519 UInt32 info_size = sizeof(device_id); |
543 | 520 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 kAudioDevicePropertyScopeInput, | 642 kAudioDevicePropertyScopeInput, |
666 static_cast<UInt32>(channel) | 643 static_cast<UInt32>(channel) |
667 }; | 644 }; |
668 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, | 645 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, |
669 &property_address, | 646 &property_address, |
670 &is_settable); | 647 &is_settable); |
671 return (result == noErr) ? is_settable : false; | 648 return (result == noErr) ? is_settable : false; |
672 } | 649 } |
673 | 650 |
674 } // namespace media | 651 } // namespace media |
OLD | NEW |