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

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

Issue 1709853002: Add RTCAudioSession proxy class. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 10 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 f6dee5b3cf82ff93862a35669be1878c200e577c..a0ea2a0f455378c68ecce9c79a317646f9224e5c 100644
--- a/webrtc/modules/audio_device/ios/audio_device_ios.mm
+++ b/webrtc/modules/audio_device/ios/audio_device_ios.mm
@@ -25,17 +25,9 @@
#include "webrtc/modules/audio_device/fine_audio_buffer.h"
#include "webrtc/modules/utility/include/helpers_ios.h"
-namespace webrtc {
-
-// Protects |g_audio_session_users|.
-static rtc::GlobalLockPod g_lock;
+#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
-// Counts number of users (=instances of this object) who needs an active
-// audio session. This variable is used to ensure that we only activate an audio
-// session for the first user and deactivate it for the last.
-// Member is static to ensure that the value is counted for all instances
-// and not per instance.
-static int g_audio_session_users GUARDED_BY(g_lock) = 0;
+namespace webrtc {
#define LOGI() LOG(LS_INFO) << "AudioDeviceIOS::"
@@ -97,10 +89,10 @@ using ios::CheckAndLogError;
// Verifies that the current audio session supports input audio and that the
// required category and mode are enabled.
-static bool VerifyAudioSession(AVAudioSession* session) {
+static bool VerifyAudioSession(RTCAudioSession* session) {
LOG(LS_INFO) << "VerifyAudioSession";
// Ensure that the device currently supports audio input.
- if (!session.isInputAvailable) {
+ if (!session.inputAvailable) {
LOG(LS_ERROR) << "No audio input path is available!";
return false;
}
@@ -121,93 +113,89 @@ static bool VerifyAudioSession(AVAudioSession* session) {
// Activates an audio session suitable for full duplex VoIP sessions when
// |activate| is true. Also sets the preferred sample rate and IO buffer
// duration. Deactivates an active audio session if |activate| is set to false.
-static bool ActivateAudioSession(AVAudioSession* session, bool activate)
- EXCLUSIVE_LOCKS_REQUIRED(g_lock) {
+static bool ActivateAudioSession(RTCAudioSession* session, bool activate) {
LOG(LS_INFO) << "ActivateAudioSession(" << activate << ")";
- @autoreleasepool {
- NSError* error = nil;
- BOOL success = NO;
-
- if (!activate) {
- // Deactivate the audio session using an extra option and then return.
- // AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation is used to
- // ensure that other audio sessions that were interrupted by our session
- // can return to their active state. It is recommended for VoIP apps to
- // use this option.
- success = [session
- setActive:NO
- withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
- error:&error];
- return CheckAndLogError(success, error);
- }
- // Go ahead and active our own audio session since |activate| is true.
- // Use a category which supports simultaneous recording and playback.
- // By default, using this category implies that our app’s audio is
- // nonmixable, hence activating the session will interrupt any other
- // audio sessions which are also nonmixable.
- if (session.category != AVAudioSessionCategoryPlayAndRecord) {
- error = nil;
- success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
- withOptions:AVAudioSessionCategoryOptionAllowBluetooth
- error:&error];
- RTC_DCHECK(CheckAndLogError(success, error));
- }
-
- // Specify mode for two-way voice communication (e.g. VoIP).
- if (session.mode != AVAudioSessionModeVoiceChat) {
- error = nil;
- success = [session setMode:AVAudioSessionModeVoiceChat error:&error];
- RTC_DCHECK(CheckAndLogError(success, error));
- }
+ NSError* error = nil;
+ BOOL success = NO;
+
+ [session lockForConfiguration];
+ if (!activate) {
+ success = [session setActive:NO
+ error:&error];
+ [session unlockForConfiguration];
+ return CheckAndLogError(success, error);
+ }
- // Set the session's sample rate or the hardware sample rate.
- // It is essential that we use the same sample rate as stream format
- // to ensure that the I/O unit does not have to do sample rate conversion.
+ // Go ahead and active our own audio session since |activate| is true.
+ // Use a category which supports simultaneous recording and playback.
+ // By default, using this category implies that our app’s audio is
+ // nonmixable, hence activating the session will interrupt any other
+ // audio sessions which are also nonmixable.
+ if (session.category != AVAudioSessionCategoryPlayAndRecord) {
error = nil;
- success =
- [session setPreferredSampleRate:kPreferredSampleRate error:&error];
+ success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
+ withOptions:AVAudioSessionCategoryOptionAllowBluetooth
+ error:&error];
RTC_DCHECK(CheckAndLogError(success, error));
+ }
- // Set the preferred audio I/O buffer duration, in seconds.
+ // Specify mode for two-way voice communication (e.g. VoIP).
+ if (session.mode != AVAudioSessionModeVoiceChat) {
error = nil;
- success = [session setPreferredIOBufferDuration:kPreferredIOBufferDuration
- error:&error];
+ success = [session setMode:AVAudioSessionModeVoiceChat error:&error];
RTC_DCHECK(CheckAndLogError(success, error));
+ }
- // Activate the audio session. Activation can fail if another active audio
- // session (e.g. phone call) has higher priority than ours.
- error = nil;
- success = [session setActive:YES error:&error];
- if (!CheckAndLogError(success, error)) {
- return false;
- }
-
- // Ensure that the active audio session has the correct category and mode.
- if (!VerifyAudioSession(session)) {
- LOG(LS_ERROR) << "Failed to verify audio session category and mode";
- return false;
- }
+ // Set the session's sample rate or the hardware sample rate.
+ // It is essential that we use the same sample rate as stream format
+ // to ensure that the I/O unit does not have to do sample rate conversion.
+ error = nil;
+ success =
+ [session setPreferredSampleRate:kPreferredSampleRate error:&error];
+ RTC_DCHECK(CheckAndLogError(success, error));
+
+ // Set the preferred audio I/O buffer duration, in seconds.
+ error = nil;
+ success = [session setPreferredIOBufferDuration:kPreferredIOBufferDuration
+ error:&error];
+ RTC_DCHECK(CheckAndLogError(success, error));
+
+ // Activate the audio session. Activation can fail if another active audio
+ // session (e.g. phone call) has higher priority than ours.
+ error = nil;
+ success = [session setActive:YES error:&error];
+ if (!CheckAndLogError(success, error)) {
+ [session unlockForConfiguration];
+ return false;
+ }
- // Try to set the preferred number of hardware audio channels. These calls
- // must be done after setting the audio session’s category and mode and
- // activating the session.
- // We try to use mono in both directions to save resources and format
- // conversions in the audio unit. Some devices does only support stereo;
- // e.g. wired headset on iPhone 6.
- // TODO(henrika): add support for stereo if needed.
- error = nil;
- success =
- [session setPreferredInputNumberOfChannels:kPreferredNumberOfChannels
- error:&error];
- RTC_DCHECK(CheckAndLogError(success, error));
- error = nil;
- success =
- [session setPreferredOutputNumberOfChannels:kPreferredNumberOfChannels
- error:&error];
- RTC_DCHECK(CheckAndLogError(success, error));
- return true;
+ // Ensure that the active audio session has the correct category and mode.
+ if (!VerifyAudioSession(session)) {
+ LOG(LS_ERROR) << "Failed to verify audio session category and mode";
+ [session unlockForConfiguration];
+ return false;
}
+
+ // Try to set the preferred number of hardware audio channels. These calls
+ // must be done after setting the audio session’s category and mode and
+ // activating the session.
+ // We try to use mono in both directions to save resources and format
+ // conversions in the audio unit. Some devices does only support stereo;
+ // e.g. wired headset on iPhone 6.
+ // TODO(henrika): add support for stereo if needed.
+ error = nil;
+ success =
+ [session setPreferredInputNumberOfChannels:kPreferredNumberOfChannels
+ error:&error];
+ RTC_DCHECK(CheckAndLogError(success, error));
+ error = nil;
+ success =
+ [session setPreferredOutputNumberOfChannels:kPreferredNumberOfChannels
+ error:&error];
+ RTC_DCHECK(CheckAndLogError(success, error));
+ [session unlockForConfiguration];
+ return true;
}
// An application can create more than one ADM and start audio streaming
@@ -215,24 +203,8 @@ static bool ActivateAudioSession(AVAudioSession* session, bool activate)
// session once (for the first one) and deactivate it once (for the last).
static bool ActivateAudioSession() {
LOGI() << "ActivateAudioSession";
- rtc::GlobalLockScope ls(&g_lock);
- if (g_audio_session_users == 0) {
- // The system provides an audio session object upon launch of an
- // application. However, we must initialize the session in order to
- // handle interruptions. Implicit initialization occurs when obtaining
- // a reference to the AVAudioSession object.
- AVAudioSession* session = [AVAudioSession sharedInstance];
- // Try to activate the audio session and ask for a set of preferred audio
- // parameters.
- if (!ActivateAudioSession(session, true)) {
- LOG(LS_ERROR) << "Failed to activate the audio session";
- return false;
- }
- LOG(LS_INFO) << "The audio session is now activated";
- }
- ++g_audio_session_users;
- LOG(LS_INFO) << "Number of audio session users: " << g_audio_session_users;
- return true;
+ RTCAudioSession* session = [RTCAudioSession sharedInstance];
+ return ActivateAudioSession(session, true);
}
// If more than one object is using the audio session, ensure that only the
@@ -240,18 +212,8 @@ static bool ActivateAudioSession() {
// only as needed and deactivate it when you are not using audio".
static bool DeactivateAudioSession() {
LOGI() << "DeactivateAudioSession";
- rtc::GlobalLockScope ls(&g_lock);
- if (g_audio_session_users == 1) {
- AVAudioSession* session = [AVAudioSession sharedInstance];
- if (!ActivateAudioSession(session, false)) {
- LOG(LS_ERROR) << "Failed to deactivate the audio session";
- return false;
- }
- LOG(LS_INFO) << "Our audio session is now deactivated";
- }
- --g_audio_session_users;
- LOG(LS_INFO) << "Number of audio session users: " << g_audio_session_users;
- return true;
+ RTCAudioSession* session = [RTCAudioSession sharedInstance];
+ return ActivateAudioSession(session, false);
}
#if !defined(NDEBUG)
@@ -344,13 +306,6 @@ int32_t AudioDeviceIOS::Terminate() {
StopPlayout();
StopRecording();
initialized_ = false;
- {
- rtc::GlobalLockScope ls(&g_lock);
- if (g_audio_session_users != 0) {
- LOG(LS_WARNING) << "Object is destructed with an active audio session";
- }
- RTC_DCHECK_GE(g_audio_session_users, 0);
- }
return 0;
}
@@ -456,7 +411,8 @@ int32_t AudioDeviceIOS::StopRecording() {
int32_t AudioDeviceIOS::SetLoudspeakerStatus(bool enable) {
LOGI() << "SetLoudspeakerStatus(" << enable << ")";
- AVAudioSession* session = [AVAudioSession sharedInstance];
+ RTCAudioSession* session = [RTCAudioSession sharedInstance];
+ [session lockForConfiguration];
NSString* category = session.category;
AVAudioSessionCategoryOptions options = session.categoryOptions;
// Respect old category options if category is
@@ -476,12 +432,13 @@ int32_t AudioDeviceIOS::SetLoudspeakerStatus(bool enable) {
withOptions:options
error:&error];
ios::CheckAndLogError(success, error);
+ [session unlockForConfiguration];
return (error == nil) ? 0 : -1;
}
int32_t AudioDeviceIOS::GetLoudspeakerStatus(bool& enabled) const {
LOGI() << "GetLoudspeakerStatus";
- AVAudioSession* session = [AVAudioSession sharedInstance];
+ RTCAudioSession* session = [RTCAudioSession sharedInstance];
AVAudioSessionCategoryOptions options = session.categoryOptions;
enabled = options & AVAudioSessionCategoryOptionDefaultToSpeaker;
return 0;
@@ -618,7 +575,7 @@ void AudioDeviceIOS::RegisterNotificationObservers() {
// Only restart audio for a valid route change and if the
// session sample rate has changed.
- AVAudioSession* session = [AVAudioSession sharedInstance];
+ RTCAudioSession* session = [RTCAudioSession sharedInstance];
const double session_sample_rate = session.sampleRate;
LOG(LS_INFO) << "session sample rate: " << session_sample_rate;
if (playout_parameters_.sample_rate() != session_sample_rate) {
@@ -672,7 +629,7 @@ void AudioDeviceIOS::UnregisterNotificationObservers() {
void AudioDeviceIOS::SetupAudioBuffersForActiveAudioSession() {
LOGI() << "SetupAudioBuffersForActiveAudioSession";
// Verify the current values once the audio session has been activated.
- AVAudioSession* session = [AVAudioSession sharedInstance];
+ RTCAudioSession* session = [RTCAudioSession sharedInstance];
LOG(LS_INFO) << " sample rate: " << session.sampleRate;
LOG(LS_INFO) << " IO buffer duration: " << session.IOBufferDuration;
LOG(LS_INFO) << " output channels: " << session.outputNumberOfChannels;
@@ -954,7 +911,7 @@ bool AudioDeviceIOS::InitPlayOrRecord() {
}
// Ensure that the active audio session has the correct category and mode.
- AVAudioSession* session = [AVAudioSession sharedInstance];
+ RTCAudioSession* session = [RTCAudioSession sharedInstance];
if (!VerifyAudioSession(session)) {
DeactivateAudioSession();
LOG(LS_ERROR) << "Failed to verify audio session category and mode";
« no previous file with comments | « webrtc/modules/audio_device/audio_device.gypi ('k') | webrtc/modules/audio_device/ios/objc/RTCAudioSession.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698