Index: webrtc/modules/audio_device/ios/audio_device_ios.mm |
diff --git a/webrtc/modules/audio_device/ios/audio_device_ios.mm b/webrtc/modules/audio_device/ios/audio_device_ios.mm |
index e094ebdc3d833d1c0a12215cea6199bfb2e5802c..b0d26be6ec28837a4cebd6e66ffd869e2af2d0e5 100644 |
--- a/webrtc/modules/audio_device/ios/audio_device_ios.mm |
+++ b/webrtc/modules/audio_device/ios/audio_device_ios.mm |
@@ -86,6 +86,12 @@ const UInt32 kBytesPerSample = 2; |
// Can most likely be removed. |
const UInt16 kFixedPlayoutDelayEstimate = 30; |
const UInt16 kFixedRecordDelayEstimate = 30; |
+// Calls to AudioUnitInitialize() can fail if called back-to-back on different |
+// ADM instances. A fall-back solution is to allow multiple sequential calls |
+// with as small delay between each. This factor sets the max number of allowed |
+// initialization attempts. |
+const int kMaxNumberOfAudioUnitInitializeAttempts = 5; |
+ |
using ios::CheckAndLogError; |
@@ -741,6 +747,7 @@ bool AudioDeviceIOS::SetupAndInitializeVoiceProcessingAudioUnit() { |
vpio_unit_description.componentManufacturer = kAudioUnitManufacturer_Apple; |
vpio_unit_description.componentFlags = 0; |
vpio_unit_description.componentFlagsMask = 0; |
+ |
// Obtain an audio unit instance given the description. |
AudioComponent found_vpio_unit_ref = |
AudioComponentFindNext(nullptr, &vpio_unit_description); |
@@ -876,17 +883,28 @@ bool AudioDeviceIOS::SetupAndInitializeVoiceProcessingAudioUnit() { |
} |
// Initialize the Voice-Processing I/O unit instance. |
+ // Calls to AudioUnitInitialize() can fail if called back-to-back on |
+ // different ADM instances. The error message in this case is -66635 which is |
+ // undocumented. Tests have shown that calling AudioUnitInitialize a second |
+ // time, after a short sleep, avoids this issue. |
+ // See webrtc:5166 for details. |
+ int failed_initalize_attempts = 0; |
result = AudioUnitInitialize(vpio_unit_); |
- if (result != noErr) { |
- result = AudioUnitUninitialize(vpio_unit_); |
- if (result != noErr) { |
- LOG_F(LS_ERROR) << "AudioUnitUninitialize failed: " << result; |
- } |
- DisposeAudioUnit(); |
+ while (result != noErr) { |
LOG(LS_ERROR) << "Failed to initialize the Voice-Processing I/O unit: " |
<< result; |
- return false; |
+ ++failed_initalize_attempts; |
+ if (failed_initalize_attempts == kMaxNumberOfAudioUnitInitializeAttempts) { |
+ // Max number of initialization attempts exceeded, hence abort. |
+ LOG(LS_WARNING) << "Too many initialization attempts"; |
+ DisposeAudioUnit(); |
+ return false; |
+ } |
+ LOG(LS_INFO) << "pause 100ms and try audio unit initialization again..."; |
+ [NSThread sleepForTimeInterval:0.1f]; |
+ result = AudioUnitInitialize(vpio_unit_); |
} |
+ LOG(LS_INFO) << "Voice-Processing I/O unit is now initialized"; |
return true; |
} |