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) {
|
if (audio_layer == kPlatformDefaultAudio) {
|
||||||
audio_device_.reset(new ios_adm::AudioDeviceIOS(
|
audio_device_.reset(new ios_adm::AudioDeviceIOS(
|
||||||
/*bypass_voice_processing=*/false,
|
/*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.";
|
RTC_LOG(LS_INFO) << "iPhone Audio APIs will be utilized.";
|
||||||
}
|
}
|
||||||
// END #if defined(WEBRTC_IOS)
|
// END #if defined(WEBRTC_IOS)
|
||||||
|
|||||||
@ -33,6 +33,11 @@ class FineAudioBuffer;
|
|||||||
|
|
||||||
namespace ios_adm {
|
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
|
// 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
|
// 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,
|
// supports audio echo cancellation. It also adds automatic gain control,
|
||||||
@ -52,7 +57,8 @@ class AudioDeviceIOS : public AudioDeviceGeneric,
|
|||||||
public:
|
public:
|
||||||
explicit AudioDeviceIOS(
|
explicit AudioDeviceIOS(
|
||||||
bool bypass_voice_processing,
|
bool bypass_voice_processing,
|
||||||
AudioDeviceModule::MutedSpeechEventHandler muted_speech_event_handler);
|
AudioDeviceModule::MutedSpeechEventHandler muted_speech_event_handler,
|
||||||
|
AudioDeviceIOSRenderErrorHandler render_error_handler);
|
||||||
~AudioDeviceIOS() override;
|
~AudioDeviceIOS() override;
|
||||||
|
|
||||||
void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
|
void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override;
|
||||||
@ -220,6 +226,13 @@ class AudioDeviceIOS : public AudioDeviceGeneric,
|
|||||||
// Handle a user speaking during muted event
|
// Handle a user speaking during muted event
|
||||||
AudioDeviceModule::MutedSpeechEventHandler muted_speech_event_handler_;
|
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.
|
// Native I/O audio thread checker.
|
||||||
SequenceChecker io_thread_checker_;
|
SequenceChecker io_thread_checker_;
|
||||||
|
|
||||||
|
|||||||
@ -97,9 +97,12 @@ static void LogDeviceInfo() {
|
|||||||
|
|
||||||
AudioDeviceIOS::AudioDeviceIOS(
|
AudioDeviceIOS::AudioDeviceIOS(
|
||||||
bool bypass_voice_processing,
|
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),
|
: bypass_voice_processing_(bypass_voice_processing),
|
||||||
muted_speech_event_handler_(muted_speech_event_handler),
|
muted_speech_event_handler_(muted_speech_event_handler),
|
||||||
|
render_error_handler_(render_error_handler),
|
||||||
|
disregard_next_render_error_(false),
|
||||||
audio_device_buffer_(nullptr),
|
audio_device_buffer_(nullptr),
|
||||||
audio_unit_(nullptr),
|
audio_unit_(nullptr),
|
||||||
recording_(0),
|
recording_(0),
|
||||||
@ -431,13 +434,18 @@ OSStatus AudioDeviceIOS::OnDeliverRecordedData(
|
|||||||
// to the preallocated audio buffer list that the audio unit renders into.
|
// 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
|
// We can make the audio unit provide a buffer instead in io_data, but we
|
||||||
// currently just use our own.
|
// currently just use our own.
|
||||||
// TODO(henrika): should error handling be improved?
|
|
||||||
result = audio_unit_->Render(
|
result = audio_unit_->Render(
|
||||||
flags, time_stamp, bus_number, num_frames, &audio_buffer_list);
|
flags, time_stamp, bus_number, num_frames, &audio_buffer_list);
|
||||||
if (result != noErr) {
|
if (result != noErr) {
|
||||||
RTCLogError(@"Failed to render audio.");
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
disregard_next_render_error_ = false;
|
||||||
|
|
||||||
// Get a pointer to the recorded audio and send it to the WebRTC ADB.
|
// Get a pointer to the recorded audio and send it to the WebRTC ADB.
|
||||||
// Use the FineAudioBuffer instance to convert between native buffer size
|
// Use the FineAudioBuffer instance to convert between native buffer size
|
||||||
|
|||||||
@ -84,10 +84,13 @@ int32_t AudioDeviceModuleIOS::Init() {
|
|||||||
RTC_DLOG(LS_INFO) << __FUNCTION__;
|
RTC_DLOG(LS_INFO) << __FUNCTION__;
|
||||||
if (initialized_) return 0;
|
if (initialized_) return 0;
|
||||||
|
|
||||||
|
AudioDeviceIOSRenderErrorHandler error_handler = ^(OSStatus error) {
|
||||||
|
ReportError(kRecordingDeviceFailed);
|
||||||
|
};
|
||||||
audio_device_buffer_.reset(
|
audio_device_buffer_.reset(
|
||||||
new webrtc::AudioDeviceBuffer(task_queue_factory_.get()));
|
new webrtc::AudioDeviceBuffer(task_queue_factory_.get()));
|
||||||
audio_device_.reset(new ios_adm::AudioDeviceIOS(bypass_voice_processing_,
|
audio_device_.reset(new ios_adm::AudioDeviceIOS(
|
||||||
muted_speech_event_handler_));
|
bypass_voice_processing_, muted_speech_event_handler_, error_handler));
|
||||||
RTC_CHECK(audio_device_);
|
RTC_CHECK(audio_device_);
|
||||||
|
|
||||||
this->AttachAudioBuffer();
|
this->AttachAudioBuffer();
|
||||||
|
|||||||
@ -48,7 +48,8 @@
|
|||||||
_audioDeviceModule = webrtc::CreateAudioDeviceModule();
|
_audioDeviceModule = webrtc::CreateAudioDeviceModule();
|
||||||
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
||||||
/*bypass_voice_processing=*/false,
|
/*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];
|
self.audioSession = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
@ -149,7 +150,8 @@
|
|||||||
|
|
||||||
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
||||||
/*bypass_voice_processing=*/false,
|
/*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(
|
_audio_device->OnReceivedMutedSpeechActivity(
|
||||||
kAUVoiceIOSpeechActivityHasStarted);
|
kAUVoiceIOSpeechActivityHasStarted);
|
||||||
@ -168,7 +170,8 @@
|
|||||||
|
|
||||||
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
_audio_device.reset(new webrtc::ios_adm::AudioDeviceIOS(
|
||||||
/*bypass_voice_processing=*/false,
|
/*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(
|
_audio_device->OnReceivedMutedSpeechActivity(
|
||||||
kAUVoiceIOSpeechActivityHasEnded);
|
kAUVoiceIOSpeechActivityHasEnded);
|
||||||
[self waitForExpectations:@[ handlerExpectation ] timeout:10.0];
|
[self waitForExpectations:@[ handlerExpectation ] timeout:10.0];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user