Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(956)

Unified Diff: webrtc/modules/audio_device/ios/audio_device_ios.mm

Issue 1822543002: Support delayed AudioUnit initialization. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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];
}

Powered by Google App Engine
This is Rietveld 408576698