From 2d014be554f63128ceed8ecba007dff89595b4ae Mon Sep 17 00:00:00 2001 From: henrika Date: Thu, 16 Jun 2016 14:26:55 +0200 Subject: [PATCH] Resolves issue with bad audio using BT headsets on iOS. BUG=webrtc:6004 R=tkchin@webrtc.org Review URL: https://codereview.webrtc.org/2063733002 . Cr-Commit-Position: refs/heads/master@{#13165} --- .../audio_device/ios/audio_device_ios.mm | 14 +++++++++++ .../audio_device/ios/objc/RTCAudioSession.mm | 25 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/webrtc/modules/audio_device/ios/audio_device_ios.mm b/webrtc/modules/audio_device/ios/audio_device_ios.mm index e564540595..0bb997db53 100644 --- a/webrtc/modules/audio_device/ios/audio_device_ios.mm +++ b/webrtc/modules/audio_device/ios/audio_device_ios.mm @@ -431,6 +431,20 @@ OSStatus AudioDeviceIOS::OnGetPlayoutData(AudioUnitRenderActionFlags* flags, memset(destination, 0, size_in_bytes); return noErr; } + // Produce silence and log a warning message for the case when Core Audio is + // asking for an invalid number of audio frames. I don't expect this to happen + // but it is done as a safety measure to avoid bad audio if such as case would + // ever be triggered e.g. in combination with BT devices. + const size_t frames_per_buffer = playout_parameters_.frames_per_buffer(); + if (num_frames != frames_per_buffer) { + RTCLogWarning(@"Expected %u frames but got %u", + static_cast(frames_per_buffer), + static_cast(num_frames)); + *flags |= kAudioUnitRenderAction_OutputIsSilence; + memset(destination, 0, size_in_bytes); + return noErr; + } + // Read decoded 16-bit PCM samples from WebRTC (using a size that matches // the native I/O audio unit) to a preallocated intermediate buffer and // copy the result to the audio buffer in the |io_data| destination. diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm b/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm index 7ef5110f47..159d34e993 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm +++ b/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm @@ -636,6 +636,31 @@ NSInteger const kRTCAudioSessionErrorConfiguration = -2; return NO; } + // It can happen (e.g. in combination with BT devices) that the attempt to set + // the preferred sample rate for WebRTC (48kHz) fails. If so, make a new + // configuration attempt using the sample rate that worked using the active + // audio session. A typical case is that only 8 or 16kHz can be set, e.g. in + // combination with BT headsets. Using this "trick" seems to avoid a state + // where Core Audio asks for a different number of audio frames than what the + // session's I/O buffer duration corresponds to. + // TODO(henrika): this fix resolves bugs.webrtc.org/6004 but it has only been + // tested on a limited set of iOS devices and BT devices. + double sessionSampleRate = self.sampleRate; + double preferredSampleRate = webRTCConfig.sampleRate; + if (sessionSampleRate != preferredSampleRate) { + RTCLogWarning( + @"Current sample rate (%.2f) is not the preferred rate (%.2f)", + sessionSampleRate, preferredSampleRate); + if (![self setPreferredSampleRate:sessionSampleRate + error:&error]) { + RTCLogError(@"Failed to set preferred sample rate: %@", + error.localizedDescription); + if (outError) { + *outError = error; + } + } + } + return YES; }