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

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

Issue 1335923002: Add RTC_ prefix to (D)CHECKs and related macros. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase. 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
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 // take care of any buffering required to convert between native buffers and 48 // take care of any buffering required to convert between native buffers and
49 // buffers used by WebRTC. It is beneficial for the performance if the native 49 // buffers used by WebRTC. It is beneficial for the performance if the native
50 // size is as close to 10ms as possible since it results in "clean" callback 50 // size is as close to 10ms as possible since it results in "clean" callback
51 // sequence without bursts of callbacks back to back. 51 // sequence without bursts of callbacks back to back.
52 const double kPreferredIOBufferDuration = 0.01; 52 const double kPreferredIOBufferDuration = 0.01;
53 // Try to use mono to save resources. Also avoids channel format conversion 53 // Try to use mono to save resources. Also avoids channel format conversion
54 // in the I/O audio unit. Initial tests have shown that it is possible to use 54 // in the I/O audio unit. Initial tests have shown that it is possible to use
55 // mono natively for built-in microphones and for BT headsets but not for 55 // mono natively for built-in microphones and for BT headsets but not for
56 // wired headsets. Wired headsets only support stereo as native channel format 56 // wired headsets. Wired headsets only support stereo as native channel format
57 // but it is a low cost operation to do a format conversion to mono in the 57 // but it is a low cost operation to do a format conversion to mono in the
58 // audio unit. Hence, we will not hit a CHECK in 58 // audio unit. Hence, we will not hit a RTC_CHECK in
59 // VerifyAudioParametersForActiveAudioSession() for a mismatch between the 59 // VerifyAudioParametersForActiveAudioSession() for a mismatch between the
60 // preferred number of channels and the actual number of channels. 60 // preferred number of channels and the actual number of channels.
61 const int kPreferredNumberOfChannels = 1; 61 const int kPreferredNumberOfChannels = 1;
62 // Number of bytes per audio sample for 16-bit signed integer representation. 62 // Number of bytes per audio sample for 16-bit signed integer representation.
63 const UInt32 kBytesPerSample = 2; 63 const UInt32 kBytesPerSample = 2;
64 // Hardcoded delay estimates based on real measurements. 64 // Hardcoded delay estimates based on real measurements.
65 // TODO(henrika): these value is not used in combination with built-in AEC. 65 // TODO(henrika): these value is not used in combination with built-in AEC.
66 // Can most likely be removed. 66 // Can most likely be removed.
67 const UInt16 kFixedPlayoutDelayEstimate = 30; 67 const UInt16 kFixedPlayoutDelayEstimate = 30;
68 const UInt16 kFixedRecordDelayEstimate = 30; 68 const UInt16 kFixedRecordDelayEstimate = 30;
69 69
70 using ios::CheckAndLogError; 70 using ios::CheckAndLogError;
71 71
72 // Activates an audio session suitable for full duplex VoIP sessions when 72 // Activates an audio session suitable for full duplex VoIP sessions when
73 // |activate| is true. Also sets the preferred sample rate and IO buffer 73 // |activate| is true. Also sets the preferred sample rate and IO buffer
74 // duration. Deactivates an active audio session if |activate| is set to false. 74 // duration. Deactivates an active audio session if |activate| is set to false.
75 static void ActivateAudioSession(AVAudioSession* session, bool activate) { 75 static void ActivateAudioSession(AVAudioSession* session, bool activate) {
76 LOG(LS_INFO) << "ActivateAudioSession(" << activate << ")"; 76 LOG(LS_INFO) << "ActivateAudioSession(" << activate << ")";
77 @autoreleasepool { 77 @autoreleasepool {
78 NSError* error = nil; 78 NSError* error = nil;
79 BOOL success = NO; 79 BOOL success = NO;
80 // Deactivate the audio session and return if |activate| is false. 80 // Deactivate the audio session and return if |activate| is false.
81 if (!activate) { 81 if (!activate) {
82 success = [session setActive:NO error:&error]; 82 success = [session setActive:NO error:&error];
83 DCHECK(CheckAndLogError(success, error)); 83 RTC_DCHECK(CheckAndLogError(success, error));
84 return; 84 return;
85 } 85 }
86 // Use a category which supports simultaneous recording and playback. 86 // Use a category which supports simultaneous recording and playback.
87 // By default, using this category implies that our app’s audio is 87 // By default, using this category implies that our app’s audio is
88 // nonmixable, hence activating the session will interrupt any other 88 // nonmixable, hence activating the session will interrupt any other
89 // audio sessions which are also nonmixable. 89 // audio sessions which are also nonmixable.
90 if (session.category != AVAudioSessionCategoryPlayAndRecord) { 90 if (session.category != AVAudioSessionCategoryPlayAndRecord) {
91 error = nil; 91 error = nil;
92 success = [session setCategory:AVAudioSessionCategoryPlayAndRecord 92 success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
93 error:&error]; 93 error:&error];
94 DCHECK(CheckAndLogError(success, error)); 94 RTC_DCHECK(CheckAndLogError(success, error));
95 } 95 }
96 // Specify mode for two-way voice communication (e.g. VoIP). 96 // Specify mode for two-way voice communication (e.g. VoIP).
97 if (session.mode != AVAudioSessionModeVoiceChat) { 97 if (session.mode != AVAudioSessionModeVoiceChat) {
98 error = nil; 98 error = nil;
99 success = [session setMode:AVAudioSessionModeVoiceChat error:&error]; 99 success = [session setMode:AVAudioSessionModeVoiceChat error:&error];
100 DCHECK(CheckAndLogError(success, error)); 100 RTC_DCHECK(CheckAndLogError(success, error));
101 } 101 }
102 // Set the session's sample rate or the hardware sample rate. 102 // Set the session's sample rate or the hardware sample rate.
103 // It is essential that we use the same sample rate as stream format 103 // It is essential that we use the same sample rate as stream format
104 // to ensure that the I/O unit does not have to do sample rate conversion. 104 // to ensure that the I/O unit does not have to do sample rate conversion.
105 error = nil; 105 error = nil;
106 success = 106 success =
107 [session setPreferredSampleRate:kPreferredSampleRate error:&error]; 107 [session setPreferredSampleRate:kPreferredSampleRate error:&error];
108 DCHECK(CheckAndLogError(success, error)); 108 RTC_DCHECK(CheckAndLogError(success, error));
109 // Set the preferred audio I/O buffer duration, in seconds. 109 // Set the preferred audio I/O buffer duration, in seconds.
110 // TODO(henrika): add more comments here. 110 // TODO(henrika): add more comments here.
111 error = nil; 111 error = nil;
112 success = [session setPreferredIOBufferDuration:kPreferredIOBufferDuration 112 success = [session setPreferredIOBufferDuration:kPreferredIOBufferDuration
113 error:&error]; 113 error:&error];
114 DCHECK(CheckAndLogError(success, error)); 114 RTC_DCHECK(CheckAndLogError(success, error));
115 115
116 // TODO(henrika): add observers here... 116 // TODO(henrika): add observers here...
117 117
118 // Activate the audio session. Activation can fail if another active audio 118 // Activate the audio session. Activation can fail if another active audio
119 // session (e.g. phone call) has higher priority than ours. 119 // session (e.g. phone call) has higher priority than ours.
120 error = nil; 120 error = nil;
121 success = [session setActive:YES error:&error]; 121 success = [session setActive:YES error:&error];
122 DCHECK(CheckAndLogError(success, error)); 122 RTC_DCHECK(CheckAndLogError(success, error));
123 CHECK(session.isInputAvailable) << "No input path is available!"; 123 RTC_CHECK(session.isInputAvailable) << "No input path is available!";
124 // Ensure that category and mode are actually activated. 124 // Ensure that category and mode are actually activated.
125 DCHECK( 125 RTC_DCHECK(
126 [session.category isEqualToString:AVAudioSessionCategoryPlayAndRecord]); 126 [session.category isEqualToString:AVAudioSessionCategoryPlayAndRecord]);
127 DCHECK([session.mode isEqualToString:AVAudioSessionModeVoiceChat]); 127 RTC_DCHECK([session.mode isEqualToString:AVAudioSessionModeVoiceChat]);
128 // Try to set the preferred number of hardware audio channels. These calls 128 // Try to set the preferred number of hardware audio channels. These calls
129 // must be done after setting the audio session’s category and mode and 129 // must be done after setting the audio session’s category and mode and
130 // activating the session. 130 // activating the session.
131 // We try to use mono in both directions to save resources and format 131 // We try to use mono in both directions to save resources and format
132 // conversions in the audio unit. Some devices does only support stereo; 132 // conversions in the audio unit. Some devices does only support stereo;
133 // e.g. wired headset on iPhone 6. 133 // e.g. wired headset on iPhone 6.
134 // TODO(henrika): add support for stereo if needed. 134 // TODO(henrika): add support for stereo if needed.
135 error = nil; 135 error = nil;
136 success = 136 success =
137 [session setPreferredInputNumberOfChannels:kPreferredNumberOfChannels 137 [session setPreferredInputNumberOfChannels:kPreferredNumberOfChannels
138 error:&error]; 138 error:&error];
139 DCHECK(CheckAndLogError(success, error)); 139 RTC_DCHECK(CheckAndLogError(success, error));
140 error = nil; 140 error = nil;
141 success = 141 success =
142 [session setPreferredOutputNumberOfChannels:kPreferredNumberOfChannels 142 [session setPreferredOutputNumberOfChannels:kPreferredNumberOfChannels
143 error:&error]; 143 error:&error];
144 DCHECK(CheckAndLogError(success, error)); 144 RTC_DCHECK(CheckAndLogError(success, error));
145 } 145 }
146 } 146 }
147 147
148 #if !defined(NDEBUG) 148 #if !defined(NDEBUG)
149 // Helper method for printing out an AudioStreamBasicDescription structure. 149 // Helper method for printing out an AudioStreamBasicDescription structure.
150 static void LogABSD(AudioStreamBasicDescription absd) { 150 static void LogABSD(AudioStreamBasicDescription absd) {
151 char formatIDString[5]; 151 char formatIDString[5];
152 UInt32 formatID = CFSwapInt32HostToBig(absd.mFormatID); 152 UInt32 formatID = CFSwapInt32HostToBig(absd.mFormatID);
153 bcopy(&formatID, formatIDString, 4); 153 bcopy(&formatID, formatIDString, 4);
154 formatIDString[4] = '\0'; 154 formatIDString[4] = '\0';
(...skipping 28 matching lines...) Expand all
183 _playing(0), 183 _playing(0),
184 _initialized(false), 184 _initialized(false),
185 _recIsInitialized(false), 185 _recIsInitialized(false),
186 _playIsInitialized(false), 186 _playIsInitialized(false),
187 _audioInterruptionObserver(nullptr) { 187 _audioInterruptionObserver(nullptr) {
188 LOGI() << "ctor" << ios::GetCurrentThreadDescription(); 188 LOGI() << "ctor" << ios::GetCurrentThreadDescription();
189 } 189 }
190 190
191 AudioDeviceIOS::~AudioDeviceIOS() { 191 AudioDeviceIOS::~AudioDeviceIOS() {
192 LOGI() << "~dtor"; 192 LOGI() << "~dtor";
193 DCHECK(_threadChecker.CalledOnValidThread()); 193 RTC_DCHECK(_threadChecker.CalledOnValidThread());
194 Terminate(); 194 Terminate();
195 } 195 }
196 196
197 void AudioDeviceIOS::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) { 197 void AudioDeviceIOS::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {
198 LOGI() << "AttachAudioBuffer"; 198 LOGI() << "AttachAudioBuffer";
199 DCHECK(audioBuffer); 199 RTC_DCHECK(audioBuffer);
200 DCHECK(_threadChecker.CalledOnValidThread()); 200 RTC_DCHECK(_threadChecker.CalledOnValidThread());
201 _audioDeviceBuffer = audioBuffer; 201 _audioDeviceBuffer = audioBuffer;
202 } 202 }
203 203
204 int32_t AudioDeviceIOS::Init() { 204 int32_t AudioDeviceIOS::Init() {
205 LOGI() << "Init"; 205 LOGI() << "Init";
206 DCHECK(_threadChecker.CalledOnValidThread()); 206 RTC_DCHECK(_threadChecker.CalledOnValidThread());
207 if (_initialized) { 207 if (_initialized) {
208 return 0; 208 return 0;
209 } 209 }
210 #if !defined(NDEBUG) 210 #if !defined(NDEBUG)
211 LogDeviceInfo(); 211 LogDeviceInfo();
212 #endif 212 #endif
213 // Store the preferred sample rate and preferred number of channels already 213 // Store the preferred sample rate and preferred number of channels already
214 // here. They have not been set and confirmed yet since ActivateAudioSession() 214 // here. They have not been set and confirmed yet since ActivateAudioSession()
215 // is not called until audio is about to start. However, it makes sense to 215 // is not called until audio is about to start. However, it makes sense to
216 // store the parameters now and then verify at a later stage. 216 // store the parameters now and then verify at a later stage.
217 _playoutParameters.reset(kPreferredSampleRate, kPreferredNumberOfChannels); 217 _playoutParameters.reset(kPreferredSampleRate, kPreferredNumberOfChannels);
218 _recordParameters.reset(kPreferredSampleRate, kPreferredNumberOfChannels); 218 _recordParameters.reset(kPreferredSampleRate, kPreferredNumberOfChannels);
219 // Ensure that the audio device buffer (ADB) knows about the internal audio 219 // Ensure that the audio device buffer (ADB) knows about the internal audio
220 // parameters. Note that, even if we are unable to get a mono audio session, 220 // parameters. Note that, even if we are unable to get a mono audio session,
221 // we will always tell the I/O audio unit to do a channel format conversion 221 // we will always tell the I/O audio unit to do a channel format conversion
222 // to guarantee mono on the "input side" of the audio unit. 222 // to guarantee mono on the "input side" of the audio unit.
223 UpdateAudioDeviceBuffer(); 223 UpdateAudioDeviceBuffer();
224 _initialized = true; 224 _initialized = true;
225 return 0; 225 return 0;
226 } 226 }
227 227
228 int32_t AudioDeviceIOS::Terminate() { 228 int32_t AudioDeviceIOS::Terminate() {
229 LOGI() << "Terminate"; 229 LOGI() << "Terminate";
230 DCHECK(_threadChecker.CalledOnValidThread()); 230 RTC_DCHECK(_threadChecker.CalledOnValidThread());
231 if (!_initialized) { 231 if (!_initialized) {
232 return 0; 232 return 0;
233 } 233 }
234 ShutdownPlayOrRecord(); 234 ShutdownPlayOrRecord();
235 _initialized = false; 235 _initialized = false;
236 return 0; 236 return 0;
237 } 237 }
238 238
239 int32_t AudioDeviceIOS::InitPlayout() { 239 int32_t AudioDeviceIOS::InitPlayout() {
240 LOGI() << "InitPlayout"; 240 LOGI() << "InitPlayout";
241 DCHECK(_threadChecker.CalledOnValidThread()); 241 RTC_DCHECK(_threadChecker.CalledOnValidThread());
242 DCHECK(_initialized); 242 RTC_DCHECK(_initialized);
243 DCHECK(!_playIsInitialized); 243 RTC_DCHECK(!_playIsInitialized);
244 DCHECK(!_playing); 244 RTC_DCHECK(!_playing);
245 if (!_recIsInitialized) { 245 if (!_recIsInitialized) {
246 if (!InitPlayOrRecord()) { 246 if (!InitPlayOrRecord()) {
247 LOG_F(LS_ERROR) << "InitPlayOrRecord failed!"; 247 LOG_F(LS_ERROR) << "InitPlayOrRecord failed!";
248 return -1; 248 return -1;
249 } 249 }
250 } 250 }
251 _playIsInitialized = true; 251 _playIsInitialized = true;
252 return 0; 252 return 0;
253 } 253 }
254 254
255 int32_t AudioDeviceIOS::InitRecording() { 255 int32_t AudioDeviceIOS::InitRecording() {
256 LOGI() << "InitRecording"; 256 LOGI() << "InitRecording";
257 DCHECK(_threadChecker.CalledOnValidThread()); 257 RTC_DCHECK(_threadChecker.CalledOnValidThread());
258 DCHECK(_initialized); 258 RTC_DCHECK(_initialized);
259 DCHECK(!_recIsInitialized); 259 RTC_DCHECK(!_recIsInitialized);
260 DCHECK(!_recording); 260 RTC_DCHECK(!_recording);
261 if (!_playIsInitialized) { 261 if (!_playIsInitialized) {
262 if (!InitPlayOrRecord()) { 262 if (!InitPlayOrRecord()) {
263 LOG_F(LS_ERROR) << "InitPlayOrRecord failed!"; 263 LOG_F(LS_ERROR) << "InitPlayOrRecord failed!";
264 return -1; 264 return -1;
265 } 265 }
266 } 266 }
267 _recIsInitialized = true; 267 _recIsInitialized = true;
268 return 0; 268 return 0;
269 } 269 }
270 270
271 int32_t AudioDeviceIOS::StartPlayout() { 271 int32_t AudioDeviceIOS::StartPlayout() {
272 LOGI() << "StartPlayout"; 272 LOGI() << "StartPlayout";
273 DCHECK(_threadChecker.CalledOnValidThread()); 273 RTC_DCHECK(_threadChecker.CalledOnValidThread());
274 DCHECK(_playIsInitialized); 274 RTC_DCHECK(_playIsInitialized);
275 DCHECK(!_playing); 275 RTC_DCHECK(!_playing);
276 _fineAudioBuffer->ResetPlayout(); 276 _fineAudioBuffer->ResetPlayout();
277 if (!_recording) { 277 if (!_recording) {
278 OSStatus result = AudioOutputUnitStart(_vpioUnit); 278 OSStatus result = AudioOutputUnitStart(_vpioUnit);
279 if (result != noErr) { 279 if (result != noErr) {
280 LOG_F(LS_ERROR) << "AudioOutputUnitStart failed: " << result; 280 LOG_F(LS_ERROR) << "AudioOutputUnitStart failed: " << result;
281 return -1; 281 return -1;
282 } 282 }
283 } 283 }
284 rtc::AtomicOps::ReleaseStore(&_playing, 1); 284 rtc::AtomicOps::ReleaseStore(&_playing, 1);
285 return 0; 285 return 0;
286 } 286 }
287 287
288 int32_t AudioDeviceIOS::StopPlayout() { 288 int32_t AudioDeviceIOS::StopPlayout() {
289 LOGI() << "StopPlayout"; 289 LOGI() << "StopPlayout";
290 DCHECK(_threadChecker.CalledOnValidThread()); 290 RTC_DCHECK(_threadChecker.CalledOnValidThread());
291 if (!_playIsInitialized || !_playing) { 291 if (!_playIsInitialized || !_playing) {
292 return 0; 292 return 0;
293 } 293 }
294 if (!_recording) { 294 if (!_recording) {
295 ShutdownPlayOrRecord(); 295 ShutdownPlayOrRecord();
296 } 296 }
297 _playIsInitialized = false; 297 _playIsInitialized = false;
298 rtc::AtomicOps::ReleaseStore(&_playing, 0); 298 rtc::AtomicOps::ReleaseStore(&_playing, 0);
299 return 0; 299 return 0;
300 } 300 }
301 301
302 int32_t AudioDeviceIOS::StartRecording() { 302 int32_t AudioDeviceIOS::StartRecording() {
303 LOGI() << "StartRecording"; 303 LOGI() << "StartRecording";
304 DCHECK(_threadChecker.CalledOnValidThread()); 304 RTC_DCHECK(_threadChecker.CalledOnValidThread());
305 DCHECK(_recIsInitialized); 305 RTC_DCHECK(_recIsInitialized);
306 DCHECK(!_recording); 306 RTC_DCHECK(!_recording);
307 _fineAudioBuffer->ResetRecord(); 307 _fineAudioBuffer->ResetRecord();
308 if (!_playing) { 308 if (!_playing) {
309 OSStatus result = AudioOutputUnitStart(_vpioUnit); 309 OSStatus result = AudioOutputUnitStart(_vpioUnit);
310 if (result != noErr) { 310 if (result != noErr) {
311 LOG_F(LS_ERROR) << "AudioOutputUnitStart failed: " << result; 311 LOG_F(LS_ERROR) << "AudioOutputUnitStart failed: " << result;
312 return -1; 312 return -1;
313 } 313 }
314 } 314 }
315 rtc::AtomicOps::ReleaseStore(&_recording, 1); 315 rtc::AtomicOps::ReleaseStore(&_recording, 1);
316 return 0; 316 return 0;
317 } 317 }
318 318
319 int32_t AudioDeviceIOS::StopRecording() { 319 int32_t AudioDeviceIOS::StopRecording() {
320 LOGI() << "StopRecording"; 320 LOGI() << "StopRecording";
321 DCHECK(_threadChecker.CalledOnValidThread()); 321 RTC_DCHECK(_threadChecker.CalledOnValidThread());
322 if (!_recIsInitialized || !_recording) { 322 if (!_recIsInitialized || !_recording) {
323 return 0; 323 return 0;
324 } 324 }
325 if (!_playing) { 325 if (!_playing) {
326 ShutdownPlayOrRecord(); 326 ShutdownPlayOrRecord();
327 } 327 }
328 _recIsInitialized = false; 328 _recIsInitialized = false;
329 rtc::AtomicOps::ReleaseStore(&_recording, 0); 329 rtc::AtomicOps::ReleaseStore(&_recording, 0);
330 return 0; 330 return 0;
331 } 331 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 return 0; 370 return 0;
371 } 371 }
372 372
373 int32_t AudioDeviceIOS::RecordingDelay(uint16_t& delayMS) const { 373 int32_t AudioDeviceIOS::RecordingDelay(uint16_t& delayMS) const {
374 delayMS = kFixedRecordDelayEstimate; 374 delayMS = kFixedRecordDelayEstimate;
375 return 0; 375 return 0;
376 } 376 }
377 377
378 int AudioDeviceIOS::GetPlayoutAudioParameters(AudioParameters* params) const { 378 int AudioDeviceIOS::GetPlayoutAudioParameters(AudioParameters* params) const {
379 LOGI() << "GetPlayoutAudioParameters"; 379 LOGI() << "GetPlayoutAudioParameters";
380 DCHECK(_playoutParameters.is_valid()); 380 RTC_DCHECK(_playoutParameters.is_valid());
381 DCHECK(_threadChecker.CalledOnValidThread()); 381 RTC_DCHECK(_threadChecker.CalledOnValidThread());
382 *params = _playoutParameters; 382 *params = _playoutParameters;
383 return 0; 383 return 0;
384 } 384 }
385 385
386 int AudioDeviceIOS::GetRecordAudioParameters(AudioParameters* params) const { 386 int AudioDeviceIOS::GetRecordAudioParameters(AudioParameters* params) const {
387 LOGI() << "GetRecordAudioParameters"; 387 LOGI() << "GetRecordAudioParameters";
388 DCHECK(_recordParameters.is_valid()); 388 RTC_DCHECK(_recordParameters.is_valid());
389 DCHECK(_threadChecker.CalledOnValidThread()); 389 RTC_DCHECK(_threadChecker.CalledOnValidThread());
390 *params = _recordParameters; 390 *params = _recordParameters;
391 return 0; 391 return 0;
392 } 392 }
393 393
394 void AudioDeviceIOS::UpdateAudioDeviceBuffer() { 394 void AudioDeviceIOS::UpdateAudioDeviceBuffer() {
395 LOGI() << "UpdateAudioDevicebuffer"; 395 LOGI() << "UpdateAudioDevicebuffer";
396 // AttachAudioBuffer() is called at construction by the main class but check 396 // AttachAudioBuffer() is called at construction by the main class but check
397 // just in case. 397 // just in case.
398 DCHECK(_audioDeviceBuffer) << "AttachAudioBuffer must be called first"; 398 RTC_DCHECK(_audioDeviceBuffer) << "AttachAudioBuffer must be called first";
399 // Inform the audio device buffer (ADB) about the new audio format. 399 // Inform the audio device buffer (ADB) about the new audio format.
400 _audioDeviceBuffer->SetPlayoutSampleRate(_playoutParameters.sample_rate()); 400 _audioDeviceBuffer->SetPlayoutSampleRate(_playoutParameters.sample_rate());
401 _audioDeviceBuffer->SetPlayoutChannels(_playoutParameters.channels()); 401 _audioDeviceBuffer->SetPlayoutChannels(_playoutParameters.channels());
402 _audioDeviceBuffer->SetRecordingSampleRate(_recordParameters.sample_rate()); 402 _audioDeviceBuffer->SetRecordingSampleRate(_recordParameters.sample_rate());
403 _audioDeviceBuffer->SetRecordingChannels(_recordParameters.channels()); 403 _audioDeviceBuffer->SetRecordingChannels(_recordParameters.channels());
404 } 404 }
405 405
406 void AudioDeviceIOS::SetupAudioBuffersForActiveAudioSession() { 406 void AudioDeviceIOS::SetupAudioBuffersForActiveAudioSession() {
407 LOGI() << "SetupAudioBuffersForActiveAudioSession"; 407 LOGI() << "SetupAudioBuffersForActiveAudioSession";
408 AVAudioSession* session = [AVAudioSession sharedInstance]; 408 AVAudioSession* session = [AVAudioSession sharedInstance];
(...skipping 12 matching lines...) Expand all
421 << "Failed to enable an audio session with the preferred sample rate!"; 421 << "Failed to enable an audio session with the preferred sample rate!";
422 } 422 }
423 423
424 // At this stage, we also know the exact IO buffer duration and can add 424 // At this stage, we also know the exact IO buffer duration and can add
425 // that info to the existing audio parameters where it is converted into 425 // that info to the existing audio parameters where it is converted into
426 // number of audio frames. 426 // number of audio frames.
427 // Example: IO buffer size = 0.008 seconds <=> 128 audio frames at 16kHz. 427 // Example: IO buffer size = 0.008 seconds <=> 128 audio frames at 16kHz.
428 // Hence, 128 is the size we expect to see in upcoming render callbacks. 428 // Hence, 128 is the size we expect to see in upcoming render callbacks.
429 _playoutParameters.reset(session.sampleRate, _playoutParameters.channels(), 429 _playoutParameters.reset(session.sampleRate, _playoutParameters.channels(),
430 session.IOBufferDuration); 430 session.IOBufferDuration);
431 DCHECK(_playoutParameters.is_complete()); 431 RTC_DCHECK(_playoutParameters.is_complete());
432 _recordParameters.reset(session.sampleRate, _recordParameters.channels(), 432 _recordParameters.reset(session.sampleRate, _recordParameters.channels(),
433 session.IOBufferDuration); 433 session.IOBufferDuration);
434 DCHECK(_recordParameters.is_complete()); 434 RTC_DCHECK(_recordParameters.is_complete());
435 LOG(LS_INFO) << " frames per I/O buffer: " 435 LOG(LS_INFO) << " frames per I/O buffer: "
436 << _playoutParameters.frames_per_buffer(); 436 << _playoutParameters.frames_per_buffer();
437 LOG(LS_INFO) << " bytes per I/O buffer: " 437 LOG(LS_INFO) << " bytes per I/O buffer: "
438 << _playoutParameters.GetBytesPerBuffer(); 438 << _playoutParameters.GetBytesPerBuffer();
439 DCHECK_EQ(_playoutParameters.GetBytesPerBuffer(), 439 RTC_DCHECK_EQ(_playoutParameters.GetBytesPerBuffer(),
440 _recordParameters.GetBytesPerBuffer()); 440 _recordParameters.GetBytesPerBuffer());
441 441
442 // Update the ADB parameters since the sample rate might have changed. 442 // Update the ADB parameters since the sample rate might have changed.
443 UpdateAudioDeviceBuffer(); 443 UpdateAudioDeviceBuffer();
444 444
445 // Create a modified audio buffer class which allows us to ask for, 445 // Create a modified audio buffer class which allows us to ask for,
446 // or deliver, any number of samples (and not only multiple of 10ms) to match 446 // or deliver, any number of samples (and not only multiple of 10ms) to match
447 // the native audio unit buffer size. 447 // the native audio unit buffer size.
448 DCHECK(_audioDeviceBuffer); 448 RTC_DCHECK(_audioDeviceBuffer);
449 _fineAudioBuffer.reset(new FineAudioBuffer( 449 _fineAudioBuffer.reset(new FineAudioBuffer(
450 _audioDeviceBuffer, _playoutParameters.GetBytesPerBuffer(), 450 _audioDeviceBuffer, _playoutParameters.GetBytesPerBuffer(),
451 _playoutParameters.sample_rate())); 451 _playoutParameters.sample_rate()));
452 452
453 // The extra/temporary playoutbuffer must be of this size to avoid 453 // The extra/temporary playoutbuffer must be of this size to avoid
454 // unnecessary memcpy while caching data between successive callbacks. 454 // unnecessary memcpy while caching data between successive callbacks.
455 const int requiredPlayoutBufferSize = 455 const int requiredPlayoutBufferSize =
456 _fineAudioBuffer->RequiredPlayoutBufferSizeBytes(); 456 _fineAudioBuffer->RequiredPlayoutBufferSizeBytes();
457 LOG(LS_INFO) << " required playout buffer size: " 457 LOG(LS_INFO) << " required playout buffer size: "
458 << requiredPlayoutBufferSize; 458 << requiredPlayoutBufferSize;
459 _playoutAudioBuffer.reset(new SInt8[requiredPlayoutBufferSize]); 459 _playoutAudioBuffer.reset(new SInt8[requiredPlayoutBufferSize]);
460 460
461 // Allocate AudioBuffers to be used as storage for the received audio. 461 // Allocate AudioBuffers to be used as storage for the received audio.
462 // The AudioBufferList structure works as a placeholder for the 462 // The AudioBufferList structure works as a placeholder for the
463 // AudioBuffer structure, which holds a pointer to the actual data buffer 463 // AudioBuffer structure, which holds a pointer to the actual data buffer
464 // in |_recordAudioBuffer|. Recorded audio will be rendered into this memory 464 // in |_recordAudioBuffer|. Recorded audio will be rendered into this memory
465 // at each input callback when calling AudioUnitRender(). 465 // at each input callback when calling AudioUnitRender().
466 const int dataByteSize = _recordParameters.GetBytesPerBuffer(); 466 const int dataByteSize = _recordParameters.GetBytesPerBuffer();
467 _recordAudioBuffer.reset(new SInt8[dataByteSize]); 467 _recordAudioBuffer.reset(new SInt8[dataByteSize]);
468 _audioRecordBufferList.mNumberBuffers = 1; 468 _audioRecordBufferList.mNumberBuffers = 1;
469 AudioBuffer* audioBuffer = &_audioRecordBufferList.mBuffers[0]; 469 AudioBuffer* audioBuffer = &_audioRecordBufferList.mBuffers[0];
470 audioBuffer->mNumberChannels = _recordParameters.channels(); 470 audioBuffer->mNumberChannels = _recordParameters.channels();
471 audioBuffer->mDataByteSize = dataByteSize; 471 audioBuffer->mDataByteSize = dataByteSize;
472 audioBuffer->mData = _recordAudioBuffer.get(); 472 audioBuffer->mData = _recordAudioBuffer.get();
473 } 473 }
474 474
475 bool AudioDeviceIOS::SetupAndInitializeVoiceProcessingAudioUnit() { 475 bool AudioDeviceIOS::SetupAndInitializeVoiceProcessingAudioUnit() {
476 LOGI() << "SetupAndInitializeVoiceProcessingAudioUnit"; 476 LOGI() << "SetupAndInitializeVoiceProcessingAudioUnit";
477 DCHECK(!_vpioUnit); 477 RTC_DCHECK(!_vpioUnit);
478 // Create an audio component description to identify the Voice-Processing 478 // Create an audio component description to identify the Voice-Processing
479 // I/O audio unit. 479 // I/O audio unit.
480 AudioComponentDescription vpioUnitDescription; 480 AudioComponentDescription vpioUnitDescription;
481 vpioUnitDescription.componentType = kAudioUnitType_Output; 481 vpioUnitDescription.componentType = kAudioUnitType_Output;
482 vpioUnitDescription.componentSubType = kAudioUnitSubType_VoiceProcessingIO; 482 vpioUnitDescription.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
483 vpioUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 483 vpioUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
484 vpioUnitDescription.componentFlags = 0; 484 vpioUnitDescription.componentFlags = 0;
485 vpioUnitDescription.componentFlagsMask = 0; 485 vpioUnitDescription.componentFlagsMask = 0;
486 // Obtain an audio unit instance given the description. 486 // Obtain an audio unit instance given the description.
487 AudioComponent foundVpioUnitRef = 487 AudioComponent foundVpioUnitRef =
(...skipping 24 matching lines...) Expand all
512 sizeof(enableOutput)), 512 sizeof(enableOutput)),
513 "Failed to enable output on output scope of output element"); 513 "Failed to enable output on output scope of output element");
514 514
515 // Set the application formats for input and output: 515 // Set the application formats for input and output:
516 // - use same format in both directions 516 // - use same format in both directions
517 // - avoid resampling in the I/O unit by using the hardware sample rate 517 // - avoid resampling in the I/O unit by using the hardware sample rate
518 // - linear PCM => noncompressed audio data format with one frame per packet 518 // - linear PCM => noncompressed audio data format with one frame per packet
519 // - no need to specify interleaving since only mono is supported 519 // - no need to specify interleaving since only mono is supported
520 AudioStreamBasicDescription applicationFormat = {0}; 520 AudioStreamBasicDescription applicationFormat = {0};
521 UInt32 size = sizeof(applicationFormat); 521 UInt32 size = sizeof(applicationFormat);
522 DCHECK_EQ(_playoutParameters.sample_rate(), _recordParameters.sample_rate()); 522 RTC_DCHECK_EQ(_playoutParameters.sample_rate(),
523 DCHECK_EQ(1, kPreferredNumberOfChannels); 523 _recordParameters.sample_rate());
524 RTC_DCHECK_EQ(1, kPreferredNumberOfChannels);
524 applicationFormat.mSampleRate = _playoutParameters.sample_rate(); 525 applicationFormat.mSampleRate = _playoutParameters.sample_rate();
525 applicationFormat.mFormatID = kAudioFormatLinearPCM; 526 applicationFormat.mFormatID = kAudioFormatLinearPCM;
526 applicationFormat.mFormatFlags = 527 applicationFormat.mFormatFlags =
527 kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; 528 kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
528 applicationFormat.mBytesPerPacket = kBytesPerSample; 529 applicationFormat.mBytesPerPacket = kBytesPerSample;
529 applicationFormat.mFramesPerPacket = 1; // uncompressed 530 applicationFormat.mFramesPerPacket = 1; // uncompressed
530 applicationFormat.mBytesPerFrame = kBytesPerSample; 531 applicationFormat.mBytesPerFrame = kBytesPerSample;
531 applicationFormat.mChannelsPerFrame = kPreferredNumberOfChannels; 532 applicationFormat.mChannelsPerFrame = kPreferredNumberOfChannels;
532 applicationFormat.mBitsPerChannel = 8 * kBytesPerSample; 533 applicationFormat.mBitsPerChannel = 8 * kBytesPerSample;
533 #if !defined(NDEBUG) 534 #if !defined(NDEBUG)
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 return true; 674 return true;
674 } 675 }
675 676
676 OSStatus AudioDeviceIOS::RecordedDataIsAvailable( 677 OSStatus AudioDeviceIOS::RecordedDataIsAvailable(
677 void* inRefCon, 678 void* inRefCon,
678 AudioUnitRenderActionFlags* ioActionFlags, 679 AudioUnitRenderActionFlags* ioActionFlags,
679 const AudioTimeStamp* inTimeStamp, 680 const AudioTimeStamp* inTimeStamp,
680 UInt32 inBusNumber, 681 UInt32 inBusNumber,
681 UInt32 inNumberFrames, 682 UInt32 inNumberFrames,
682 AudioBufferList* ioData) { 683 AudioBufferList* ioData) {
683 DCHECK_EQ(1u, inBusNumber); 684 RTC_DCHECK_EQ(1u, inBusNumber);
684 DCHECK(!ioData); // no buffer should be allocated for input at this stage 685 RTC_DCHECK(!ioData); // no buffer should be allocated for input at this stage
685 AudioDeviceIOS* audio_device_ios = static_cast<AudioDeviceIOS*>(inRefCon); 686 AudioDeviceIOS* audio_device_ios = static_cast<AudioDeviceIOS*>(inRefCon);
686 return audio_device_ios->OnRecordedDataIsAvailable( 687 return audio_device_ios->OnRecordedDataIsAvailable(
687 ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames); 688 ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames);
688 } 689 }
689 690
690 OSStatus AudioDeviceIOS::OnRecordedDataIsAvailable( 691 OSStatus AudioDeviceIOS::OnRecordedDataIsAvailable(
691 AudioUnitRenderActionFlags* ioActionFlags, 692 AudioUnitRenderActionFlags* ioActionFlags,
692 const AudioTimeStamp* inTimeStamp, 693 const AudioTimeStamp* inTimeStamp,
693 UInt32 inBusNumber, 694 UInt32 inBusNumber,
694 UInt32 inNumberFrames) { 695 UInt32 inNumberFrames) {
695 DCHECK_EQ(_recordParameters.frames_per_buffer(), inNumberFrames); 696 RTC_DCHECK_EQ(_recordParameters.frames_per_buffer(), inNumberFrames);
696 OSStatus result = noErr; 697 OSStatus result = noErr;
697 // Simply return if recording is not enabled. 698 // Simply return if recording is not enabled.
698 if (!rtc::AtomicOps::AcquireLoad(&_recording)) 699 if (!rtc::AtomicOps::AcquireLoad(&_recording))
699 return result; 700 return result;
700 // Obtain the recorded audio samples by initiating a rendering cycle. 701 // Obtain the recorded audio samples by initiating a rendering cycle.
701 // Since it happens on the input bus, the |ioData| parameter is a reference 702 // Since it happens on the input bus, the |ioData| parameter is a reference
702 // to the preallocated audio buffer list that the audio unit renders into. 703 // to the preallocated audio buffer list that the audio unit renders into.
703 // TODO(henrika): should error handling be improved? 704 // TODO(henrika): should error handling be improved?
704 AudioBufferList* ioData = &_audioRecordBufferList; 705 AudioBufferList* ioData = &_audioRecordBufferList;
705 result = AudioUnitRender(_vpioUnit, ioActionFlags, inTimeStamp, inBusNumber, 706 result = AudioUnitRender(_vpioUnit, ioActionFlags, inTimeStamp, inBusNumber,
706 inNumberFrames, ioData); 707 inNumberFrames, ioData);
707 if (result != noErr) { 708 if (result != noErr) {
708 LOG_F(LS_ERROR) << "AudioOutputUnitStart failed: " << result; 709 LOG_F(LS_ERROR) << "AudioOutputUnitStart failed: " << result;
709 return result; 710 return result;
710 } 711 }
711 // Get a pointer to the recorded audio and send it to the WebRTC ADB. 712 // Get a pointer to the recorded audio and send it to the WebRTC ADB.
712 // Use the FineAudioBuffer instance to convert between native buffer size 713 // Use the FineAudioBuffer instance to convert between native buffer size
713 // and the 10ms buffer size used by WebRTC. 714 // and the 10ms buffer size used by WebRTC.
714 const UInt32 dataSizeInBytes = ioData->mBuffers[0].mDataByteSize; 715 const UInt32 dataSizeInBytes = ioData->mBuffers[0].mDataByteSize;
715 CHECK_EQ(dataSizeInBytes / kBytesPerSample, inNumberFrames); 716 RTC_CHECK_EQ(dataSizeInBytes / kBytesPerSample, inNumberFrames);
716 SInt8* data = static_cast<SInt8*>(ioData->mBuffers[0].mData); 717 SInt8* data = static_cast<SInt8*>(ioData->mBuffers[0].mData);
717 _fineAudioBuffer->DeliverRecordedData(data, dataSizeInBytes, 718 _fineAudioBuffer->DeliverRecordedData(data, dataSizeInBytes,
718 kFixedPlayoutDelayEstimate, 719 kFixedPlayoutDelayEstimate,
719 kFixedRecordDelayEstimate); 720 kFixedRecordDelayEstimate);
720 return noErr; 721 return noErr;
721 } 722 }
722 723
723 OSStatus AudioDeviceIOS::GetPlayoutData( 724 OSStatus AudioDeviceIOS::GetPlayoutData(
724 void* inRefCon, 725 void* inRefCon,
725 AudioUnitRenderActionFlags* ioActionFlags, 726 AudioUnitRenderActionFlags* ioActionFlags,
726 const AudioTimeStamp* inTimeStamp, 727 const AudioTimeStamp* inTimeStamp,
727 UInt32 inBusNumber, 728 UInt32 inBusNumber,
728 UInt32 inNumberFrames, 729 UInt32 inNumberFrames,
729 AudioBufferList* ioData) { 730 AudioBufferList* ioData) {
730 DCHECK_EQ(0u, inBusNumber); 731 RTC_DCHECK_EQ(0u, inBusNumber);
731 DCHECK(ioData); 732 RTC_DCHECK(ioData);
732 AudioDeviceIOS* audio_device_ios = static_cast<AudioDeviceIOS*>(inRefCon); 733 AudioDeviceIOS* audio_device_ios = static_cast<AudioDeviceIOS*>(inRefCon);
733 return audio_device_ios->OnGetPlayoutData(ioActionFlags, inNumberFrames, 734 return audio_device_ios->OnGetPlayoutData(ioActionFlags, inNumberFrames,
734 ioData); 735 ioData);
735 } 736 }
736 737
737 OSStatus AudioDeviceIOS::OnGetPlayoutData( 738 OSStatus AudioDeviceIOS::OnGetPlayoutData(
738 AudioUnitRenderActionFlags* ioActionFlags, 739 AudioUnitRenderActionFlags* ioActionFlags,
739 UInt32 inNumberFrames, 740 UInt32 inNumberFrames,
740 AudioBufferList* ioData) { 741 AudioBufferList* ioData) {
741 // Verify 16-bit, noninterleaved mono PCM signal format. 742 // Verify 16-bit, noninterleaved mono PCM signal format.
742 DCHECK_EQ(1u, ioData->mNumberBuffers); 743 RTC_DCHECK_EQ(1u, ioData->mNumberBuffers);
743 DCHECK_EQ(1u, ioData->mBuffers[0].mNumberChannels); 744 RTC_DCHECK_EQ(1u, ioData->mBuffers[0].mNumberChannels);
744 // Get pointer to internal audio buffer to which new audio data shall be 745 // Get pointer to internal audio buffer to which new audio data shall be
745 // written. 746 // written.
746 const UInt32 dataSizeInBytes = ioData->mBuffers[0].mDataByteSize; 747 const UInt32 dataSizeInBytes = ioData->mBuffers[0].mDataByteSize;
747 CHECK_EQ(dataSizeInBytes / kBytesPerSample, inNumberFrames); 748 RTC_CHECK_EQ(dataSizeInBytes / kBytesPerSample, inNumberFrames);
748 SInt8* destination = static_cast<SInt8*>(ioData->mBuffers[0].mData); 749 SInt8* destination = static_cast<SInt8*>(ioData->mBuffers[0].mData);
749 // Produce silence and give audio unit a hint about it if playout is not 750 // Produce silence and give audio unit a hint about it if playout is not
750 // activated. 751 // activated.
751 if (!rtc::AtomicOps::AcquireLoad(&_playing)) { 752 if (!rtc::AtomicOps::AcquireLoad(&_playing)) {
752 *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence; 753 *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
753 memset(destination, 0, dataSizeInBytes); 754 memset(destination, 0, dataSizeInBytes);
754 return noErr; 755 return noErr;
755 } 756 }
756 // Read decoded 16-bit PCM samples from WebRTC (using a size that matches 757 // Read decoded 16-bit PCM samples from WebRTC (using a size that matches
757 // the native I/O audio unit) to a preallocated intermediate buffer and 758 // the native I/O audio unit) to a preallocated intermediate buffer and
758 // copy the result to the audio buffer in the |ioData| destination. 759 // copy the result to the audio buffer in the |ioData| destination.
759 SInt8* source = _playoutAudioBuffer.get(); 760 SInt8* source = _playoutAudioBuffer.get();
760 _fineAudioBuffer->GetPlayoutData(source); 761 _fineAudioBuffer->GetPlayoutData(source);
761 memcpy(destination, source, dataSizeInBytes); 762 memcpy(destination, source, dataSizeInBytes);
762 return noErr; 763 return noErr;
763 } 764 }
764 765
765 } // namespace webrtc 766 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_device/ios/audio_device_ios.h ('k') | webrtc/modules/audio_device/ios/audio_device_unittest_ios.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698