Skip to content

Commit 6566dd4

Browse files
committed
Rollback logic
1 parent fa864f3 commit 6566dd4

File tree

1 file changed

+87
-18
lines changed

1 file changed

+87
-18
lines changed

modules/audio_device/audio_engine_device.mm

Lines changed: 87 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,16 @@
16421642
RTC_DCHECK_RUN_ON(thread_);
16431643
RTC_DCHECK(engine_manual_input_ == nullptr);
16441644

1645+
std::vector<std::function<void()>> rollback_actions;
1646+
1647+
auto rollback = [&](int32_t result) {
1648+
for (auto& action : rollback_actions) {
1649+
action();
1650+
}
1651+
1652+
return result;
1653+
};
1654+
16451655
auto inputNode = [this, state]() {
16461656
RTC_DCHECK_RUN_ON(thread_);
16471657
RTC_DCHECK(engine_device_ != nil);
@@ -1656,6 +1666,9 @@
16561666
return engine_device_.outputNode;
16571667
};
16581668

1669+
// --------------------------------------------------------------------------------------------
1670+
// Step: Stop AVAudioEngine
1671+
//
16591672
if (state.prev.IsAnyRunning() &&
16601673
(!state.next.IsAnyRunning() || state.IsEngineRestartRequired() ||
16611674
state.DidBeginInterruption() || state.IsEngineRecreateRequired())) {
@@ -1677,39 +1690,54 @@
16771690
state.next.IsInputEnabled());
16781691
if (result != 0) {
16791692
LOGE() << "Call to OnEngineDidStop returned error: " << result;
1680-
return result;
1693+
return rollback(result);
16811694
}
16821695
}
16831696
}
16841697

1698+
// --------------------------------------------------------------------------------------------
1699+
// Step: Recreate AVAudioEngine
1700+
//
16851701
if (state.IsEngineRecreateRequired()) {
16861702
LOGI() << "Recreate required, releasing AVAudioEngine...";
16871703
if (observer_ != nullptr) {
16881704
int32_t result = observer_->OnEngineWillRelease(engine_device_);
16891705
if (result != 0) {
16901706
LOGE() << "Call to OnEngineWillRelease returned error: " << result;
1691-
return result;
1707+
return rollback(result);
16921708
}
16931709
}
16941710
engine_device_ = nil;
16951711
}
16961712

1713+
// --------------------------------------------------------------------------------------------
1714+
// Step: Create AVAudioEngine
1715+
//
16971716
if (state.next.IsAnyEnabled() &&
16981717
(!state.prev.IsAnyEnabled() || state.IsEngineRecreateRequired())) {
16991718
LOGI() << "Creating AVAudioEngine (device)...";
17001719
RTC_DCHECK(engine_device_ == nil);
17011720

17021721
engine_device_ = [[AVAudioEngine alloc] init];
17031722

1723+
rollback_actions.push_back([=]() {
1724+
RTC_DCHECK_RUN_ON(thread_);
1725+
LOGI() << "Rolling back create AVAudioEngine (device)...";
1726+
engine_device_ = nil;
1727+
});
1728+
17041729
if (observer_ != nullptr) {
17051730
int32_t result = observer_->OnEngineDidCreate(engine_device_);
17061731
if (result != 0) {
17071732
LOGE() << "Call to OnEngineDidCreate returned error: " << result;
1708-
return result;
1733+
return rollback(result);
17091734
}
17101735
}
17111736
}
17121737

1738+
// --------------------------------------------------------------------------------------------
1739+
// Step: Stop playout buffer
1740+
//
17131741
if (!state.next.IsOutputEnabled() && audio_device_buffer_->IsPlaying()) {
17141742
LOGI() << "Stopping Playout buffer...";
17151743
if (engine_device_ != nullptr) {
@@ -1719,6 +1747,9 @@
17191747
audio_device_buffer_->StopPlayout();
17201748
}
17211749

1750+
// --------------------------------------------------------------------------------------------
1751+
// Step: Stop recording buffer
1752+
//
17221753
if (!state.next.IsInputEnabled() && audio_device_buffer_->IsRecording()) {
17231754
LOGI() << "Stopping Record buffer...";
17241755
if (engine_device_ != nullptr) {
@@ -1728,17 +1759,23 @@
17281759
audio_device_buffer_->StopRecording();
17291760
}
17301761

1762+
// --------------------------------------------------------------------------------------------
1763+
// Step: Trigger "engine will enable" event
1764+
//
17311765
if (state.DidAnyEnable() && observer_ != nullptr) {
17321766
// Invoke here before configuring nodes. In iOS, session configuration is required before
17331767
// enabling AGC, muted talker etc.
17341768
int32_t result = observer_->OnEngineWillEnable(engine_device_, state.next.IsOutputEnabled(),
17351769
state.next.IsInputEnabled());
17361770
if (result != 0) {
17371771
LOGE() << "Call to OnEngineWillEnable returned error: " << result;
1738-
return result;
1772+
return rollback(result);
17391773
}
17401774
}
17411775

1776+
// --------------------------------------------------------------------------------------------
1777+
// Step: Configure device (macOS only)
1778+
//
17421779
#if TARGET_OS_OSX
17431780
if (state.next.IsAnyEnabled() &&
17441781
(!state.prev.IsAnyEnabled() || state.IsEngineRecreateRequired() ||
@@ -1781,7 +1818,9 @@
17811818
}
17821819
#endif
17831820

1784-
// Configure Voice-Processing I/O since it affects outputNode also.
1821+
// --------------------------------------------------------------------------------------------
1822+
// Step: Configure Voice-Processing I/O
1823+
//
17851824
if (state.next.IsInputEnabled() &&
17861825
inputNode().voiceProcessingEnabled != state.next.voice_processing_enabled) {
17871826
LOGI() << "setVoiceProcessingEnabled (input): " << state.next.voice_processing_enabled ? "YES"
@@ -1833,6 +1872,9 @@
18331872
}
18341873
}
18351874

1875+
// --------------------------------------------------------------------------------------------
1876+
// Step: Enable output
1877+
//
18361878
if (state.next.IsOutputEnabled() &&
18371879
(!state.prev.IsOutputEnabled() || state.IsEngineRecreateRequired())) {
18381880
LOGI() << "Enabling output for AVAudioEngine...";
@@ -1853,7 +1895,7 @@
18531895
if (output_node_format.sampleRate == 0 || output_node_format.channelCount == 0) {
18541896
LOGE() << "Output device not available, sampleRate=" << output_node_format.sampleRate
18551897
<< ", channelCount=" << output_node_format.channelCount;
1856-
return kAudioEnginePlayoutDeviceNotAvailableError;
1898+
return rollback(kAudioEnginePlayoutDeviceNotAvailableError);
18571899
}
18581900

18591901
AVAudioFormat* engine_output_format = [[AVAudioFormat alloc]
@@ -1908,7 +1950,7 @@
19081950
outputNode(), engine_output_format, context);
19091951
if (result != 0) {
19101952
LOGE() << "Call to OnEngineWillConnectOutput returned error: " << result;
1911-
return result;
1953+
return rollback(result);
19121954
}
19131955
}
19141956

@@ -1932,6 +1974,9 @@
19321974
}
19331975
}
19341976

1977+
// --------------------------------------------------------------------------------------------
1978+
// Step: Enable input
1979+
//
19351980
if (state.next.IsInputEnabled() &&
19361981
(!state.prev.IsInputEnabled() || state.IsEngineRecreateRequired())) {
19371982
LOGI() << "Enabling input for AVAudioEngine...";
@@ -1961,7 +2006,7 @@
19612006
if (input_node_format.sampleRate == 0 || input_node_format.channelCount == 0) {
19622007
LOGE() << "Input device not available, sampleRate=" << input_node_format.sampleRate
19632008
<< ", channelCount=" << input_node_format.channelCount;
1964-
return kAudioEngineRecordingDeviceNotAvailableError;
2009+
return rollback(kAudioEngineRecordingDeviceNotAvailableError);
19652010
}
19662011

19672012
input_mixer_node_ = [[AVAudioMixerNode alloc] init];
@@ -2039,7 +2084,7 @@
20392084
engine_device_, inputNode(), input_mixer_node_, engine_input_format, context);
20402085
if (result != 0) {
20412086
LOGE() << "Call to OnEngineWillConnectInput returned error: " << result;
2042-
return result;
2087+
return rollback(result);
20432088
}
20442089
}
20452090

@@ -2113,24 +2158,31 @@
21132158
converter_buffer_ = nil;
21142159
}
21152160

2161+
// --------------------------------------------------------------------------------------------
2162+
// Step: Trigger "engine did disable" event
2163+
//
21162164
if (state.DidAnyDisable() && observer_ != nullptr) {
21172165
int32_t result = observer_->OnEngineDidDisable(engine_device_, state.next.IsOutputEnabled(),
21182166
state.next.IsInputEnabled());
21192167
if (result != 0) {
21202168
LOGE() << "Call to OnEngineDidDisable returned error: " << result;
2121-
return result;
2169+
return rollback(result);
21222170
}
21232171
}
21242172

2125-
// Run-time mute toggling if vp mode.
2173+
// --------------------------------------------------------------------------------------------
2174+
// Step: Run-time mute toggling if vp mode.
2175+
//
21262176
if (state.next.mute_mode == MuteMode::VoiceProcessing && state.next.IsInputEnabled() &&
21272177
inputNode().voiceProcessingEnabled &&
21282178
inputNode().voiceProcessingInputMuted != state.next.input_muted) {
21292179
LOGI() << "Update mute (voice processing) runtime update" << state.next.input_muted;
21302180
inputNode().voiceProcessingInputMuted = state.next.input_muted;
21312181
}
21322182

2133-
// Run-time mute toggling if mixer mute mode.
2183+
// --------------------------------------------------------------------------------------------
2184+
// Step: Run-time mute toggling if mixer mute mode.
2185+
//
21342186
if (state.next.mute_mode == MuteMode::InputMixer && state.next.IsInputEnabled() &&
21352187
input_mixer_node_ != nil) {
21362188
// Only update if the volume has changed.
@@ -2141,6 +2193,9 @@
21412193
}
21422194
}
21432195

2196+
// --------------------------------------------------------------------------------------------
2197+
// Step: Configure other audio ducking
2198+
//
21442199
#if !TARGET_OS_TV
21452200
if (state.next.IsInputEnabled() && inputNode().voiceProcessingEnabled &&
21462201
(!state.prev.IsInputEnabled() ||
@@ -2160,21 +2215,27 @@
21602215
}
21612216
#endif
21622217

2163-
// Bypass
2218+
// --------------------------------------------------------------------------------------------
2219+
// Step: Bypass voice processing
2220+
//
21642221
if (state.next.IsInputEnabled() && inputNode().voiceProcessingEnabled &&
21652222
inputNode().voiceProcessingBypassed != state.next.voice_processing_bypassed) {
21662223
LOGI() << "setting voiceProcessingBypassed: " << state.next.voice_processing_bypassed;
21672224
inputNode().voiceProcessingBypassed = state.next.voice_processing_bypassed;
21682225
}
21692226

2170-
// AGC
2227+
// --------------------------------------------------------------------------------------------
2228+
// Step: Configure AGC
2229+
//
21712230
if (state.next.IsInputEnabled() && inputNode().voiceProcessingEnabled &&
21722231
inputNode().voiceProcessingAGCEnabled != state.next.voice_processing_agc_enabled) {
21732232
LOGI() << "setting voiceProcessingAGCEnabled: " << state.next.voice_processing_agc_enabled;
21742233
inputNode().voiceProcessingAGCEnabled = state.next.voice_processing_agc_enabled;
21752234
}
21762235

2177-
// Start playout buffer if output is running
2236+
// --------------------------------------------------------------------------------------------
2237+
// Step: Start playout buffer
2238+
//
21782239
if (state.next.IsOutputEnabled() && !audio_device_buffer_->IsPlaying()) {
21792240
if (engine_device_ != nullptr) {
21802241
// Rendering must be stopped first.
@@ -2185,7 +2246,9 @@
21852246
fine_audio_buffer_->ResetPlayout();
21862247
}
21872248

2188-
// Start recording buffer if input is running
2249+
// --------------------------------------------------------------------------------------------
2250+
// Step: Start recording buffer
2251+
//
21892252
if (state.next.IsInputEnabled() && !audio_device_buffer_->IsRecording()) {
21902253
if (engine_device_ != nullptr) {
21912254
// Rendering must be stopped first.
@@ -2196,6 +2259,9 @@
21962259
fine_audio_buffer_->ResetRecord();
21972260
}
21982261

2262+
// --------------------------------------------------------------------------------------------
2263+
// Step: Start engine
2264+
//
21992265
if (state.next.IsAnyRunning()) {
22002266
if (!state.prev.IsAnyRunning() || state.DidEndInterruption() ||
22012267
state.IsEngineRestartRequired() || state.IsEngineRecreateRequired()) {
@@ -2204,7 +2270,7 @@
22042270
state.next.IsInputEnabled());
22052271
if (result != 0) {
22062272
LOGE() << "Call to OnEngineWillStart returned error: " << result;
2207-
return result;
2273+
return rollback(result);
22082274
}
22092275
}
22102276

@@ -2261,14 +2327,17 @@
22612327
}
22622328
}
22632329

2330+
// --------------------------------------------------------------------------------------------
2331+
// Step: Release AVAudioEngine
2332+
//
22642333
if (state.prev.IsAnyEnabled() && !state.next.IsAnyEnabled()) {
22652334
RTC_DCHECK(engine_device_ != nullptr);
22662335

22672336
if (observer_ != nullptr) {
22682337
int32_t result = observer_->OnEngineWillRelease(engine_device_);
22692338
if (result != 0) {
22702339
LOGE() << "Call to OnEngineWillRelease returned error: " << result;
2271-
return result;
2340+
return rollback(result);
22722341
}
22732342
}
22742343

0 commit comments

Comments
 (0)