diff --git a/modules/audio_device/ios/audio_device_ios.h b/modules/audio_device/ios/audio_device_ios.h index c51a9799da5..b1d40537af5 100644 --- a/modules/audio_device/ios/audio_device_ios.h +++ b/modules/audio_device/ios/audio_device_ios.h @@ -195,6 +195,9 @@ class AudioDeviceIOS : public AudioDeviceGeneric, // Closes and deletes the voice-processing I/O unit. void ShutdownPlayOrRecord(); + // Resets thread-checkers before a call is restarted. + void PrepareForNewStart(); + // Ensures that methods are called from the same thread as this object is // created on. rtc::ThreadChecker thread_checker_; diff --git a/modules/audio_device/ios/audio_device_ios.mm b/modules/audio_device/ios/audio_device_ios.mm index 36da53819fa..f8aae2efe6d 100644 --- a/modules/audio_device/ios/audio_device_ios.mm +++ b/modules/audio_device/ios/audio_device_ios.mm @@ -491,15 +491,7 @@ static void LogDeviceInfo() { if (!audio_unit_->Stop()) { RTCLogError(@"Failed to stop the audio unit for interruption begin."); } else { - // The audio unit has been stopped but will be restarted when the - // interruption ends in HandleInterruptionEnd(). It will result in audio - // callbacks from a new native I/O thread which means that we must detach - // thread checkers here to be prepared for an upcoming new audio stream. - io_thread_checker_.DetachFromThread(); - // The audio device buffer must also be informed about the interrupted - // state so it can detach its thread checkers as well. - audio_device_buffer_->NativeAudioPlayoutInterrupted(); - audio_device_buffer_->NativeAudioRecordingInterrupted(); + PrepareForNewStart(); } } is_interrupted_ = true; @@ -581,6 +573,7 @@ static void LogDeviceInfo() { if (audio_unit_->GetState() == VoiceProcessingAudioUnit::kStarted) { audio_unit_->Stop(); restart_audio_unit = true; + PrepareForNewStart(); } if (audio_unit_->GetState() == VoiceProcessingAudioUnit::kInitialized) { audio_unit_->Uninitialize(); @@ -901,4 +894,19 @@ static void LogDeviceInfo() { [session unlockForConfiguration]; } +void AudioDeviceIOS::PrepareForNewStart() { + LOGI() << "PrepareForNewStart"; + // The audio unit has been stopped and preparations are needed for an upcoming + // restart. It will result in audio callbacks from a new native I/O thread + // which means that we must detach thread checkers here to be prepared for an + // upcoming new audio stream. + io_thread_checker_.DetachFromThread(); + // The audio device buffer must also be informed about the interrupted + // state so it can detach its thread checkers as well. + if (audio_device_buffer_) { + audio_device_buffer_->NativeAudioPlayoutInterrupted(); + audio_device_buffer_->NativeAudioRecordingInterrupted(); + } +} + } // namespace webrtc diff --git a/sdk/objc/Framework/Native/src/audio/audio_device_ios.h b/sdk/objc/Framework/Native/src/audio/audio_device_ios.h index 250826de188..4001f49055e 100644 --- a/sdk/objc/Framework/Native/src/audio/audio_device_ios.h +++ b/sdk/objc/Framework/Native/src/audio/audio_device_ios.h @@ -198,6 +198,9 @@ class AudioDeviceIOS : public AudioDeviceGeneric, // Closes and deletes the voice-processing I/O unit. void ShutdownPlayOrRecord(); + // Resets thread-checkers before a call is restarted. + void PrepareForNewStart(); + // Ensures that methods are called from the same thread as this object is // created on. rtc::ThreadChecker thread_checker_; diff --git a/sdk/objc/Framework/Native/src/audio/audio_device_ios.mm b/sdk/objc/Framework/Native/src/audio/audio_device_ios.mm index cf254869c09..3779c2552e4 100644 --- a/sdk/objc/Framework/Native/src/audio/audio_device_ios.mm +++ b/sdk/objc/Framework/Native/src/audio/audio_device_ios.mm @@ -497,15 +497,7 @@ static void LogDeviceInfo() { if (!audio_unit_->Stop()) { RTCLogError(@"Failed to stop the audio unit for interruption begin."); } else { - // The audio unit has been stopped but will be restarted when the - // interruption ends in HandleInterruptionEnd(). It will result in audio - // callbacks from a new native I/O thread which means that we must detach - // thread checkers here to be prepared for an upcoming new audio stream. - io_thread_checker_.DetachFromThread(); - // The audio device buffer must also be informed about the interrupted - // state so it can detach its thread checkers as well. - audio_device_buffer_->NativeAudioPlayoutInterrupted(); - audio_device_buffer_->NativeAudioRecordingInterrupted(); + PrepareForNewStart(); } } is_interrupted_ = true; @@ -587,6 +579,7 @@ static void LogDeviceInfo() { if (audio_unit_->GetState() == VoiceProcessingAudioUnit::kStarted) { audio_unit_->Stop(); restart_audio_unit = true; + PrepareForNewStart(); } if (audio_unit_->GetState() == VoiceProcessingAudioUnit::kInitialized) { audio_unit_->Uninitialize(); @@ -907,6 +900,21 @@ static void LogDeviceInfo() { [session unlockForConfiguration]; } +void AudioDeviceIOS::PrepareForNewStart() { + LOGI() << "PrepareForNewStart"; + // The audio unit has been stopped and preparations are needed for an upcoming + // restart. It will result in audio callbacks from a new native I/O thread + // which means that we must detach thread checkers here to be prepared for an + // upcoming new audio stream. + io_thread_checker_.DetachFromThread(); + // The audio device buffer must also be informed about the interrupted + // state so it can detach its thread checkers as well. + if (audio_device_buffer_) { + audio_device_buffer_->NativeAudioPlayoutInterrupted(); + audio_device_buffer_->NativeAudioRecordingInterrupted(); + } +} + bool AudioDeviceIOS::IsInterrupted() { return is_interrupted_; }