Add a render error callback from AudioDeviceIOS to AudioDeviceModuleIOS.
This change expands on https://webrtc-review.googlesource.com/c/src/+/374420 to cover the error produced when copying microphone samples. Change-Id: I7aa58c9c9ac175d5f4cfdb60bbd3f16334c03c1b Bug: webrtc:390314937 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/375540 Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org> Reviewed-by: Henrik Andreassson <henrika@webrtc.org> Commit-Queue: Peter Hanspers <peterhanspers@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43826}
This commit is contained in:
parent
4b39cb3eb6
commit
d643be9fdc
@ -243,7 +243,8 @@ int32_t AudioDeviceModuleImpl::CreatePlatformSpecificObjects() {
|
||||
if (audio_layer == kPlatformDefaultAudio) {
|
||||
audio_device_.reset(new ios_adm::AudioDeviceIOS(
|
||||
/*bypass_voice_processing=*/false,
|
||||
/*muted_speech_event_handler=*/nullptr));
|
||||
/*muted_speech_event_handler=*/nullptr,
|
||||
/*render_error_handler=*/nullptr));
|
||||
RTC_LOG(LS_INFO) << "iPhone Audio APIs will be utilized.";
|
||||
}
|
||||
// END #if defined(WEBRTC_IOS)
|
||||
|
||||
@ -33,6 +33,11 @@ class FineAudioBuffer;
|
||||
|
||||
namespace ios_adm {
|
||||
|
||||
// A callback handler for audio device rendering errors.
|
||||
// Note: Called on a realtime thread.
|
||||
// Note: Only applies to input rendering errors, not output.
|
||||
typedef void (^AudioDeviceIOSRenderErrorHandler)(OSStatus error);
|
||||
|
||||
// Implements full duplex 16-bit mono PCM audio support for iOS using a
|
||||
// Voice-Processing (VP) I/O audio unit in Core Audio. The VP I/O audio unit
|
||||
// supports audio echo cancellation. It also adds automatic gain control,
|
||||
@ -52,7 +57,8 @@ class AudioDeviceIOS : public AudioDeviceGeneric,
|
||||
public:
|
||||
explicit AudioDeviceIOS(
|
||||
bool bypass_voice_processing,
|
||||
AudioDeviceModule::MutedSpeechEventHandler muted_speech_event_handler);
|
||||
AudioDeviceModule::MutedSpeechEventHandler muted_speech_event_handler,
|
||||
AudioDeviceIOSRenderErrorHandler render_error_handler);
|
||||
~AudioDeviceIOS() override;
|
||||
|
||||
void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
|
||||
@ -220,6 +226,13 @@ class AudioDeviceIOS : public AudioDeviceGeneric,
|
||||
// Handle a user speaking during muted event
|
||||
AudioDeviceModule::MutedSpeechEventHandler muted_speech_event_handler_;
|
||||
|
||||
// Handle microphone rendering errors.
|
||||
AudioDeviceIOSRenderErrorHandler render_error_handler_;
|
||||
|
||||
// Copying microphone data (rendering to a buffer) may keep failing. This
|
||||
// field makes sure subsequent errors are not reported.
|
||||
bool disregard_next_render_error_;
|
||||
|
||||
// Native I/O audio thread checker.
|
||||
SequenceChecker io_thread_checker_;
|
||||
|
||||
|
||||
@ -97,9 +97,12 @@ static void LogDeviceInfo() {
|
||||
|
||||
AudioDeviceIOS::AudioDeviceIOS(
|
||||
bool bypass_voice_processing,
|
||||
AudioDeviceModule::MutedSpeechEventHandler muted_speech_event_handler)
|
||||
AudioDeviceModule::MutedSpeechEventHandler muted_speech_event_handler,
|
||||
AudioDeviceIOSRenderErrorHandler render_error_handler)
|
||||
: bypass_voice_processing_(bypass_voice_processing),
|
||||
muted_speech_event_handler_(muted_speech_event_handler),
|
||||
render_error_handler_(render_error_handler),
|
||||
disregard_next_render_error_(false),
|
||||
audio_device_buffer_(nullptr),
|
||||
audio_unit_(nullptr),
|
||||
recording_(0),
|
||||
@ -431,13 +434,18 @@ OSStatus AudioDeviceIOS::OnDeliverRecordedData(
|
||||
// to the preallocated audio buffer list that the audio unit renders into.
|
||||
// We can make the audio unit provide a buffer instead in io_data, but we
|
||||
// currently just use our own.
|
||||
// TODO(henrika): should error handling be improved?
|
||||
result = audio_unit_->Render(
|
||||
flags, time_stamp, bus_number, num_frames, &audio_buffer_list);
|
||||
if (result != noErr) {
|
||||
RTCLogError(@"Failed to render audio.");
|
||||
if (render_error_handler_ && !disregard_next_render_error_) {
|
||||
disregard_next_render_error_ = true;
|
||||
thread_->PostTask(
|
||||
SafeTask(safety_, [this, result] { render_error_handler_(result); }));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
disregard_next_render_error_ = false;
|
||||
|
||||
// Get a pointer to the recorded audio and send it to the WebRTC ADB.
|
||||
// Use the FineAudioBuffer instance to convert between native buffer size
|
||||
|
||||
@ -84,10 +84,13 @@ int32_t AudioDeviceModuleIOS::Init() {
|
||||
RTC_DLOG(LS_INFO) << __FUNCTION__;
|
||||
if (initialized_) return 0;
|
||||
|
||||
AudioDeviceIOSRenderErrorHandler error_handler = ^(OSStatus error) {
|
||||
ReportError(kRecordingDeviceFailed);
|
||||
};
|
||||
audio_device_buffer_.reset(
|
||||
new webrtc::AudioDeviceBuffer(task_queue_factory_.get()));
|
||||
audio_device_.reset(new ios_adm::AudioDeviceIOS(bypass_voice_processing_,
|
||||
muted_speech_event_handler_));
|
||||
audio_device_.reset(new ios_adm::AudioDeviceIOS(
|
||||
bypass_voice_processing_, muted_speech_event_handler_, error_handler));
|
||||
RTC_CHECK(audio_device_);
|
||||
|
||||
this->AttachAudioBuffer();
|
||||
|
||||
@ -48,7 +48,8 @@
|
||||
_audioDeviceModule = webrtc::CreateAudioDeviceModule();
|
||||
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
||||
/*bypass_voice_processing=*/false,
|
||||
/*muted_speech_event_handler=*/nullptr));
|
||||
/*muted_speech_event_handler=*/nullptr,
|
||||
/*render_error_handler=*/nullptr));
|
||||
self.audioSession = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
|
||||
|
||||
NSError *error = nil;
|
||||
@ -149,7 +150,8 @@
|
||||
|
||||
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
||||
/*bypass_voice_processing=*/false,
|
||||
/*muted_speech_event_handler=*/muted_speech_event_handler));
|
||||
/*muted_speech_event_handler=*/muted_speech_event_handler,
|
||||
/*render_error_handler=*/nullptr));
|
||||
|
||||
_audio_device->OnReceivedMutedSpeechActivity(
|
||||
kAUVoiceIOSpeechActivityHasStarted);
|
||||
@ -168,7 +170,8 @@
|
||||
|
||||
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
||||
/*bypass_voice_processing=*/false,
|
||||
/*muted_speech_event_handler=*/muted_speech_event_handler));
|
||||
/*muted_speech_event_handler=*/muted_speech_event_handler,
|
||||
/*render_error_handler=*/nullptr));
|
||||
_audio_device->OnReceivedMutedSpeechActivity(
|
||||
kAUVoiceIOSpeechActivityHasEnded);
|
||||
[self waitForExpectations:@[ handlerExpectation ] timeout:10.0];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user