diff --git a/sdk/objc/components/audio/RTCAudioSession+Private.h b/sdk/objc/components/audio/RTCAudioSession+Private.h index 8ee4fddd7f..4f5107f7e9 100644 --- a/sdk/objc/components/audio/RTCAudioSession+Private.h +++ b/sdk/objc/components/audio/RTCAudioSession+Private.h @@ -73,6 +73,12 @@ NS_ASSUME_NONNULL_BEGIN /** Returns a configuration error with the given description. */ - (NSError *)configurationErrorWithDescription:(NSString *)description; +/** Notifies the reciever that a playout glitch was detected. */ +- (void)notifyDidDetectPlayoutGlitch:(int64_t)totalNumberOfGlitches; + +/** Notifies the reciever that there was an error when starting an audio unit. */ +- (void)notifyAudioUnitStartFailedWithError:(OSStatus)error; + // Properties and methods for tests. - (void)notifyDidBeginInterruption; - (void)notifyDidEndInterruptionWithShouldResumeSession:(BOOL)shouldResumeSession; @@ -83,7 +89,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)notifyDidChangeCanPlayOrRecord:(BOOL)canPlayOrRecord; - (void)notifyDidStartPlayOrRecord; - (void)notifyDidStopPlayOrRecord; -- (void)notifyDidDetectPlayoutGlitch:(int64_t)totalNumberOfGlitches; @end diff --git a/sdk/objc/components/audio/RTCAudioSession.h b/sdk/objc/components/audio/RTCAudioSession.h index 58811553b3..3b83b27ba5 100644 --- a/sdk/objc/components/audio/RTCAudioSession.h +++ b/sdk/objc/components/audio/RTCAudioSession.h @@ -99,6 +99,9 @@ RTC_OBJC_EXPORT failedToSetActive:(BOOL)active error:(NSError *)error; +- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)audioSession + audioUnitStartFailedWithError:(NSError *)error; + @end /** This is a protocol used to inform RTCAudioSession when the audio session diff --git a/sdk/objc/components/audio/RTCAudioSession.mm b/sdk/objc/components/audio/RTCAudioSession.mm index 057f62cf27..5031e1542e 100644 --- a/sdk/objc/components/audio/RTCAudioSession.mm +++ b/sdk/objc/components/audio/RTCAudioSession.mm @@ -794,6 +794,18 @@ NSString * const kRTCAudioSessionOutputVolumeSelector = @"outputVolume"; } } +- (void)notifyAudioUnitStartFailedWithError:(OSStatus)error { + for (auto delegate : self.delegates) { + SEL sel = @selector(audioSession:audioUnitStartFailedWithError:); + if ([delegate respondsToSelector:sel]) { + [delegate audioSession:self + audioUnitStartFailedWithError:[NSError errorWithDomain:kRTCAudioSessionErrorDomain + code:error + userInfo:nil]]; + } + } +} + - (void)notifyDidBeginInterruption { for (auto delegate : self.delegates) { SEL sel = @selector(audioSessionDidBeginInterruption:); diff --git a/sdk/objc/native/src/audio/audio_device_ios.mm b/sdk/objc/native/src/audio/audio_device_ios.mm index e3020ec1df..3ec7d0b75a 100644 --- a/sdk/objc/native/src/audio/audio_device_ios.mm +++ b/sdk/objc/native/src/audio/audio_device_ios.mm @@ -235,8 +235,11 @@ int32_t AudioDeviceIOS::StartPlayout() { fine_audio_buffer_->ResetPlayout(); } if (!recording_ && audio_unit_->GetState() == VoiceProcessingAudioUnit::kInitialized) { - if (!audio_unit_->Start()) { - RTCLogError(@"StartPlayout failed to start audio unit."); + OSStatus result = audio_unit_->Start(); + if (result != noErr) { + RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance]; + [session notifyAudioUnitStartFailedWithError:result]; + RTCLogError(@"StartPlayout failed to start audio unit, reason %d", result); return -1; } RTC_LOG(LS_INFO) << "Voice-Processing I/O audio unit is now started"; @@ -288,8 +291,11 @@ int32_t AudioDeviceIOS::StartRecording() { fine_audio_buffer_->ResetRecord(); } if (!playing_ && audio_unit_->GetState() == VoiceProcessingAudioUnit::kInitialized) { - if (!audio_unit_->Start()) { - RTCLogError(@"StartRecording failed to start audio unit."); + OSStatus result = audio_unit_->Start(); + if (result != noErr) { + RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance]; + [session notifyAudioUnitStartFailedWithError:result]; + RTCLogError(@"StartRecording failed to start audio unit, reason %d", result); return -1; } RTC_LOG(LS_INFO) << "Voice-Processing I/O audio unit is now started"; @@ -620,9 +626,16 @@ void AudioDeviceIOS::HandleSampleRateChange(float sample_rate) { } // Restart the audio unit if it was already running. - if (restart_audio_unit && !audio_unit_->Start()) { - RTCLogError(@"Failed to start audio unit with sample rate: %f", session_sample_rate); - return; + if (restart_audio_unit) { + OSStatus result = audio_unit_->Start(); + if (result != noErr) { + RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance]; + [session notifyAudioUnitStartFailedWithError:result]; + RTCLogError(@"Failed to start audio unit with sample rate: %f, reason %d", + session_sample_rate, + result); + return; + } } RTCLog(@"Successfully handled sample rate change."); } @@ -801,8 +814,10 @@ void AudioDeviceIOS::UpdateAudioUnit(bool can_play_or_record) { // Log session settings before trying to start audio streaming. RTC_OBJC_TYPE(RTCAudioSession)* session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance]; RTCLog(@"%@", session); - if (!audio_unit_->Start()) { - RTCLogError(@"Failed to start audio unit."); + OSStatus result = audio_unit_->Start(); + if (result != noErr) { + [session notifyAudioUnitStartFailedWithError:result]; + RTCLogError(@"Failed to start audio unit, reason %d", result); return; } } diff --git a/sdk/objc/native/src/audio/voice_processing_audio_unit.h b/sdk/objc/native/src/audio/voice_processing_audio_unit.h index 72e29c0d67..ed9dd98568 100644 --- a/sdk/objc/native/src/audio/voice_processing_audio_unit.h +++ b/sdk/objc/native/src/audio/voice_processing_audio_unit.h @@ -78,7 +78,7 @@ class VoiceProcessingAudioUnit { bool Initialize(Float64 sample_rate); // Starts the underlying audio unit. - bool Start(); + OSStatus Start(); // Stops the underlying audio unit. bool Stop(); diff --git a/sdk/objc/native/src/audio/voice_processing_audio_unit.mm b/sdk/objc/native/src/audio/voice_processing_audio_unit.mm index 2325b2ed2e..661022f523 100644 --- a/sdk/objc/native/src/audio/voice_processing_audio_unit.mm +++ b/sdk/objc/native/src/audio/voice_processing_audio_unit.mm @@ -332,19 +332,19 @@ bool VoiceProcessingAudioUnit::Initialize(Float64 sample_rate) { return true; } -bool VoiceProcessingAudioUnit::Start() { +OSStatus VoiceProcessingAudioUnit::Start() { RTC_DCHECK_GE(state_, kUninitialized); RTCLog(@"Starting audio unit."); OSStatus result = AudioOutputUnitStart(vpio_unit_); if (result != noErr) { RTCLogError(@"Failed to start audio unit. Error=%ld", (long)result); - return false; + return result; } else { RTCLog(@"Started audio unit"); } state_ = kStarted; - return true; + return noErr; } bool VoiceProcessingAudioUnit::Stop() {