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" |
(...skipping 17 matching lines...) Expand all Loading... |
28 << "channels per frame: " << format.mChannelsPerFrame << std::endl | 28 << "channels per frame: " << format.mChannelsPerFrame << std::endl |
29 << "bits per channel : " << format.mBitsPerChannel; | 29 << "bits per channel : " << format.mBitsPerChannel; |
30 return os; | 30 return os; |
31 } | 31 } |
32 | 32 |
33 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" | 33 // See "Technical Note TN2091 - Device input using the HAL Output Audio Unit" |
34 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html | 34 // http://developer.apple.com/library/mac/#technotes/tn2091/_index.html |
35 // for more details and background regarding this implementation. | 35 // for more details and background regarding this implementation. |
36 | 36 |
37 AUAudioInputStream::AUAudioInputStream( | 37 AUAudioInputStream::AUAudioInputStream( |
38 AudioManagerMac* manager, const AudioParameters& params, | 38 AudioManagerMac* manager, |
| 39 const AudioParameters& input_params, |
| 40 const AudioParameters& output_params, |
39 AudioDeviceID audio_device_id) | 41 AudioDeviceID audio_device_id) |
40 : manager_(manager), | 42 : manager_(manager), |
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 fifo_delay_bytes_(0), | 48 fifo_delay_bytes_(0), |
47 number_of_channels_in_frame_(0) { | 49 number_of_channels_in_frame_(0) { |
48 DCHECK(manager_); | 50 DCHECK(manager_); |
49 | 51 |
50 // Set up the desired (output) format specified by the client. | 52 // Set up the desired (output) format specified by the client. |
51 format_.mSampleRate = params.sample_rate(); | 53 format_.mSampleRate = input_params.sample_rate(); |
52 format_.mFormatID = kAudioFormatLinearPCM; | 54 format_.mFormatID = kAudioFormatLinearPCM; |
53 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | | 55 format_.mFormatFlags = kLinearPCMFormatFlagIsPacked | |
54 kLinearPCMFormatFlagIsSignedInteger; | 56 kLinearPCMFormatFlagIsSignedInteger; |
55 format_.mBitsPerChannel = params.bits_per_sample(); | 57 format_.mBitsPerChannel = input_params.bits_per_sample(); |
56 format_.mChannelsPerFrame = params.channels(); | 58 format_.mChannelsPerFrame = input_params.channels(); |
57 format_.mFramesPerPacket = 1; // uncompressed audio | 59 format_.mFramesPerPacket = 1; // uncompressed audio |
58 format_.mBytesPerPacket = (format_.mBitsPerChannel * | 60 format_.mBytesPerPacket = (format_.mBitsPerChannel * |
59 params.channels()) / 8; | 61 input_params.channels()) / 8; |
60 format_.mBytesPerFrame = format_.mBytesPerPacket; | 62 format_.mBytesPerFrame = format_.mBytesPerPacket; |
61 format_.mReserved = 0; | 63 format_.mReserved = 0; |
62 | 64 |
63 DVLOG(1) << "Desired ouput format: " << format_; | 65 DVLOG(1) << "Desired ouput format: " << format_; |
64 | 66 |
65 // Set number of sample frames per callback used by the internal audio layer. | 67 // Set number of sample frames per callback used by the internal audio layer. |
66 // An internal FIFO is then utilized to adapt the internal size to the size | 68 // An internal FIFO is then utilized to adapt the internal size to the size |
67 // requested by the client. | 69 // requested by the client. |
68 // Note that we use the same native buffer size as for the output side here | 70 // Note that we use the same native buffer size as for the output side here |
69 // since the AUHAL implementation requires that both capture and render side | 71 // since the AUHAL implementation requires that both capture and render side |
70 // use the same buffer size. See http://crbug.com/154352 for more details. | 72 // use the same buffer size. See http://crbug.com/154352 for more details. |
71 // TODO(xians): Get the audio parameters from the right device. | 73 number_of_frames_ = output_params.frames_per_buffer(); |
72 const AudioParameters parameters = | |
73 manager_->GetInputStreamParameters(AudioManagerBase::kDefaultDeviceId); | |
74 number_of_frames_ = parameters.frames_per_buffer(); | |
75 DVLOG(1) << "Size of data buffer in frames : " << number_of_frames_; | 74 DVLOG(1) << "Size of data buffer in frames : " << number_of_frames_; |
76 | 75 |
77 // Derive size (in bytes) of the buffers that we will render to. | 76 // Derive size (in bytes) of the buffers that we will render to. |
78 UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame; | 77 UInt32 data_byte_size = number_of_frames_ * format_.mBytesPerFrame; |
79 DVLOG(1) << "Size of data buffer in bytes : " << data_byte_size; | 78 DVLOG(1) << "Size of data buffer in bytes : " << data_byte_size; |
80 | 79 |
81 // Allocate AudioBuffers to be used as storage for the received audio. | 80 // Allocate AudioBuffers to be used as storage for the received audio. |
82 // The AudioBufferList structure works as a placeholder for the | 81 // The AudioBufferList structure works as a placeholder for the |
83 // AudioBuffer structure, which holds a pointer to the actual data buffer. | 82 // AudioBuffer structure, which holds a pointer to the actual data buffer. |
84 audio_data_buffer_.reset(new uint8[data_byte_size]); | 83 audio_data_buffer_.reset(new uint8[data_byte_size]); |
85 audio_buffer_list_.mNumberBuffers = 1; | 84 audio_buffer_list_.mNumberBuffers = 1; |
86 | 85 |
87 AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers; | 86 AudioBuffer* audio_buffer = audio_buffer_list_.mBuffers; |
88 audio_buffer->mNumberChannels = params.channels(); | 87 audio_buffer->mNumberChannels = input_params.channels(); |
89 audio_buffer->mDataByteSize = data_byte_size; | 88 audio_buffer->mDataByteSize = data_byte_size; |
90 audio_buffer->mData = audio_data_buffer_.get(); | 89 audio_buffer->mData = audio_data_buffer_.get(); |
91 | 90 |
92 // Set up an internal FIFO buffer that will accumulate recorded audio frames | 91 // Set up an internal FIFO buffer that will accumulate recorded audio frames |
93 // until a requested size is ready to be sent to the client. | 92 // until a requested size is ready to be sent to the client. |
94 // It is not possible to ask for less than |kAudioFramesPerCallback| number of | 93 // It is not possible to ask for less than |kAudioFramesPerCallback| number of |
95 // audio frames. | 94 // audio frames. |
96 const size_t requested_size_frames = | 95 size_t requested_size_frames = |
97 params.GetBytesPerBuffer() / format_.mBytesPerPacket; | 96 input_params.GetBytesPerBuffer() / format_.mBytesPerPacket; |
98 DCHECK_GE(requested_size_frames, number_of_frames_); | 97 if (requested_size_frames < number_of_frames_) { |
| 98 // For devices that only support a low sample rate like 8kHz, we adjust the |
| 99 // buffer size to match number_of_frames_. The value of number_of_frames_ |
| 100 // in this case has not been calculated based on hardware settings but |
| 101 // rather our hardcoded defaults (see ChooseBufferSize). |
| 102 requested_size_frames = number_of_frames_; |
| 103 } |
| 104 |
99 requested_size_bytes_ = requested_size_frames * format_.mBytesPerFrame; | 105 requested_size_bytes_ = requested_size_frames * format_.mBytesPerFrame; |
100 DVLOG(1) << "Requested buffer size in bytes : " << requested_size_bytes_; | 106 DVLOG(1) << "Requested buffer size in bytes : " << requested_size_bytes_; |
101 DLOG_IF(INFO, requested_size_frames > number_of_frames_) << "FIFO is used"; | 107 DLOG_IF(INFO, requested_size_frames > number_of_frames_) << "FIFO is used"; |
102 | 108 |
103 const int number_of_bytes = number_of_frames_ * format_.mBytesPerFrame; | 109 const int number_of_bytes = number_of_frames_ * format_.mBytesPerFrame; |
104 fifo_delay_bytes_ = requested_size_bytes_ - number_of_bytes; | 110 fifo_delay_bytes_ = requested_size_bytes_ - number_of_bytes; |
105 | 111 |
106 // Allocate some extra memory to avoid memory reallocations. | 112 // Allocate some extra memory to avoid memory reallocations. |
107 // Ensure that the size is an even multiple of |number_of_frames_ and | 113 // Ensure that the size is an even multiple of |number_of_frames_ and |
108 // larger than |requested_size_frames|. | 114 // larger than |requested_size_frames|. |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 kAudioDevicePropertyScopeInput, | 661 kAudioDevicePropertyScopeInput, |
656 static_cast<UInt32>(channel) | 662 static_cast<UInt32>(channel) |
657 }; | 663 }; |
658 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, | 664 OSStatus result = AudioObjectIsPropertySettable(input_device_id_, |
659 &property_address, | 665 &property_address, |
660 &is_settable); | 666 &is_settable); |
661 return (result == noErr) ? is_settable : false; | 667 return (result == noErr) ? is_settable : false; |
662 } | 668 } |
663 | 669 |
664 } // namespace media | 670 } // namespace media |
OLD | NEW |