@@ -94,10 +94,11 @@ static void LogDeviceInfo() {
9494 : bypass_voice_processing_(bypass_voice_processing),
9595 audio_device_buffer_ (nullptr ),
9696 audio_unit_(nullptr ),
97+ recording_is_initialized_(false ),
9798 recording_(0 ),
99+ playout_is_initialized_(false ),
98100 playing_(0 ),
99101 initialized_(false ),
100- audio_is_initialized_(false ),
101102 is_interrupted_(false ),
102103 has_configured_session_(false ),
103104 num_detected_playout_glitches_(0 ),
@@ -176,48 +177,57 @@ static void LogDeviceInfo() {
176177 LOGI () << " InitPlayout" ;
177178 RTC_DCHECK_RUN_ON (thread_);
178179 RTC_DCHECK (initialized_);
179- RTC_DCHECK (!audio_is_initialized_ );
180+ RTC_DCHECK (!playout_is_initialized_ );
180181 RTC_DCHECK (!playing_.load ());
181- if (!audio_is_initialized_) {
182- if (!InitPlayOrRecord ()) {
182+ if (!recording_is_initialized_) {
183+ // recording not initialized yet, init with no input
184+ if (!InitPlayOrRecord (false )) {
183185 RTC_LOG_F (LS_ERROR) << " InitPlayOrRecord failed for InitPlayout!" ;
184186 return -1 ;
185187 }
186188 }
187- audio_is_initialized_ = true ;
189+
190+ playout_is_initialized_ = true ;
191+
188192 return 0 ;
189193}
190194
191195bool AudioDeviceIOS::PlayoutIsInitialized () const {
192196 RTC_DCHECK_RUN_ON (thread_);
193- return audio_is_initialized_ ;
197+ return playout_is_initialized_ ;
194198}
195199
196200bool AudioDeviceIOS::RecordingIsInitialized () const {
197201 RTC_DCHECK_RUN_ON (thread_);
198- return audio_is_initialized_ ;
202+ return recording_is_initialized_ ;
199203}
200204
201205int32_t AudioDeviceIOS::InitRecording () {
202206 LOGI () << " InitRecording" ;
203207 RTC_DCHECK_RUN_ON (thread_);
204208 RTC_DCHECK (initialized_);
205- RTC_DCHECK (!audio_is_initialized_ );
209+ RTC_DCHECK (!recording_is_initialized_ );
206210 RTC_DCHECK (!recording_.load ());
207- if (!audio_is_initialized_) {
208- if (!InitPlayOrRecord ()) {
211+ if (!playout_is_initialized_) {
212+ // playout not initialized yet, init with input
213+ if (!InitPlayOrRecord (true )) {
209214 RTC_LOG_F (LS_ERROR) << " InitPlayOrRecord failed for InitRecording!" ;
210215 return -1 ;
211216 }
217+ } else {
218+ // playout already initialized, restart audio unit with input
219+ RestartAudioUnit (true );
212220 }
213- audio_is_initialized_ = true ;
221+
222+ recording_is_initialized_ = true ;
223+
214224 return 0 ;
215225}
216226
217227int32_t AudioDeviceIOS::StartPlayout () {
218228 LOGI () << " StartPlayout" ;
219229 RTC_DCHECK_RUN_ON (thread_);
220- RTC_DCHECK (audio_is_initialized_ );
230+ RTC_DCHECK (playout_is_initialized_ );
221231 RTC_DCHECK (!playing_.load ());
222232 RTC_DCHECK (audio_unit_);
223233 if (fine_audio_buffer_) {
@@ -242,12 +252,13 @@ static void LogDeviceInfo() {
242252int32_t AudioDeviceIOS::StopPlayout () {
243253 LOGI () << " StopPlayout" ;
244254 RTC_DCHECK_RUN_ON (thread_);
245- if (!audio_is_initialized_ || !playing_.load ()) {
255+ if (!playout_is_initialized_ || !playing_.load ()) {
246256 return 0 ;
247257 }
248258 if (!recording_.load ()) {
249259 ShutdownPlayOrRecord ();
250- audio_is_initialized_ = false ;
260+
261+ recording_is_initialized_ = false ;
251262 }
252263 playing_.store (0 , std::memory_order_release);
253264
@@ -273,7 +284,7 @@ static void LogDeviceInfo() {
273284int32_t AudioDeviceIOS::StartRecording () {
274285 LOGI () << " StartRecording" ;
275286 RTC_DCHECK_RUN_ON (thread_);
276- RTC_DCHECK (audio_is_initialized_ );
287+ RTC_DCHECK (recording_is_initialized_ );
277288 RTC_DCHECK (!recording_.load ());
278289 RTC_DCHECK (audio_unit_);
279290 if (fine_audio_buffer_) {
@@ -296,12 +307,16 @@ static void LogDeviceInfo() {
296307int32_t AudioDeviceIOS::StopRecording () {
297308 LOGI () << " StopRecording" ;
298309 RTC_DCHECK_RUN_ON (thread_);
299- if (!audio_is_initialized_ || !recording_.load ()) {
310+ if (!recording_is_initialized_ || !recording_.load ()) {
300311 return 0 ;
301312 }
302313 if (!playing_.load ()) {
303314 ShutdownPlayOrRecord ();
304- audio_is_initialized_ = false ;
315+
316+ playout_is_initialized_ = false ;
317+ } else if (playout_is_initialized_) {
318+ // restart audio unit with no input
319+ RestartAudioUnit (false );
305320 }
306321 recording_.store (0 , std::memory_order_release);
307322 return 0 ;
@@ -360,11 +375,6 @@ static void LogDeviceInfo() {
360375 thread_->PostTask (SafeTask (safety_, [this] { HandleOutputVolumeChange (); }));
361376}
362377
363- void AudioDeviceIOS::OnChangedRecordingEnabled () {
364- RTC_DCHECK (thread_);
365- thread_->PostTask (SafeTask (safety_, [this] { HandleAudioSessionRecordingEnabledChange (); }));
366- }
367-
368378OSStatus AudioDeviceIOS::OnDeliverRecordedData (AudioUnitRenderActionFlags* flags,
369379 const AudioTimeStamp* time_stamp,
370380 UInt32 bus_number,
@@ -584,7 +594,7 @@ static void LogDeviceInfo() {
584594 SetupAudioBuffersForActiveAudioSession ();
585595
586596 // Initialize the audio unit again with the new sample rate.
587- if (!audio_unit_->Initialize (playout_parameters_.sample_rate ())) {
597+ if (!audio_unit_->Initialize (playout_parameters_.sample_rate (), recording_is_initialized_ )) {
588598 RTCLogError (@" Failed to initialize the audio unit with sample rate: %d " ,
589599 playout_parameters_.sample_rate ());
590600 return ;
@@ -638,59 +648,44 @@ static void LogDeviceInfo() {
638648 last_output_volume_change_time_ = rtc::TimeMillis ();
639649}
640650
641- void AudioDeviceIOS::HandleAudioSessionRecordingEnabledChange ( ) {
651+ bool AudioDeviceIOS::RestartAudioUnit ( bool enable_input ) {
642652 RTC_DCHECK_RUN_ON (&io_thread_checker_);
643653
644- LOGI () << " HandleAudioSessionRecordingEnabledChange " ;
654+ LOGI () << " RestartAudioUnit " ;
645655
646656 // If we don't have an audio unit yet, or the audio unit is uninitialized,
647657 // there is no work to do.
648658 if (!audio_unit_ || audio_unit_->GetState () < VoiceProcessingAudioUnit::kInitialized ) {
649- return ;
659+ return false ;
650660 }
651661
652- // The audio unit is already initialized or started.
653- // Check to see if the sample rate or buffer size has changed.
654- RTC_OBJC_TYPE (RTCAudioSession)* session = [RTC_OBJC_TYPE (RTCAudioSession) sharedInstance ];
655- const double session_sample_rate = session.sampleRate ;
656-
657- // Extra sanity check to ensure that the new sample rate is valid.
658- if (session_sample_rate <= 0.0 ) {
659- RTCLogError (@" Sample rate is invalid: %f " , session_sample_rate);
660- LOGI () << " Sample rate is invalid " << session_sample_rate;
661- return ;
662- }
663- // We need to adjust our format and buffer sizes.
664- // The stream format is about to be changed and it requires that we first
665- // stop and uninitialize the audio unit to deallocate its resources.
666- RTCLog (@" Stopping and uninitializing audio unit to adjust buffers." );
667662 bool restart_audio_unit = false ;
668663 if (audio_unit_->GetState () == VoiceProcessingAudioUnit::kStarted ) {
669664 audio_unit_->Stop ();
670- restart_audio_unit = true ;
671665 PrepareForNewStart ();
666+ restart_audio_unit = true ;
672667 }
668+
673669 if (audio_unit_->GetState () == VoiceProcessingAudioUnit::kInitialized ) {
674670 audio_unit_->Uninitialize ();
675671 }
676672
677- // Allocate new buffers given the new stream format .
678- SetupAudioBuffersForActiveAudioSession ();
673+ // Initialize the audio unit again with the same sample rate .
674+ const double sample_rate = playout_parameters_. sample_rate ();
679675
680- // Initialize the audio unit again with the new sample rate.
681- RTC_DCHECK_EQ (playout_parameters_.sample_rate (), session_sample_rate);
682- if (!audio_unit_->Initialize (session_sample_rate)) {
683- RTCLogError (@" Failed to initialize the audio unit with sample rate: %f " , session_sample_rate);
684- return ;
676+ if (!audio_unit_->Initialize (sample_rate, enable_input)) {
677+ RTCLogError (@" Failed to initialize the audio unit with sample rate: %f " , sample_rate);
678+ return false ;
685679 }
686680
687681 // Restart the audio unit if it was already running.
688682 if (restart_audio_unit && !audio_unit_->Start ()) {
689- RTCLogError (@" Failed to start audio unit with sample rate: %f " , session_sample_rate );
690- return ;
683+ RTCLogError (@" Failed to start audio unit with sample rate: %f " , sample_rate );
684+ return false ;
691685 }
692686
693687 LOGI () << " Successfully enabled audio unit for recording." ;
688+ return true ;
694689}
695690
696691void AudioDeviceIOS::UpdateAudioDeviceBuffer () {
@@ -786,7 +781,7 @@ static void LogDeviceInfo() {
786781
787782 // If we're not initialized we don't need to do anything. Audio unit will
788783 // be initialized on initialization.
789- if (!audio_is_initialized_ ) return ;
784+ if (!playout_is_initialized_ && !recording_is_initialized_ ) return ;
790785
791786 // If we're initialized, we must have an audio unit.
792787 RTC_DCHECK (audio_unit_);
@@ -824,7 +819,7 @@ static void LogDeviceInfo() {
824819 RTCLog (@" Initializing audio unit for UpdateAudioUnit" );
825820 ConfigureAudioSession ();
826821 SetupAudioBuffersForActiveAudioSession ();
827- if (!audio_unit_->Initialize (playout_parameters_.sample_rate ())) {
822+ if (!audio_unit_->Initialize (playout_parameters_.sample_rate (), recording_is_initialized_ )) {
828823 RTCLogError (@" Failed to initialize audio unit." );
829824 return ;
830825 }
@@ -914,7 +909,7 @@ static void LogDeviceInfo() {
914909 RTCLog (@" Unconfigured audio session." );
915910}
916911
917- bool AudioDeviceIOS::InitPlayOrRecord () {
912+ bool AudioDeviceIOS::InitPlayOrRecord (bool enable_input ) {
918913 LOGI () << " InitPlayOrRecord" ;
919914 RTC_DCHECK_RUN_ON (thread_);
920915
@@ -950,7 +945,7 @@ static void LogDeviceInfo() {
950945 return false ;
951946 }
952947 SetupAudioBuffersForActiveAudioSession ();
953- audio_unit_->Initialize (playout_parameters_.sample_rate ());
948+ audio_unit_->Initialize (playout_parameters_.sample_rate (), enable_input );
954949 }
955950
956951 // Release the lock.
0 commit comments