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

Unified Diff: webrtc/modules/audio_device/ios/objc/RTCAudioSession.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/objc/RTCAudioSession.mm
diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm b/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm
index 05e9cb50c5070328323de70930956a06ad406ba3..c6e3677b8461751b7489dea445ff88cc27707356 100644
--- a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm
+++ b/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm
@@ -10,6 +10,7 @@
#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
+#include "webrtc/base/atomicops.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/modules/audio_device/ios/audio_device_ios.h"
@@ -27,20 +28,22 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
@implementation RTCAudioSession {
rtc::CriticalSection _crit;
AVAudioSession *_session;
- NSInteger _activationCount;
- NSInteger _lockRecursionCount;
+ volatile int _activationCount;
+ volatile int _lockRecursionCount;
+ volatile int _webRTCSessionCount;
BOOL _isActive;
BOOL _shouldDelayAudioConfiguration;
}
@synthesize session = _session;
@synthesize delegates = _delegates;
+@synthesize savedConfiguration = _savedConfiguration;
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
static RTCAudioSession *sharedInstance = nil;
dispatch_once(&onceToken, ^{
- sharedInstance = [[RTCAudioSession alloc] init];
+ sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
@@ -106,13 +109,13 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
}
- (BOOL)isLocked {
- @synchronized(self) {
- return _lockRecursionCount > 0;
- }
+ return _lockRecursionCount > 0;
}
- (void)setShouldDelayAudioConfiguration:(BOOL)shouldDelayAudioConfiguration {
@synchronized(self) {
+ // No one should be changing this while an audio device is active.
+ RTC_DCHECK(!self.isConfiguredForWebRTC);
if (_shouldDelayAudioConfiguration == shouldDelayAudioConfiguration) {
return;
}
@@ -126,6 +129,7 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
}
}
+// TODO(tkchin): Check for duplicates.
- (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate {
if (!delegate) {
return;
@@ -150,18 +154,14 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
- (void)lockForConfiguration {
_crit.Enter();
- @synchronized(self) {
- ++_lockRecursionCount;
- }
+ rtc::AtomicOps::Increment(&_lockRecursionCount);
}
- (void)unlockForConfiguration {
// Don't let threads other than the one that called lockForConfiguration
// unlock.
if (_crit.TryEnter()) {
- @synchronized(self) {
- --_lockRecursionCount;
- }
+ rtc::AtomicOps::Decrement(&_lockRecursionCount);
// One unlock for the tryLock, and another one to actually unlock. If this
// was called without anyone calling lock, we will hit an assertion.
_crit.Leave();
@@ -262,7 +262,7 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
if (![self checkLock:outError]) {
return NO;
}
- NSInteger activationCount = self.activationCount;
+ int activationCount = _activationCount;
if (!active && activationCount == 0) {
RTCLogWarning(@"Attempting to deactivate without prior activation.");
}
@@ -304,7 +304,7 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
if (!active) {
[self decrementActivationCount];
}
- RTCLog(@"Number of current activations: %ld", (long)self.activationCount);
+ RTCLog(@"Number of current activations: %d", _activationCount);
return success;
}
@@ -496,6 +496,22 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
}
}
+- (void)setSavedConfiguration:(RTCAudioSessionConfiguration *)configuration {
+ @synchronized(self) {
+ if (_savedConfiguration == configuration) {
+ return;
+ }
+ _savedConfiguration = configuration;
+ }
+}
+
+- (RTCAudioSessionConfiguration *)savedConfiguration {
+ @synchronized(self) {
+ return _savedConfiguration;
+ }
+}
+
+// TODO(tkchin): check for duplicates.
- (void)pushDelegate:(id<RTCAudioSessionDelegate>)delegate {
@synchronized(self) {
_delegates.insert(_delegates.begin(), delegate);
@@ -512,24 +528,22 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
}
}
-- (NSInteger)activationCount {
- @synchronized(self) {
- return _activationCount;
- }
+- (int)activationCount {
+ return _activationCount;
}
-- (NSInteger)incrementActivationCount {
+- (int)incrementActivationCount {
RTCLog(@"Incrementing activation count.");
- @synchronized(self) {
- return ++_activationCount;
- }
+ return rtc::AtomicOps::Increment(&_activationCount);
}
- (NSInteger)decrementActivationCount {
RTCLog(@"Decrementing activation count.");
- @synchronized(self) {
- return --_activationCount;
- }
+ return rtc::AtomicOps::Decrement(&_activationCount);
+}
+
+- (int)webRTCSessionCount {
+ return _webRTCSessionCount;
}
- (BOOL)checkLock:(NSError **)outError {
@@ -544,6 +558,99 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
return YES;
}
+- (BOOL)beginWebRTCSession:(NSError **)outError {
+ if (outError) {
+ *outError = nil;
+ }
+ if (![self checkLock:outError]) {
+ return NO;
+ }
+ NSInteger sessionCount = rtc::AtomicOps::Increment(&_webRTCSessionCount);
+ if (sessionCount > 1) {
+ // Should already be configured.
+ RTC_DCHECK(self.isConfiguredForWebRTC);
+ return YES;
+ }
+
+ // Only perform configuration steps once. Application might have already
+ // configured the session.
+ if (self.isConfiguredForWebRTC) {
+ // Nothing more to do, already configured.
+ return YES;
+ }
+
+ // If application has prevented automatic configuration, return here and wait
+ // for application to call configureWebRTCSession.
+ if (self.shouldDelayAudioConfiguration) {
+ [self notifyShouldConfigure];
+ return YES;
+ }
+
+ // Configure audio session.
+ NSError *error = nil;
+ if (![self configureWebRTCSession:&error]) {
+ RTCLogError(@"Error configuring audio session: %@",
+ error.localizedDescription);
+ if (outError) {
+ *outError = error;
+ }
+ return NO;
+ }
+
+ return YES;
+}
+
+- (BOOL)endWebRTCSession:(NSError **)outError {
+ if (outError) {
+ *outError = nil;
+ }
+ if (![self checkLock:outError]) {
+ return NO;
+ }
+ int sessionCount = rtc::AtomicOps::Decrement(&_webRTCSessionCount);
+ RTC_DCHECK_GE(sessionCount, 0);
+ if (sessionCount != 0) {
+ // Should still be configured.
+ RTC_DCHECK(self.isConfiguredForWebRTC);
+ return YES;
+ }
+
+ // Only unconfigure if application has not done it.
+ if (!self.isConfiguredForWebRTC) {
+ // Nothing more to do, already unconfigured.
+ return YES;
+ }
+
+ // If application has prevented automatic configuration, return here and wait
+ // for application to call unconfigureWebRTCSession.
+ if (self.shouldDelayAudioConfiguration) {
+ [self notifyShouldUnconfigure];
+ return YES;
+ }
+
+ // Unconfigure audio session.
+ NSError *error = nil;
+ if (![self unconfigureWebRTCSession:&error]) {
+ RTCLogError(@"Error unconfiguring audio session: %@",
+ error.localizedDescription);
+ if (outError) {
+ *outError = error;
+ }
+ return NO;
+ }
+
+ return YES;
+}
+
+- (NSError *)configurationErrorWithDescription:(NSString *)description {
+ NSDictionary* userInfo = @{
+ NSLocalizedDescriptionKey: description,
+ };
+ return [[NSError alloc] initWithDomain:kRTCAudioSessionErrorDomain
+ code:kRTCAudioSessionErrorConfiguration
+ userInfo:userInfo];
+}
+
- (void)updateAudioSessionAfterEvent {
BOOL shouldActivate = self.activationCount > 0;
AVAudioSessionSetActiveOptions options = shouldActivate ?
@@ -561,37 +668,87 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2;
- (void)notifyDidBeginInterruption {
for (auto delegate : self.delegates) {
- [delegate audioSessionDidBeginInterruption:self];
+ SEL sel = @selector(audioSessionDidBeginInterruption:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionDidBeginInterruption:self];
+ }
}
}
- (void)notifyDidEndInterruptionWithShouldResumeSession:
(BOOL)shouldResumeSession {
for (auto delegate : self.delegates) {
- [delegate audioSessionDidEndInterruption:self
- shouldResumeSession:shouldResumeSession];
+ SEL sel = @selector(audioSessionDidEndInterruption:shouldResumeSession:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionDidEndInterruption:self
+ shouldResumeSession:shouldResumeSession];
+ }
}
-
}
- (void)notifyDidChangeRouteWithReason:(AVAudioSessionRouteChangeReason)reason
previousRoute:(AVAudioSessionRouteDescription *)previousRoute {
for (auto delegate : self.delegates) {
- [delegate audioSessionDidChangeRoute:self
- reason:reason
- previousRoute:previousRoute];
+ SEL sel = @selector(audioSessionDidChangeRoute:reason:previousRoute:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionDidChangeRoute:self
+ reason:reason
+ previousRoute:previousRoute];
+ }
}
}
- (void)notifyMediaServicesWereLost {
for (auto delegate : self.delegates) {
- [delegate audioSessionMediaServicesWereLost:self];
+ SEL sel = @selector(audioSessionMediaServicesWereLost:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionMediaServicesWereLost:self];
+ }
}
}
- (void)notifyMediaServicesWereReset {
for (auto delegate : self.delegates) {
- [delegate audioSessionMediaServicesWereReset:self];
+ SEL sel = @selector(audioSessionMediaServicesWereReset:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionMediaServicesWereReset:self];
+ }
+ }
+}
+
+- (void)notifyShouldConfigure {
+ for (auto delegate : self.delegates) {
+ SEL sel = @selector(audioSessionShouldConfigure:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionShouldConfigure:self];
+ }
+ }
+}
+
+- (void)notifyShouldUnconfigure {
+ for (auto delegate : self.delegates) {
+ SEL sel = @selector(audioSessionShouldUnconfigure:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionShouldUnconfigure:self];
+ }
+ }
+}
+
+- (void)notifyDidConfigure {
+ for (auto delegate : self.delegates) {
+ SEL sel = @selector(audioSessionDidConfigure:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionDidConfigure:self];
+ }
+ }
+}
+
+- (void)notifyDidUnconfigure {
+ for (auto delegate : self.delegates) {
+ SEL sel = @selector(audioSessionDidUnconfigure:);
+ if ([delegate respondsToSelector:sel]) {
+ [delegate audioSessionDidUnconfigure:self];
+ }
}
}

Powered by Google App Engine
This is Rietveld 408576698