| 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 860c1a280057d075ed50cd2641c8193ed29bb2a3..f6c339fed00de7edc263df84d520d1c877987f24 100644
|
| --- a/webrtc/modules/audio_device/ios/audio_device_ios.mm
|
| +++ b/webrtc/modules/audio_device/ios/audio_device_ios.mm
|
| @@ -191,8 +191,11 @@ int32_t AudioDeviceIOS::StartPlayout() {
|
| RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| RTC_DCHECK(play_is_initialized_);
|
| RTC_DCHECK(!playing_);
|
| - fine_audio_buffer_->ResetPlayout();
|
| - if (!recording_) {
|
| + if (fine_audio_buffer_) {
|
| + fine_audio_buffer_->ResetPlayout();
|
| + }
|
| + if (!recording_ &&
|
| + audio_unit_->GetState() == VoiceProcessingAudioUnit::kInitialized) {
|
| if (!audio_unit_->Start()) {
|
| RTCLogError(@"StartPlayout failed to start audio unit.");
|
| return -1;
|
| @@ -222,8 +225,11 @@ int32_t AudioDeviceIOS::StartRecording() {
|
| RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| RTC_DCHECK(rec_is_initialized_);
|
| RTC_DCHECK(!recording_);
|
| - fine_audio_buffer_->ResetRecord();
|
| - if (!playing_) {
|
| + if (fine_audio_buffer_) {
|
| + fine_audio_buffer_->ResetRecord();
|
| + }
|
| + if (!playing_ &&
|
| + audio_unit_->GetState() == VoiceProcessingAudioUnit::kInitialized) {
|
| if (!audio_unit_->Start()) {
|
| RTCLogError(@"StartRecording failed to start audio unit.");
|
| return -1;
|
| @@ -347,6 +353,18 @@ void AudioDeviceIOS::OnValidRouteChange() {
|
| rtc::Bind(&webrtc::AudioDeviceIOS::HandleValidRouteChange, this));
|
| }
|
|
|
| +void AudioDeviceIOS::OnConfiguredForWebRTC() {
|
| + RTC_DCHECK(async_invoker_);
|
| + RTC_DCHECK(thread_);
|
| + if (thread_->IsCurrent()) {
|
| + HandleValidRouteChange();
|
| + return;
|
| + }
|
| + async_invoker_->AsyncInvoke<void>(
|
| + thread_,
|
| + rtc::Bind(&webrtc::AudioDeviceIOS::HandleConfiguredForWebRTC, this));
|
| +}
|
| +
|
| OSStatus AudioDeviceIOS::OnDeliverRecordedData(
|
| AudioUnitRenderActionFlags* flags,
|
| const AudioTimeStamp* time_stamp,
|
| @@ -431,6 +449,7 @@ OSStatus AudioDeviceIOS::OnGetPlayoutData(AudioUnitRenderActionFlags* flags,
|
|
|
| void AudioDeviceIOS::HandleInterruptionBegin() {
|
| RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| RTCLog(@"Stopping the audio unit due to interruption begin.");
|
| if (!audio_unit_->Stop()) {
|
| RTCLogError(@"Failed to stop the audio unit.");
|
| @@ -440,6 +459,7 @@ void AudioDeviceIOS::HandleInterruptionBegin() {
|
|
|
| void AudioDeviceIOS::HandleInterruptionEnd() {
|
| RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| RTCLog(@"Starting the audio unit due to interruption end.");
|
| if (!audio_unit_->Start()) {
|
| RTCLogError(@"Failed to start the audio unit.");
|
| @@ -469,6 +489,39 @@ void AudioDeviceIOS::HandleValidRouteChange() {
|
| }
|
| }
|
|
|
| +void AudioDeviceIOS::HandleConfiguredForWebRTC() {
|
| + RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + // If we're not initialized we don't need to do anything. Audio unit will
|
| + // be initialized on initialization.
|
| + if (!rec_is_initialized_ && !play_is_initialized_)
|
| + return;
|
| +
|
| + // If we're initialized, we must have an audio unit.
|
| + RTC_DCHECK(audio_unit_);
|
| +
|
| + // Use configured audio session's settings to set up audio device buffer.
|
| + // TODO(tkchin): Use RTCAudioSessionConfiguration to pick up settings and
|
| + // pass it along.
|
| + SetupAudioBuffersForActiveAudioSession();
|
| +
|
| + // Initialize the audio unit. This will affect any existing audio playback.
|
| + if (!audio_unit_->Initialize(playout_parameters_.sample_rate())) {
|
| + RTCLogError(@"Failed to initialize audio unit after configuration.");
|
| + return;
|
| + }
|
| +
|
| + // If we haven't started playing or recording there's nothing more to do.
|
| + if (!playing_ && !recording_)
|
| + return;
|
| +
|
| + // We are in a play or record state, start the audio unit.
|
| + if (!audio_unit_->Start()) {
|
| + RTCLogError(@"Failed to start audio unit after configuration.");
|
| + return;
|
| + }
|
| +}
|
| +
|
| void AudioDeviceIOS::UpdateAudioDeviceBuffer() {
|
| LOGI() << "UpdateAudioDevicebuffer";
|
| // AttachAudioBuffer() is called at construction by the main class but check
|
| @@ -603,32 +656,35 @@ bool AudioDeviceIOS::RestartAudioUnit(float sample_rate) {
|
| bool AudioDeviceIOS::InitPlayOrRecord() {
|
| LOGI() << "InitPlayOrRecord";
|
|
|
| - // Use the correct audio session configuration for WebRTC.
|
| - // This will attempt to activate the audio session.
|
| + if (!CreateAudioUnit()) {
|
| + return false;
|
| + }
|
| +
|
| RTCAudioSession* session = [RTCAudioSession sharedInstance];
|
| + // Subscribe to audio session events.
|
| + [session pushDelegate:audio_session_observer_];
|
| +
|
| + // Lock the session to make configuration changes.
|
| [session lockForConfiguration];
|
| NSError* error = nil;
|
| - if (![session configureWebRTCSession:&error]) {
|
| - RTCLogError(@"Failed to configure WebRTC session: %@",
|
| - error.localizedDescription);
|
| + if (![session beginWebRTCSession:&error]) {
|
| [session unlockForConfiguration];
|
| + RTCLogError(@"Failed to begin WebRTC session: %@",
|
| + error.localizedDescription);
|
| return false;
|
| }
|
|
|
| - // Start observing audio session interruptions and route changes.
|
| - [session pushDelegate:audio_session_observer_];
|
| -
|
| - // Ensure that we got what what we asked for in our active audio session.
|
| - SetupAudioBuffersForActiveAudioSession();
|
| -
|
| - // Create, setup and initialize a new Voice-Processing I/O unit.
|
| - // TODO(tkchin): Delay the initialization when needed.
|
| - if (!CreateAudioUnit() ||
|
| - !audio_unit_->Initialize(playout_parameters_.sample_rate())) {
|
| - [session setActive:NO error:nil];
|
| + // If we are already configured properly, we can initialize the audio unit.
|
| + if (session.isConfiguredForWebRTC) {
|
| [session unlockForConfiguration];
|
| - return false;
|
| + SetupAudioBuffersForActiveAudioSession();
|
| + // Audio session has been marked ready for WebRTC so we can initialize the
|
| + // audio unit now.
|
| + audio_unit_->Initialize(playout_parameters_.sample_rate());
|
| + return true;
|
| }
|
| +
|
| + // Release the lock.
|
| [session unlockForConfiguration];
|
|
|
| return true;
|
| @@ -639,8 +695,6 @@ void AudioDeviceIOS::ShutdownPlayOrRecord() {
|
|
|
| // Close and delete the voice-processing I/O unit.
|
| if (audio_unit_) {
|
| - audio_unit_->Stop();
|
| - audio_unit_->Uninitialize();
|
| audio_unit_.reset();
|
| }
|
|
|
| @@ -651,7 +705,7 @@ void AudioDeviceIOS::ShutdownPlayOrRecord() {
|
| // All I/O should be stopped or paused prior to deactivating the audio
|
| // session, hence we deactivate as last action.
|
| [session lockForConfiguration];
|
| - [session setActive:NO error:nil];
|
| + [session endWebRTCSession:nil];
|
| [session unlockForConfiguration];
|
| }
|
|
|
|
|