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}
This commit is contained in:
henrika 2016-06-16 14:26:55 +02:00
parent 5a9e7e0ba0
commit 2d014be554
2 changed files with 39 additions and 0 deletions

View File

@ -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<unsigned int>(frames_per_buffer),
static_cast<unsigned int>(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.

View File

@ -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;
}