Chromium Code Reviews

Side by Side 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.
Jump to:
View unified diff |
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #if !defined(__has_feature) || !__has_feature(objc_arc) 11 #if !defined(__has_feature) || !__has_feature(objc_arc)
12 #error "This file requires ARC support." 12 #error "This file requires ARC support."
13 #endif 13 #endif
14 14
15 #import <AVFoundation/AVFoundation.h> 15 #import <AVFoundation/AVFoundation.h>
16 #import <Foundation/Foundation.h> 16 #import <Foundation/Foundation.h>
17 17
18 #include "webrtc/modules/audio_device/ios/audio_device_ios.h" 18 #include "webrtc/modules/audio_device/ios/audio_device_ios.h"
19 19
20 #include "webrtc/base/atomicops.h" 20 #include "webrtc/base/atomicops.h"
21 #include "webrtc/base/checks.h" 21 #include "webrtc/base/checks.h"
22 #include "webrtc/base/criticalsection.h" 22 #include "webrtc/base/criticalsection.h"
23 #include "webrtc/base/logging.h" 23 #include "webrtc/base/logging.h"
24 #include "webrtc/base/thread_annotations.h" 24 #include "webrtc/base/thread_annotations.h"
25 #include "webrtc/modules/audio_device/fine_audio_buffer.h" 25 #include "webrtc/modules/audio_device/fine_audio_buffer.h"
26 #include "webrtc/modules/utility/include/helpers_ios.h" 26 #include "webrtc/modules/utility/include/helpers_ios.h"
27 27
28 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
29
28 namespace webrtc { 30 namespace webrtc {
29 31
30 // Protects |g_audio_session_users|.
31 static rtc::GlobalLockPod g_lock;
32
33 // Counts number of users (=instances of this object) who needs an active
34 // audio session. This variable is used to ensure that we only activate an audio
35 // session for the first user and deactivate it for the last.
36 // Member is static to ensure that the value is counted for all instances
37 // and not per instance.
38 static int g_audio_session_users GUARDED_BY(g_lock) = 0;
39
40 #define LOGI() LOG(LS_INFO) << "AudioDeviceIOS::" 32 #define LOGI() LOG(LS_INFO) << "AudioDeviceIOS::"
41 33
42 #define LOG_AND_RETURN_IF_ERROR(error, message) \ 34 #define LOG_AND_RETURN_IF_ERROR(error, message) \
43 do { \ 35 do { \
44 OSStatus err = error; \ 36 OSStatus err = error; \
45 if (err) { \ 37 if (err) { \
46 LOG(LS_ERROR) << message << ": " << err; \ 38 LOG(LS_ERROR) << message << ": " << err; \
47 return false; \ 39 return false; \
48 } \ 40 } \
49 } while (0) 41 } while (0)
(...skipping 40 matching lines...)
90 // ADM instances. A fall-back solution is to allow multiple sequential calls 82 // ADM instances. A fall-back solution is to allow multiple sequential calls
91 // with as small delay between each. This factor sets the max number of allowed 83 // with as small delay between each. This factor sets the max number of allowed
92 // initialization attempts. 84 // initialization attempts.
93 const int kMaxNumberOfAudioUnitInitializeAttempts = 5; 85 const int kMaxNumberOfAudioUnitInitializeAttempts = 5;
94 86
95 87
96 using ios::CheckAndLogError; 88 using ios::CheckAndLogError;
97 89
98 // Verifies that the current audio session supports input audio and that the 90 // Verifies that the current audio session supports input audio and that the
99 // required category and mode are enabled. 91 // required category and mode are enabled.
100 static bool VerifyAudioSession(AVAudioSession* session) { 92 static bool VerifyAudioSession(RTCAudioSession* session) {
101 LOG(LS_INFO) << "VerifyAudioSession"; 93 LOG(LS_INFO) << "VerifyAudioSession";
102 // Ensure that the device currently supports audio input. 94 // Ensure that the device currently supports audio input.
103 if (!session.isInputAvailable) { 95 if (!session.inputAvailable) {
104 LOG(LS_ERROR) << "No audio input path is available!"; 96 LOG(LS_ERROR) << "No audio input path is available!";
105 return false; 97 return false;
106 } 98 }
107 99
108 // Ensure that the required category and mode are actually activated. 100 // Ensure that the required category and mode are actually activated.
109 if (![session.category isEqualToString:AVAudioSessionCategoryPlayAndRecord]) { 101 if (![session.category isEqualToString:AVAudioSessionCategoryPlayAndRecord]) {
110 LOG(LS_ERROR) 102 LOG(LS_ERROR)
111 << "Failed to set category to AVAudioSessionCategoryPlayAndRecord"; 103 << "Failed to set category to AVAudioSessionCategoryPlayAndRecord";
112 return false; 104 return false;
113 } 105 }
114 if (![session.mode isEqualToString:AVAudioSessionModeVoiceChat]) { 106 if (![session.mode isEqualToString:AVAudioSessionModeVoiceChat]) {
115 LOG(LS_ERROR) << "Failed to set mode to AVAudioSessionModeVoiceChat"; 107 LOG(LS_ERROR) << "Failed to set mode to AVAudioSessionModeVoiceChat";
116 return false; 108 return false;
117 } 109 }
118 return true; 110 return true;
119 } 111 }
120 112
121 // Activates an audio session suitable for full duplex VoIP sessions when 113 // Activates an audio session suitable for full duplex VoIP sessions when
122 // |activate| is true. Also sets the preferred sample rate and IO buffer 114 // |activate| is true. Also sets the preferred sample rate and IO buffer
123 // duration. Deactivates an active audio session if |activate| is set to false. 115 // duration. Deactivates an active audio session if |activate| is set to false.
124 static bool ActivateAudioSession(AVAudioSession* session, bool activate) 116 static bool ActivateAudioSession(RTCAudioSession* session, bool activate) {
125 EXCLUSIVE_LOCKS_REQUIRED(g_lock) {
126 LOG(LS_INFO) << "ActivateAudioSession(" << activate << ")"; 117 LOG(LS_INFO) << "ActivateAudioSession(" << activate << ")";
127 @autoreleasepool {
128 NSError* error = nil;
129 BOOL success = NO;
130 118
131 if (!activate) { 119 NSError* error = nil;
132 // Deactivate the audio session using an extra option and then return. 120 BOOL success = NO;
133 // AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation is used to
134 // ensure that other audio sessions that were interrupted by our session
135 // can return to their active state. It is recommended for VoIP apps to
136 // use this option.
137 success = [session
138 setActive:NO
139 withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
140 error:&error];
141 return CheckAndLogError(success, error);
142 }
143 121
144 // Go ahead and active our own audio session since |activate| is true. 122 [session lockForConfiguration];
145 // Use a category which supports simultaneous recording and playback. 123 if (!activate) {
146 // By default, using this category implies that our app’s audio is 124 success = [session setActive:NO
147 // nonmixable, hence activating the session will interrupt any other 125 error:&error];
148 // audio sessions which are also nonmixable. 126 [session unlockForConfiguration];
149 if (session.category != AVAudioSessionCategoryPlayAndRecord) { 127 return CheckAndLogError(success, error);
150 error = nil; 128 }
151 success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
152 withOptions:AVAudioSessionCategoryOptionAllowBluetooth
153 error:&error];
154 RTC_DCHECK(CheckAndLogError(success, error));
155 }
156 129
157 // Specify mode for two-way voice communication (e.g. VoIP). 130 // Go ahead and active our own audio session since |activate| is true.
158 if (session.mode != AVAudioSessionModeVoiceChat) { 131 // Use a category which supports simultaneous recording and playback.
159 error = nil; 132 // By default, using this category implies that our app’s audio is
160 success = [session setMode:AVAudioSessionModeVoiceChat error:&error]; 133 // nonmixable, hence activating the session will interrupt any other
161 RTC_DCHECK(CheckAndLogError(success, error)); 134 // audio sessions which are also nonmixable.
162 } 135 if (session.category != AVAudioSessionCategoryPlayAndRecord) {
136 error = nil;
137 success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
138 withOptions:AVAudioSessionCategoryOptionAllowBluetooth
139 error:&error];
140 RTC_DCHECK(CheckAndLogError(success, error));
141 }
163 142
164 // Set the session's sample rate or the hardware sample rate. 143 // Specify mode for two-way voice communication (e.g. VoIP).
165 // It is essential that we use the same sample rate as stream format 144 if (session.mode != AVAudioSessionModeVoiceChat) {
166 // to ensure that the I/O unit does not have to do sample rate conversion.
167 error = nil; 145 error = nil;
168 success = 146 success = [session setMode:AVAudioSessionModeVoiceChat error:&error];
169 [session setPreferredSampleRate:kPreferredSampleRate error:&error];
170 RTC_DCHECK(CheckAndLogError(success, error)); 147 RTC_DCHECK(CheckAndLogError(success, error));
148 }
171 149
172 // Set the preferred audio I/O buffer duration, in seconds. 150 // Set the session's sample rate or the hardware sample rate.
173 error = nil; 151 // It is essential that we use the same sample rate as stream format
174 success = [session setPreferredIOBufferDuration:kPreferredIOBufferDuration 152 // to ensure that the I/O unit does not have to do sample rate conversion.
175 error:&error]; 153 error = nil;
176 RTC_DCHECK(CheckAndLogError(success, error)); 154 success =
155 [session setPreferredSampleRate:kPreferredSampleRate error:&error];
156 RTC_DCHECK(CheckAndLogError(success, error));
177 157
178 // Activate the audio session. Activation can fail if another active audio 158 // Set the preferred audio I/O buffer duration, in seconds.
179 // session (e.g. phone call) has higher priority than ours. 159 error = nil;
180 error = nil; 160 success = [session setPreferredIOBufferDuration:kPreferredIOBufferDuration
181 success = [session setActive:YES error:&error]; 161 error:&error];
182 if (!CheckAndLogError(success, error)) { 162 RTC_DCHECK(CheckAndLogError(success, error));
183 return false;
184 }
185 163
186 // Ensure that the active audio session has the correct category and mode. 164 // Activate the audio session. Activation can fail if another active audio
187 if (!VerifyAudioSession(session)) { 165 // session (e.g. phone call) has higher priority than ours.
188 LOG(LS_ERROR) << "Failed to verify audio session category and mode"; 166 error = nil;
189 return false; 167 success = [session setActive:YES error:&error];
190 } 168 if (!CheckAndLogError(success, error)) {
169 [session unlockForConfiguration];
170 return false;
171 }
191 172
192 // Try to set the preferred number of hardware audio channels. These calls 173 // Ensure that the active audio session has the correct category and mode.
193 // must be done after setting the audio session’s category and mode and 174 if (!VerifyAudioSession(session)) {
194 // activating the session. 175 LOG(LS_ERROR) << "Failed to verify audio session category and mode";
195 // We try to use mono in both directions to save resources and format 176 [session unlockForConfiguration];
196 // conversions in the audio unit. Some devices does only support stereo; 177 return false;
197 // e.g. wired headset on iPhone 6.
198 // TODO(henrika): add support for stereo if needed.
199 error = nil;
200 success =
201 [session setPreferredInputNumberOfChannels:kPreferredNumberOfChannels
202 error:&error];
203 RTC_DCHECK(CheckAndLogError(success, error));
204 error = nil;
205 success =
206 [session setPreferredOutputNumberOfChannels:kPreferredNumberOfChannels
207 error:&error];
208 RTC_DCHECK(CheckAndLogError(success, error));
209 return true;
210 } 178 }
179
180 // Try to set the preferred number of hardware audio channels. These calls
181 // must be done after setting the audio session’s category and mode and
182 // activating the session.
183 // We try to use mono in both directions to save resources and format
184 // conversions in the audio unit. Some devices does only support stereo;
185 // e.g. wired headset on iPhone 6.
186 // TODO(henrika): add support for stereo if needed.
187 error = nil;
188 success =
189 [session setPreferredInputNumberOfChannels:kPreferredNumberOfChannels
190 error:&error];
191 RTC_DCHECK(CheckAndLogError(success, error));
192 error = nil;
193 success =
194 [session setPreferredOutputNumberOfChannels:kPreferredNumberOfChannels
195 error:&error];
196 RTC_DCHECK(CheckAndLogError(success, error));
197 [session unlockForConfiguration];
198 return true;
211 } 199 }
212 200
213 // An application can create more than one ADM and start audio streaming 201 // An application can create more than one ADM and start audio streaming
214 // for all of them. It is essential that we only activate the app's audio 202 // for all of them. It is essential that we only activate the app's audio
215 // session once (for the first one) and deactivate it once (for the last). 203 // session once (for the first one) and deactivate it once (for the last).
216 static bool ActivateAudioSession() { 204 static bool ActivateAudioSession() {
217 LOGI() << "ActivateAudioSession"; 205 LOGI() << "ActivateAudioSession";
218 rtc::GlobalLockScope ls(&g_lock); 206 RTCAudioSession* session = [RTCAudioSession sharedInstance];
219 if (g_audio_session_users == 0) { 207 return ActivateAudioSession(session, true);
220 // The system provides an audio session object upon launch of an
221 // application. However, we must initialize the session in order to
222 // handle interruptions. Implicit initialization occurs when obtaining
223 // a reference to the AVAudioSession object.
224 AVAudioSession* session = [AVAudioSession sharedInstance];
225 // Try to activate the audio session and ask for a set of preferred audio
226 // parameters.
227 if (!ActivateAudioSession(session, true)) {
228 LOG(LS_ERROR) << "Failed to activate the audio session";
229 return false;
230 }
231 LOG(LS_INFO) << "The audio session is now activated";
232 }
233 ++g_audio_session_users;
234 LOG(LS_INFO) << "Number of audio session users: " << g_audio_session_users;
235 return true;
236 } 208 }
237 209
238 // If more than one object is using the audio session, ensure that only the 210 // If more than one object is using the audio session, ensure that only the
239 // last object deactivates. Apple recommends: "activate your audio session 211 // last object deactivates. Apple recommends: "activate your audio session
240 // only as needed and deactivate it when you are not using audio". 212 // only as needed and deactivate it when you are not using audio".
241 static bool DeactivateAudioSession() { 213 static bool DeactivateAudioSession() {
242 LOGI() << "DeactivateAudioSession"; 214 LOGI() << "DeactivateAudioSession";
243 rtc::GlobalLockScope ls(&g_lock); 215 RTCAudioSession* session = [RTCAudioSession sharedInstance];
244 if (g_audio_session_users == 1) { 216 return ActivateAudioSession(session, false);
245 AVAudioSession* session = [AVAudioSession sharedInstance];
246 if (!ActivateAudioSession(session, false)) {
247 LOG(LS_ERROR) << "Failed to deactivate the audio session";
248 return false;
249 }
250 LOG(LS_INFO) << "Our audio session is now deactivated";
251 }
252 --g_audio_session_users;
253 LOG(LS_INFO) << "Number of audio session users: " << g_audio_session_users;
254 return true;
255 } 217 }
256 218
257 #if !defined(NDEBUG) 219 #if !defined(NDEBUG)
258 // Helper method for printing out an AudioStreamBasicDescription structure. 220 // Helper method for printing out an AudioStreamBasicDescription structure.
259 static void LogABSD(AudioStreamBasicDescription absd) { 221 static void LogABSD(AudioStreamBasicDescription absd) {
260 char formatIDString[5]; 222 char formatIDString[5];
261 UInt32 formatID = CFSwapInt32HostToBig(absd.mFormatID); 223 UInt32 formatID = CFSwapInt32HostToBig(absd.mFormatID);
262 bcopy(&formatID, formatIDString, 4); 224 bcopy(&formatID, formatIDString, 4);
263 formatIDString[4] = '\0'; 225 formatIDString[4] = '\0';
264 LOG(LS_INFO) << "LogABSD"; 226 LOG(LS_INFO) << "LogABSD";
(...skipping 72 matching lines...)
337 299
338 int32_t AudioDeviceIOS::Terminate() { 300 int32_t AudioDeviceIOS::Terminate() {
339 LOGI() << "Terminate"; 301 LOGI() << "Terminate";
340 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 302 RTC_DCHECK(thread_checker_.CalledOnValidThread());
341 if (!initialized_) { 303 if (!initialized_) {
342 return 0; 304 return 0;
343 } 305 }
344 StopPlayout(); 306 StopPlayout();
345 StopRecording(); 307 StopRecording();
346 initialized_ = false; 308 initialized_ = false;
347 {
348 rtc::GlobalLockScope ls(&g_lock);
349 if (g_audio_session_users != 0) {
350 LOG(LS_WARNING) << "Object is destructed with an active audio session";
351 }
352 RTC_DCHECK_GE(g_audio_session_users, 0);
353 }
354 return 0; 309 return 0;
355 } 310 }
356 311
357 int32_t AudioDeviceIOS::InitPlayout() { 312 int32_t AudioDeviceIOS::InitPlayout() {
358 LOGI() << "InitPlayout"; 313 LOGI() << "InitPlayout";
359 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 314 RTC_DCHECK(thread_checker_.CalledOnValidThread());
360 RTC_DCHECK(initialized_); 315 RTC_DCHECK(initialized_);
361 RTC_DCHECK(!play_is_initialized_); 316 RTC_DCHECK(!play_is_initialized_);
362 RTC_DCHECK(!playing_); 317 RTC_DCHECK(!playing_);
363 if (!rec_is_initialized_) { 318 if (!rec_is_initialized_) {
(...skipping 85 matching lines...)
449 } 404 }
450 rec_is_initialized_ = false; 405 rec_is_initialized_ = false;
451 rtc::AtomicOps::ReleaseStore(&recording_, 0); 406 rtc::AtomicOps::ReleaseStore(&recording_, 0);
452 return 0; 407 return 0;
453 } 408 }
454 409
455 // Change the default receiver playout route to speaker. 410 // Change the default receiver playout route to speaker.
456 int32_t AudioDeviceIOS::SetLoudspeakerStatus(bool enable) { 411 int32_t AudioDeviceIOS::SetLoudspeakerStatus(bool enable) {
457 LOGI() << "SetLoudspeakerStatus(" << enable << ")"; 412 LOGI() << "SetLoudspeakerStatus(" << enable << ")";
458 413
459 AVAudioSession* session = [AVAudioSession sharedInstance]; 414 RTCAudioSession* session = [RTCAudioSession sharedInstance];
415 [session lockForConfiguration];
460 NSString* category = session.category; 416 NSString* category = session.category;
461 AVAudioSessionCategoryOptions options = session.categoryOptions; 417 AVAudioSessionCategoryOptions options = session.categoryOptions;
462 // Respect old category options if category is 418 // Respect old category options if category is
463 // AVAudioSessionCategoryPlayAndRecord. Otherwise reset it since old options 419 // AVAudioSessionCategoryPlayAndRecord. Otherwise reset it since old options
464 // might not be valid for this category. 420 // might not be valid for this category.
465 if ([category isEqualToString:AVAudioSessionCategoryPlayAndRecord]) { 421 if ([category isEqualToString:AVAudioSessionCategoryPlayAndRecord]) {
466 if (enable) { 422 if (enable) {
467 options |= AVAudioSessionCategoryOptionDefaultToSpeaker; 423 options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
468 } else { 424 } else {
469 options &= ~AVAudioSessionCategoryOptionDefaultToSpeaker; 425 options &= ~AVAudioSessionCategoryOptionDefaultToSpeaker;
470 } 426 }
471 } else { 427 } else {
472 options = AVAudioSessionCategoryOptionDefaultToSpeaker; 428 options = AVAudioSessionCategoryOptionDefaultToSpeaker;
473 } 429 }
474 NSError* error = nil; 430 NSError* error = nil;
475 BOOL success = [session setCategory:AVAudioSessionCategoryPlayAndRecord 431 BOOL success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
476 withOptions:options 432 withOptions:options
477 error:&error]; 433 error:&error];
478 ios::CheckAndLogError(success, error); 434 ios::CheckAndLogError(success, error);
435 [session unlockForConfiguration];
479 return (error == nil) ? 0 : -1; 436 return (error == nil) ? 0 : -1;
480 } 437 }
481 438
482 int32_t AudioDeviceIOS::GetLoudspeakerStatus(bool& enabled) const { 439 int32_t AudioDeviceIOS::GetLoudspeakerStatus(bool& enabled) const {
483 LOGI() << "GetLoudspeakerStatus"; 440 LOGI() << "GetLoudspeakerStatus";
484 AVAudioSession* session = [AVAudioSession sharedInstance]; 441 RTCAudioSession* session = [RTCAudioSession sharedInstance];
485 AVAudioSessionCategoryOptions options = session.categoryOptions; 442 AVAudioSessionCategoryOptions options = session.categoryOptions;
486 enabled = options & AVAudioSessionCategoryOptionDefaultToSpeaker; 443 enabled = options & AVAudioSessionCategoryOptionDefaultToSpeaker;
487 return 0; 444 return 0;
488 } 445 }
489 446
490 int32_t AudioDeviceIOS::PlayoutDelay(uint16_t& delayMS) const { 447 int32_t AudioDeviceIOS::PlayoutDelay(uint16_t& delayMS) const {
491 delayMS = kFixedPlayoutDelayEstimate; 448 delayMS = kFixedPlayoutDelayEstimate;
492 return 0; 449 return 0;
493 } 450 }
494 451
(...skipping 116 matching lines...)
611 if (valid_route_change) { 568 if (valid_route_change) {
612 // Log previous route configuration. 569 // Log previous route configuration.
613 AVAudioSessionRouteDescription* prev_route = 570 AVAudioSessionRouteDescription* prev_route =
614 notification.userInfo[AVAudioSessionRouteChangePreviousRouteKey]; 571 notification.userInfo[AVAudioSessionRouteChangePreviousRouteKey];
615 LOG(LS_INFO) << "Previous route:"; 572 LOG(LS_INFO) << "Previous route:";
616 LOG(LS_INFO) << ios::StdStringFromNSString( 573 LOG(LS_INFO) << ios::StdStringFromNSString(
617 [NSString stringWithFormat:@"%@", prev_route]); 574 [NSString stringWithFormat:@"%@", prev_route]);
618 575
619 // Only restart audio for a valid route change and if the 576 // Only restart audio for a valid route change and if the
620 // session sample rate has changed. 577 // session sample rate has changed.
621 AVAudioSession* session = [AVAudioSession sharedInstance]; 578 RTCAudioSession* session = [RTCAudioSession sharedInstance];
622 const double session_sample_rate = session.sampleRate; 579 const double session_sample_rate = session.sampleRate;
623 LOG(LS_INFO) << "session sample rate: " << session_sample_rate; 580 LOG(LS_INFO) << "session sample rate: " << session_sample_rate;
624 if (playout_parameters_.sample_rate() != session_sample_rate) { 581 if (playout_parameters_.sample_rate() != session_sample_rate) {
625 if (!RestartAudioUnitWithNewFormat(session_sample_rate)) { 582 if (!RestartAudioUnitWithNewFormat(session_sample_rate)) {
626 LOG(LS_ERROR) << "Audio restart failed"; 583 LOG(LS_ERROR) << "Audio restart failed";
627 } 584 }
628 } 585 }
629 } 586 }
630 }; 587 };
631 588
(...skipping 33 matching lines...)
665 if (route_change_observer_ != nullptr) { 622 if (route_change_observer_ != nullptr) {
666 id observer = (__bridge_transfer id)route_change_observer_; 623 id observer = (__bridge_transfer id)route_change_observer_;
667 [center removeObserver:observer]; 624 [center removeObserver:observer];
668 route_change_observer_ = nullptr; 625 route_change_observer_ = nullptr;
669 } 626 }
670 } 627 }
671 628
672 void AudioDeviceIOS::SetupAudioBuffersForActiveAudioSession() { 629 void AudioDeviceIOS::SetupAudioBuffersForActiveAudioSession() {
673 LOGI() << "SetupAudioBuffersForActiveAudioSession"; 630 LOGI() << "SetupAudioBuffersForActiveAudioSession";
674 // Verify the current values once the audio session has been activated. 631 // Verify the current values once the audio session has been activated.
675 AVAudioSession* session = [AVAudioSession sharedInstance]; 632 RTCAudioSession* session = [RTCAudioSession sharedInstance];
676 LOG(LS_INFO) << " sample rate: " << session.sampleRate; 633 LOG(LS_INFO) << " sample rate: " << session.sampleRate;
677 LOG(LS_INFO) << " IO buffer duration: " << session.IOBufferDuration; 634 LOG(LS_INFO) << " IO buffer duration: " << session.IOBufferDuration;
678 LOG(LS_INFO) << " output channels: " << session.outputNumberOfChannels; 635 LOG(LS_INFO) << " output channels: " << session.outputNumberOfChannels;
679 LOG(LS_INFO) << " input channels: " << session.inputNumberOfChannels; 636 LOG(LS_INFO) << " input channels: " << session.inputNumberOfChannels;
680 LOG(LS_INFO) << " output latency: " << session.outputLatency; 637 LOG(LS_INFO) << " output latency: " << session.outputLatency;
681 LOG(LS_INFO) << " input latency: " << session.inputLatency; 638 LOG(LS_INFO) << " input latency: " << session.inputLatency;
682 639
683 // Log a warning message for the case when we are unable to set the preferred 640 // Log a warning message for the case when we are unable to set the preferred
684 // hardware sample rate but continue and use the non-ideal sample rate after 641 // hardware sample rate but continue and use the non-ideal sample rate after
685 // reinitializing the audio parameters. Most BT headsets only support 8kHz or 642 // reinitializing the audio parameters. Most BT headsets only support 8kHz or
(...skipping 261 matching lines...)
947 } 904 }
948 905
949 bool AudioDeviceIOS::InitPlayOrRecord() { 906 bool AudioDeviceIOS::InitPlayOrRecord() {
950 LOGI() << "InitPlayOrRecord"; 907 LOGI() << "InitPlayOrRecord";
951 // Activate the audio session if not already activated. 908 // Activate the audio session if not already activated.
952 if (!ActivateAudioSession()) { 909 if (!ActivateAudioSession()) {
953 return false; 910 return false;
954 } 911 }
955 912
956 // Ensure that the active audio session has the correct category and mode. 913 // Ensure that the active audio session has the correct category and mode.
957 AVAudioSession* session = [AVAudioSession sharedInstance]; 914 RTCAudioSession* session = [RTCAudioSession sharedInstance];
958 if (!VerifyAudioSession(session)) { 915 if (!VerifyAudioSession(session)) {
959 DeactivateAudioSession(); 916 DeactivateAudioSession();
960 LOG(LS_ERROR) << "Failed to verify audio session category and mode"; 917 LOG(LS_ERROR) << "Failed to verify audio session category and mode";
961 return false; 918 return false;
962 } 919 }
963 920
964 // Start observing audio session interruptions and route changes. 921 // Start observing audio session interruptions and route changes.
965 RegisterNotificationObservers(); 922 RegisterNotificationObservers();
966 923
967 // Ensure that we got what what we asked for in our active audio session. 924 // Ensure that we got what what we asked for in our active audio session.
(...skipping 135 matching lines...)
1103 // Read decoded 16-bit PCM samples from WebRTC (using a size that matches 1060 // Read decoded 16-bit PCM samples from WebRTC (using a size that matches
1104 // the native I/O audio unit) to a preallocated intermediate buffer and 1061 // the native I/O audio unit) to a preallocated intermediate buffer and
1105 // copy the result to the audio buffer in the |io_data| destination. 1062 // copy the result to the audio buffer in the |io_data| destination.
1106 SInt8* source = playout_audio_buffer_.get(); 1063 SInt8* source = playout_audio_buffer_.get();
1107 fine_audio_buffer_->GetPlayoutData(source); 1064 fine_audio_buffer_->GetPlayoutData(source);
1108 memcpy(destination, source, dataSizeInBytes); 1065 memcpy(destination, source, dataSizeInBytes);
1109 return noErr; 1066 return noErr;
1110 } 1067 }
1111 1068
1112 } // namespace webrtc 1069 } // namespace webrtc
OLDNEW
« 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