summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/sdk/objc/native/src/objc_audio_device.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/sdk/objc/native/src/objc_audio_device.h')
-rw-r--r--third_party/libwebrtc/sdk/objc/native/src/objc_audio_device.h277
1 files changed, 277 insertions, 0 deletions
diff --git a/third_party/libwebrtc/sdk/objc/native/src/objc_audio_device.h b/third_party/libwebrtc/sdk/objc/native/src/objc_audio_device.h
new file mode 100644
index 0000000000..fcfe7a6e8b
--- /dev/null
+++ b/third_party/libwebrtc/sdk/objc/native/src/objc_audio_device.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef SDK_OBJC_NATIVE_SRC_OBJC_AUDIO_DEVICE_H_
+#define SDK_OBJC_NATIVE_SRC_OBJC_AUDIO_DEVICE_H_
+
+#include <memory>
+
+#import "components/audio/RTCAudioDevice.h"
+
+#include "modules/audio_device/audio_device_buffer.h"
+#include "modules/audio_device/include/audio_device.h"
+#include "rtc_base/thread.h"
+
+@class ObjCAudioDeviceDelegate;
+
+namespace webrtc {
+
+class FineAudioBuffer;
+
+namespace objc_adm {
+
+class ObjCAudioDeviceModule : public AudioDeviceModule {
+ public:
+ explicit ObjCAudioDeviceModule(id<RTC_OBJC_TYPE(RTCAudioDevice)> audio_device);
+ ~ObjCAudioDeviceModule() override;
+
+ // Retrieve the currently utilized audio layer
+ int32_t ActiveAudioLayer(AudioLayer* audioLayer) const override;
+
+ // Full-duplex transportation of PCM audio
+ int32_t RegisterAudioCallback(AudioTransport* audioCallback) override;
+
+ // Main initialization and termination
+ int32_t Init() override;
+ int32_t Terminate() override;
+ bool Initialized() const override;
+
+ // Device enumeration
+ int16_t PlayoutDevices() override;
+ int16_t RecordingDevices() override;
+ int32_t PlayoutDeviceName(uint16_t index,
+ char name[kAdmMaxDeviceNameSize],
+ char guid[kAdmMaxGuidSize]) override;
+ int32_t RecordingDeviceName(uint16_t index,
+ char name[kAdmMaxDeviceNameSize],
+ char guid[kAdmMaxGuidSize]) override;
+
+ // Device selection
+ int32_t SetPlayoutDevice(uint16_t index) override;
+ int32_t SetPlayoutDevice(WindowsDeviceType device) override;
+ int32_t SetRecordingDevice(uint16_t index) override;
+ int32_t SetRecordingDevice(WindowsDeviceType device) override;
+
+ // Audio transport initialization
+ int32_t PlayoutIsAvailable(bool* available) override;
+ int32_t InitPlayout() override;
+ bool PlayoutIsInitialized() const override;
+ int32_t RecordingIsAvailable(bool* available) override;
+ int32_t InitRecording() override;
+ bool RecordingIsInitialized() const override;
+
+ // Audio transport control
+ int32_t StartPlayout() override;
+ int32_t StopPlayout() override;
+ bool Playing() const override;
+ int32_t StartRecording() override;
+ int32_t StopRecording() override;
+ bool Recording() const override;
+
+ // Audio mixer initialization
+ int32_t InitSpeaker() override;
+ bool SpeakerIsInitialized() const override;
+ int32_t InitMicrophone() override;
+ bool MicrophoneIsInitialized() const override;
+
+ // Speaker volume controls
+ int32_t SpeakerVolumeIsAvailable(bool* available) override;
+ int32_t SetSpeakerVolume(uint32_t volume) override;
+ int32_t SpeakerVolume(uint32_t* volume) const override;
+ int32_t MaxSpeakerVolume(uint32_t* maxVolume) const override;
+ int32_t MinSpeakerVolume(uint32_t* minVolume) const override;
+
+ // Microphone volume controls
+ int32_t MicrophoneVolumeIsAvailable(bool* available) override;
+ int32_t SetMicrophoneVolume(uint32_t volume) override;
+ int32_t MicrophoneVolume(uint32_t* volume) const override;
+ int32_t MaxMicrophoneVolume(uint32_t* maxVolume) const override;
+ int32_t MinMicrophoneVolume(uint32_t* minVolume) const override;
+
+ // Speaker mute control
+ int32_t SpeakerMuteIsAvailable(bool* available) override;
+ int32_t SetSpeakerMute(bool enable) override;
+ int32_t SpeakerMute(bool* enabled) const override;
+
+ // Microphone mute control
+ int32_t MicrophoneMuteIsAvailable(bool* available) override;
+ int32_t SetMicrophoneMute(bool enable) override;
+ int32_t MicrophoneMute(bool* enabled) const override;
+
+ // Stereo support
+ int32_t StereoPlayoutIsAvailable(bool* available) const override;
+ int32_t SetStereoPlayout(bool enable) override;
+ int32_t StereoPlayout(bool* enabled) const override;
+ int32_t StereoRecordingIsAvailable(bool* available) const override;
+ int32_t SetStereoRecording(bool enable) override;
+ int32_t StereoRecording(bool* enabled) const override;
+
+ // Playout delay
+ int32_t PlayoutDelay(uint16_t* delayMS) const override;
+
+ // Only supported on Android.
+ bool BuiltInAECIsAvailable() const override;
+ bool BuiltInAGCIsAvailable() const override;
+ bool BuiltInNSIsAvailable() const override;
+
+ // Enables the built-in audio effects. Only supported on Android.
+ int32_t EnableBuiltInAEC(bool enable) override;
+ int32_t EnableBuiltInAGC(bool enable) override;
+ int32_t EnableBuiltInNS(bool enable) override;
+
+ // Play underrun count. Only supported on Android.
+ int32_t GetPlayoutUnderrunCount() const override;
+
+#if defined(WEBRTC_IOS)
+ int GetPlayoutAudioParameters(AudioParameters* params) const override;
+ int GetRecordAudioParameters(AudioParameters* params) const override;
+#endif // WEBRTC_IOS
+
+ public:
+ OSStatus OnDeliverRecordedData(AudioUnitRenderActionFlags* flags,
+ const AudioTimeStamp* time_stamp,
+ NSInteger bus_number,
+ UInt32 num_frames,
+ const AudioBufferList* io_data,
+ void* render_context,
+ RTC_OBJC_TYPE(RTCAudioDeviceRenderRecordedDataBlock) render_block);
+
+ OSStatus OnGetPlayoutData(AudioUnitRenderActionFlags* flags,
+ const AudioTimeStamp* time_stamp,
+ NSInteger bus_number,
+ UInt32 num_frames,
+ AudioBufferList* io_data);
+
+ // Notifies `ObjCAudioDeviceModule` that at least one of the audio input
+ // parameters or audio input latency of `RTCAudioDevice` has changed. It necessary to
+ // update `record_parameters_` with current audio parameter of `RTCAudioDevice`
+ // via `UpdateAudioParameters` and if parameters are actually change then
+ // ADB parameters are updated with `UpdateInputAudioDeviceBuffer`. Audio input latency
+ // stored in `cached_recording_delay_ms_` is also updated with current latency
+ // of `RTCAudioDevice`.
+ void HandleAudioInputParametersChange();
+
+ // Same as `HandleAudioInputParametersChange` but should be called when audio output
+ // parameters of `RTCAudioDevice` has changed.
+ void HandleAudioOutputParametersChange();
+
+ // Notifies `ObjCAudioDeviceModule` about audio input interruption happen due to
+ // any reason so `ObjCAudioDeviceModule` is can prepare to restart of audio IO.
+ void HandleAudioInputInterrupted();
+
+ // Same as `ObjCAudioDeviceModule` but should be called when audio output
+ // is interrupted.
+ void HandleAudioOutputInterrupted();
+
+ private:
+ // Update our audio parameters if they are different from current device audio parameters
+ // Returns true when our parameters are update, false - otherwise.
+ // `ObjCAudioDeviceModule` has audio device buffer (ADB) which has audio parameters
+ // of playout & recording. The ADB is configured to work with specific sample rate & channel
+ // count. `ObjCAudioDeviceModule` stores audio parameters which were used to configure ADB in the
+ // fields `playout_parameters_` and `recording_parameters_`.
+ // `RTCAudioDevice` protocol has its own audio parameters exposed as individual properties.
+ // `RTCAudioDevice` audio parameters might change when playout/recording is already in progress,
+ // for example, when device is switched. `RTCAudioDevice` audio parameters must be kept in sync
+ // with ADB audio parameters. This method is invoked when `RTCAudioDevice` reports that it's audio
+ // parameters (`device_params`) are changed and it detects if there any difference with our
+ // current audio parameters (`params`). Our parameters are updated in case of actual change and
+ // method returns true. In case of actual change there is follow-up call to either
+ // `UpdateOutputAudioDeviceBuffer` or `UpdateInputAudioDeviceBuffer` to apply updated
+ // `playout_parameters_` or `recording_parameters_` to ADB.
+
+ bool UpdateAudioParameters(AudioParameters& params, const AudioParameters& device_params);
+
+ // Update our cached audio latency with device latency. Device latency is reported by
+ // `RTCAudioDevice` object. Whenever latency is changed, `RTCAudioDevice` is obliged to notify ADM
+ // about the change via `HandleAudioInputParametersChange` or `HandleAudioOutputParametersChange`.
+ // Current device IO latency is cached in the atomic field and used from audio IO thread
+ // to be reported to audio device buffer. It is highly recommended by Apple not to call any
+ // ObjC methods from audio IO thread, that is why implementation relies on caching latency
+ // into a field and being notified when latency is changed, which is the case when device
+ // is switched.
+ void UpdateAudioDelay(std::atomic<int>& delay_ms, const NSTimeInterval device_latency);
+
+ // Uses current `playout_parameters_` to inform the audio device buffer (ADB)
+ // about our internal audio parameters.
+ void UpdateOutputAudioDeviceBuffer();
+
+ // Uses current `record_parameters_` to inform the audio device buffer (ADB)
+ // about our internal audio parameters.
+ void UpdateInputAudioDeviceBuffer();
+
+ private:
+ id<RTC_OBJC_TYPE(RTCAudioDevice)> audio_device_;
+
+ const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
+
+ // AudioDeviceBuffer is a buffer to consume audio recorded by `RTCAudioDevice`
+ // and provide audio to be played via `RTCAudioDevice`.
+ // Audio PCMs could have different sample rate and channels count, but expected
+ // to be in 16-bit integer interleaved linear PCM format.
+ // The current parameters ADB configured to work with is stored in field
+ // `playout_parameters_` for playout and `record_parameters_` for recording.
+ // These parameters and ADB must kept in sync with `RTCAudioDevice` audio parameters.
+ std::unique_ptr<AudioDeviceBuffer> audio_device_buffer_;
+
+ // Set to 1 when recording is active and 0 otherwise.
+ std::atomic<bool> recording_ = false;
+
+ // Set to 1 when playout is active and 0 otherwise.
+ std::atomic<bool> playing_ = false;
+
+ // Stores cached value of `RTCAudioDevice outputLatency` to be used from
+ // audio IO thread. Latency is updated on audio output parameters change.
+ std::atomic<int> cached_playout_delay_ms_ = 0;
+
+ // Same as `cached_playout_delay_ms_` but for audio input
+ std::atomic<int> cached_recording_delay_ms_ = 0;
+
+ // Thread that is initialized audio device module.
+ rtc::Thread* thread_;
+
+ // Ensures that methods are called from the same thread as this object is
+ // initialized on.
+ SequenceChecker thread_checker_;
+
+ // I/O audio thread checker.
+ SequenceChecker io_playout_thread_checker_;
+ SequenceChecker io_record_thread_checker_;
+
+ bool is_initialized_ RTC_GUARDED_BY(thread_checker_) = false;
+ bool is_playout_initialized_ RTC_GUARDED_BY(thread_checker_) = false;
+ bool is_recording_initialized_ RTC_GUARDED_BY(thread_checker_) = false;
+
+ // Contains audio parameters (sample rate, #channels, buffer size etc.) for
+ // the playout and recording sides.
+ AudioParameters playout_parameters_;
+ AudioParameters record_parameters_;
+
+ // `FineAudioBuffer` takes an `AudioDeviceBuffer` which delivers audio data
+ // in chunks of 10ms. `RTCAudioDevice` might deliver recorded data in
+ // chunks which are not 10ms long. `FineAudioBuffer` implements adaptation
+ // from undetermined chunk size to 10ms chunks.
+ std::unique_ptr<FineAudioBuffer> record_fine_audio_buffer_;
+
+ // Same as `record_fine_audio_buffer_` but for audio output.
+ std::unique_ptr<FineAudioBuffer> playout_fine_audio_buffer_;
+
+ // Temporary storage for recorded data.
+ rtc::BufferT<int16_t> record_audio_buffer_;
+
+ // Delegate object provided to RTCAudioDevice during initialization
+ ObjCAudioDeviceDelegate* audio_device_delegate_;
+};
+
+} // namespace objc_adm
+
+} // namespace webrtc
+
+#endif // SDK_OBJC_NATIVE_SRC_OBJC_AUDIO_DEVICE_H_