Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(390)

Side by Side Diff: webrtc/modules/audio_device/ios/audio_device_ios.h

Issue 1254883002: Refactor the AudioDevice for iOS and improve the performance and stability (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Extended unit test for FineAudioBuffer with recorded data Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_IOS_H 11 #ifndef WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_
12 #define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_IOS_H 12 #define WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_
13 13
14 #include <AudioUnit/AudioUnit.h> 14 #include <AudioUnit/AudioUnit.h>
15 15
16 #include "webrtc/base/scoped_ptr.h"
16 #include "webrtc/base/thread_checker.h" 17 #include "webrtc/base/thread_checker.h"
17 #include "webrtc/modules/audio_device/audio_device_generic.h" 18 #include "webrtc/modules/audio_device/audio_device_generic.h"
18 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
19 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
20 19
21 namespace webrtc { 20 namespace webrtc {
22 const uint32_t N_REC_SAMPLES_PER_SEC = 44100;
23 const uint32_t N_PLAY_SAMPLES_PER_SEC = 44100;
24 21
25 const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES = (N_REC_SAMPLES_PER_SEC / 100); 22 class FineAudioBuffer;
26 const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES = (N_PLAY_SAMPLES_PER_SEC / 100);
27 23
28 // Number of 10 ms recording blocks in recording buffer 24 // Implements full duplex 16-bit mono PCM audio support for iOS using a
29 const uint16_t N_REC_BUFFERS = 20; 25 // Voice-Processing (VP) I/O audio unit in Core Audio. The VP I/O audio unit
30 26 // supports audio echo cancellation. It also adds automatic gain control,
27 // adjustment of voice-processing quality and muting.
28 //
29 // An instance must be created and destroyed on one and the same thread.
30 // All supported public methods must also be called on the same thread.
31 // A thread checker will DCHECK if any supported method is called on an invalid
32 // thread.
33 //
34 // Recorded audio will be delivered on a real-time internal I/O thread in the
35 // audio unit. The audio unit will also ask for audio data to play out on this
36 // same thread.
31 class AudioDeviceIOS : public AudioDeviceGeneric { 37 class AudioDeviceIOS : public AudioDeviceGeneric {
32 public: 38 public:
33 AudioDeviceIOS(); 39 AudioDeviceIOS();
34 ~AudioDeviceIOS(); 40 ~AudioDeviceIOS();
35 41
36 void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override; 42 void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
37 43
38 int32_t Init() override; 44 int32_t Init() override;
39 int32_t Terminate() override; 45 int32_t Terminate() override;
40 bool Initialized() const override { return _initialized; } 46 bool Initialized() const override { return _initialized; }
41 47
42 int32_t InitPlayout() override; 48 int32_t InitPlayout() override;
43 bool PlayoutIsInitialized() const override { return _playIsInitialized; } 49 bool PlayoutIsInitialized() const override { return _playIsInitialized; }
44 50
45 int32_t InitRecording() override; 51 int32_t InitRecording() override;
46 bool RecordingIsInitialized() const override { return _recIsInitialized; } 52 bool RecordingIsInitialized() const override { return _recIsInitialized; }
47 53
48 int32_t StartPlayout() override; 54 int32_t StartPlayout() override;
49 int32_t StopPlayout() override; 55 int32_t StopPlayout() override;
50 bool Playing() const override { return _playing; } 56 bool Playing() const override { return _playing; }
51 57
52 int32_t StartRecording() override; 58 int32_t StartRecording() override;
53 int32_t StopRecording() override; 59 int32_t StopRecording() override;
54 bool Recording() const override { return _recording; } 60 bool Recording() const override { return _recording; }
55 61
56 int32_t SetLoudspeakerStatus(bool enable) override; 62 int32_t SetLoudspeakerStatus(bool enable) override;
57 int32_t GetLoudspeakerStatus(bool& enabled) const override; 63 int32_t GetLoudspeakerStatus(bool& enabled) const override;
58 64
59 // TODO(henrika): investigate if we can reduce the complexity here. 65 // Currently using hard-coded delay values and not dynamic delay estimates.
60 // Do we even need delay estimates? 66 // Given that a built-in AEC is available on iOS, it saves resources to
67 // return fixed (reasonable) values here instead. Any AEC in WebRTC will then
tkchin_webrtc 2015/09/01 20:54:50 ooc, what happens if two aec passes occur? Does it
henrika_webrtc 2015/09/03 13:44:41 Extended the comments. Today we always disable all
68 // work as well.
61 int32_t PlayoutDelay(uint16_t& delayMS) const override; 69 int32_t PlayoutDelay(uint16_t& delayMS) const override;
62 int32_t RecordingDelay(uint16_t& delayMS) const override; 70 int32_t RecordingDelay(uint16_t& delayMS) const override;
63 71
64 int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type, 72 // Native audio parameters stored during construction.
65 uint16_t& sizeMS) const override;
66
67 // These methods are unique for the iOS implementation. 73 // These methods are unique for the iOS implementation.
68
69 // Native audio parameters stored during construction.
70 int GetPlayoutAudioParameters(AudioParameters* params) const override; 74 int GetPlayoutAudioParameters(AudioParameters* params) const override;
71 int GetRecordAudioParameters(AudioParameters* params) const override; 75 int GetRecordAudioParameters(AudioParameters* params) const override;
72 76
73 // These methods are currently not implemented on iOS. 77 // These methods are currently not fully implemented on iOS:
74 // See audio_device_not_implemented_ios.mm for dummy implementations.
75 78
79 // See audio_device_not_implemented.cc for trivial implementations.
80 int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type,
81 uint16_t& sizeMS) const override;
76 int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const; 82 int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const;
77 int32_t ResetAudioDevice() override; 83 int32_t ResetAudioDevice() override;
78 int32_t PlayoutIsAvailable(bool& available) override; 84 int32_t PlayoutIsAvailable(bool& available) override;
79 int32_t RecordingIsAvailable(bool& available) override; 85 int32_t RecordingIsAvailable(bool& available) override;
80 int32_t SetAGC(bool enable) override; 86 int32_t SetAGC(bool enable) override;
81 bool AGC() const override; 87 bool AGC() const override;
82 int16_t PlayoutDevices() override; 88 int16_t PlayoutDevices() override;
83 int16_t RecordingDevices() override; 89 int16_t RecordingDevices() override;
84 int32_t PlayoutDeviceName(uint16_t index, 90 int32_t PlayoutDeviceName(uint16_t index,
85 char name[kAdmMaxDeviceNameSize], 91 char name[kAdmMaxDeviceNameSize],
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 bool PlayoutWarning() const override; 139 bool PlayoutWarning() const override;
134 bool PlayoutError() const override; 140 bool PlayoutError() const override;
135 bool RecordingWarning() const override; 141 bool RecordingWarning() const override;
136 bool RecordingError() const override; 142 bool RecordingError() const override;
137 void ClearPlayoutWarning() override{}; 143 void ClearPlayoutWarning() override{};
138 void ClearPlayoutError() override{}; 144 void ClearPlayoutError() override{};
139 void ClearRecordingWarning() override{}; 145 void ClearRecordingWarning() override{};
140 void ClearRecordingError() override{}; 146 void ClearRecordingError() override{};
141 147
142 private: 148 private:
143 // TODO(henrika): try to remove these. 149 // Uses current |_playoutParameters| and |_recordParameters| to inform the
144 void Lock() { 150 // audio device buffer (ADB) about our internal audio parameters.
145 _critSect.Enter(); 151 void UpdateAudioDeviceBuffer();
146 }
147 152
148 void UnLock() { 153 // Since the preferred audio parameters are only hints to the OS, the actual
149 _critSect.Leave(); 154 // values may be different once the AVAudioSession has been activated.
150 } 155 // This method asks for the current hardware parameters and takes actions
156 // if they should differ from what we have asked for initially.
157 void VerifyAudioParametersForActiveAudioSession();
151 158
152 // Init and shutdown 159 // Creates a Voice-Processing I/O unit and configures it for full-duplex
153 int32_t InitPlayOrRecord(); 160 // audio. The selected stream format is selected to avoid internal resampling
154 int32_t ShutdownPlayOrRecord(); 161 // and to match the 10ms callback rate for WebRTC as well as possible.
162 // This method also initializes the created audio unit.
163 void SetupAndInitializeVoiceProcessingAudioUnit();
155 164
156 void UpdateRecordingDelay(); 165 // Activates our audio session, creates and initilizes the voice-processing
157 void UpdatePlayoutDelay(); 166 // audio unit and verifies that we got the preferred native audio parameters.
167 bool InitPlayOrRecord();
158 168
159 static OSStatus RecordProcess(void *inRefCon, 169 // Closes and deletes the voice-processing I/O unit.
160 AudioUnitRenderActionFlags *ioActionFlags, 170 bool ShutdownPlayOrRecord();
161 const AudioTimeStamp *timeStamp,
162 UInt32 inBusNumber,
163 UInt32 inNumberFrames,
164 AudioBufferList *ioData);
165 171
166 static OSStatus PlayoutProcess(void *inRefCon, 172 // Callback function called on a real-time priority I/O thread from the audio
167 AudioUnitRenderActionFlags *ioActionFlags, 173 // unit. This method is used to signal that recorded audio is available.
168 const AudioTimeStamp *timeStamp, 174 static OSStatus RecordedDataIsAvailable(
tkchin_webrtc 2015/09/01 20:54:50 nit: Style guide is to use C++ syntax/style in C++
henrika_webrtc 2015/09/03 13:44:41 ooh nooo, I was not sure if one could use objc not
tkchin_webrtc 2015/09/04 05:29:16 I'm ok with changing old stuff separately not part
henrika_webrtc 2015/09/04 09:51:18 Agree. And thanks for letting me do this in a sepa
175 void* inRefCon,
176 AudioUnitRenderActionFlags* ioActionFlags,
177 const AudioTimeStamp* timeStamp,
178 UInt32 inBusNumber,
179 UInt32 inNumberFrames,
180 AudioBufferList* ioData);
181 OSStatus OnRecordedDataIsAvailable(AudioUnitRenderActionFlags* ioActionFlags,
182 const AudioTimeStamp* timeStamp,
183 UInt32 inBusNumber,
184 UInt32 inNumberFrames);
185
186 // Callback function called on a real-time priority I/O thread from the audio
187 // unit. This method is used to provide audio samples to the audio unit.
188 static OSStatus GetPlayoutData(void* inRefCon,
189 AudioUnitRenderActionFlags* ioActionFlags,
190 const AudioTimeStamp* timeStamp,
169 UInt32 inBusNumber, 191 UInt32 inBusNumber,
170 UInt32 inNumberFrames, 192 UInt32 inNumberFrames,
171 AudioBufferList *ioData); 193 AudioBufferList* ioData);
172 194 OSStatus OnGetPlayoutData(AudioUnitRenderActionFlags* ioActionFlags,
173 OSStatus RecordProcessImpl(AudioUnitRenderActionFlags *ioActionFlags, 195 UInt32 inNumberFrames,
174 const AudioTimeStamp *timeStamp, 196 AudioBufferList* ioData);
175 uint32_t inBusNumber,
176 uint32_t inNumberFrames);
177
178 OSStatus PlayoutProcessImpl(uint32_t inNumberFrames,
179 AudioBufferList *ioData);
180
181 static bool RunCapture(void* ptrThis);
182 bool CaptureWorkerThread();
183 197
184 private: 198 private:
185 rtc::ThreadChecker thread_checker_; 199 // Ensures that methods are called from the same thread as this object is
200 // created on.
201 rtc::ThreadChecker _threadChecker;
tkchin_webrtc 2015/09/01 20:54:50 nit: Style guide is to use C++ syntax/style in C++
henrika_webrtc 2015/09/03 13:44:41 Acknowledged.
186 202
187 // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the 203 // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the
188 // AudioDeviceModuleImpl class and called by AudioDeviceModuleImpl::Create(). 204 // AudioDeviceModuleImpl class and called by AudioDeviceModuleImpl::Create().
189 // The AudioDeviceBuffer is a member of the AudioDeviceModuleImpl instance 205 // The AudioDeviceBuffer is a member of the AudioDeviceModuleImpl instance
190 // and therefore outlives this object. 206 // and therefore outlives this object.
191 AudioDeviceBuffer* audio_device_buffer_; 207 AudioDeviceBuffer* _audioDeviceBuffer;
192 208
193 CriticalSectionWrapper& _critSect; 209 // Contains audio parameters (sample rate, #channels, buffer size etc.) for
210 // the playout and recording sides. These structure is set in two steps:
211 // first, native sample rate and #channels are defined in Init(). Next, the
212 // audio session is activated and we verify that the preferred parameters
213 // were granted by the OS. At this stage it is also possible to add a third
214 // component to the parameters; the native I/O buffer duration.
215 // A CHECK will be hit if we for some reason fail to open an audio session
216 // using the specified parameters.
217 AudioParameters _playoutParameters;
218 AudioParameters _recordParameters;
194 219
195 AudioParameters playout_parameters_; 220 // The Voice-Processing I/O unit has the same characteristics as the
196 AudioParameters record_parameters_; 221 // Remote I/O unit (supports full duplex low-latency audio input and output)
222 // and adds AEC for for two-way duplex communication. It also adds AGC,
223 // adjustment of voice-processing quality, and muting. Hence, ideal for
224 // VoIP applications.
225 AudioUnit _vpioUnit;
197 226
198 rtc::scoped_ptr<ThreadWrapper> _captureWorkerThread; 227 // FineAudioBuffer takes an AudioDeviceBuffer which delivers audio data
228 // in chunks of 10ms. It then allows for this data to be pulled in
229 // a finer or coarser granularity. I.e. interacting with this class instead
230 // of directly with the AudioDeviceBuffer one can ask for any number of
231 // audio data samples.
232 // Example: native buffer size can be 128 audio frames at 16kHz sample rate.
233 // WebRTC will provide 480 audio frames per 10ms but iOS asks for 128
234 // in each callback (one every 8ms). This class can then ask for 128 and the
235 // FineAudioBuffer will ask WebRTC for new data only when needed and also
236 // cach non-utilized audio between callbacks.
tkchin_webrtc 2015/09/01 20:54:50 Thanks for this comment - it was helpful.
tkchin_webrtc 2015/09/01 20:54:50 nit: cache non-utilized
henrika_webrtc 2015/09/03 13:44:41 Done.
henrika_webrtc 2015/09/03 13:44:41 Thanks. Added comments for the recording side as w
237 rtc::scoped_ptr<FineAudioBuffer> _fineAudioBuffer;
199 238
200 AudioUnit _auVoiceProcessing; 239 // Extra audio buffer to be used by the playout side for rendering audio.
201 void* _audioInterruptionObserver; 240 // The buffer size is given by FineAudioBuffer::RequiredBufferSizeBytes().
241 rtc::scoped_ptr<SInt8[]> _playoutAudioBuffer;
202 242
243 // Provides a mechanism for encapsulating one or more buffers of audio data.
244 // Only used on the recording side.
245 AudioBufferList _audioRecordBufferList;
246
247 // Temporary storage for recorded data. AudioUnitRender() renders into this
248 // array as soon as a frame of the desired buffer size has been recorded.
249 rtc::scoped_ptr<SInt8[]> _recordAudioBuffer;
250
251 // Set to 1 when recording is active and 0 otherwise.
252 volatile int _recording;
253
254 // Set to 1 when playout is active and 0 otherwise.
255 volatile int _playing;
256
257 // Set to true after successful call to Init(), false otherwise.
203 bool _initialized; 258 bool _initialized;
204 bool _isShutDown; 259
205 bool _recording; 260 // Set to true after successful call to InitRecording(), false otherwise.
206 bool _playing;
207 bool _recIsInitialized; 261 bool _recIsInitialized;
262
263 // Set to true after successful call to InitPlayout(), false otherwise.
208 bool _playIsInitialized; 264 bool _playIsInitialized;
209 265
210 // The sampling rate to use with Audio Device Buffer 266 // Audio interruption observer instance.
211 int _adbSampFreq; 267 void* _audioInterruptionObserver;
212
213 // Delay calculation
214 uint32_t _recordingDelay;
215 uint32_t _playoutDelay;
216 uint32_t _playoutDelayMeasurementCounter;
217 uint32_t _recordingDelayHWAndOS;
218 uint32_t _recordingDelayMeasurementCounter;
219
220 // Playout buffer, needed for 44.0 / 44.1 kHz mismatch
221 int16_t _playoutBuffer[ENGINE_PLAY_BUF_SIZE_IN_SAMPLES];
222 uint32_t _playoutBufferUsed; // How much is filled
223
224 // Recording buffers
225 int16_t _recordingBuffer[N_REC_BUFFERS][ENGINE_REC_BUF_SIZE_IN_SAMPLES];
226 uint32_t _recordingLength[N_REC_BUFFERS];
227 uint32_t _recordingSeqNumber[N_REC_BUFFERS];
228 uint32_t _recordingCurrentSeq;
229
230 // Current total size all data in buffers, used for delay estimate
231 uint32_t _recordingBufferTotalSize;
232 }; 268 };
233 269
234 } // namespace webrtc 270 } // namespace webrtc
235 271
236 #endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_IOS_H 272 #endif // WEBRTC_MODULES_AUDIO_DEVICE_IOS_AUDIO_DEVICE_IOS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698