summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/audio_device/mac/audio_device_mac.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/audio_device/mac/audio_device_mac.h')
-rw-r--r--third_party/libwebrtc/modules/audio_device/mac/audio_device_mac.h350
1 files changed, 350 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/audio_device/mac/audio_device_mac.h b/third_party/libwebrtc/modules/audio_device/mac/audio_device_mac.h
new file mode 100644
index 0000000000..bb06395d03
--- /dev/null
+++ b/third_party/libwebrtc/modules/audio_device/mac/audio_device_mac.h
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2012 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 AUDIO_DEVICE_AUDIO_DEVICE_MAC_H_
+#define AUDIO_DEVICE_AUDIO_DEVICE_MAC_H_
+
+#include <AudioToolbox/AudioConverter.h>
+#include <CoreAudio/CoreAudio.h>
+#include <mach/semaphore.h>
+
+#include <atomic>
+#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "modules/audio_device/audio_device_generic.h"
+#include "modules/audio_device/mac/audio_mixer_manager_mac.h"
+#include "rtc_base/event.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/synchronization/mutex.h"
+#include "rtc_base/thread_annotations.h"
+
+struct PaUtilRingBuffer;
+
+namespace webrtc {
+
+const uint32_t N_REC_SAMPLES_PER_SEC = 48000;
+const uint32_t N_PLAY_SAMPLES_PER_SEC = 48000;
+
+const uint32_t N_REC_CHANNELS = 1; // default is mono recording
+const uint32_t N_PLAY_CHANNELS = 2; // default is stereo playout
+const uint32_t N_DEVICE_CHANNELS = 64;
+
+const int kBufferSizeMs = 10;
+
+const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES =
+ N_REC_SAMPLES_PER_SEC * kBufferSizeMs / 1000;
+const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES =
+ N_PLAY_SAMPLES_PER_SEC * kBufferSizeMs / 1000;
+
+const int N_BLOCKS_IO = 2;
+const int N_BUFFERS_IN = 2; // Must be at least N_BLOCKS_IO.
+const int N_BUFFERS_OUT = 3; // Must be at least N_BLOCKS_IO.
+
+const uint32_t TIMER_PERIOD_MS = 2 * 10 * N_BLOCKS_IO * 1000000;
+
+const uint32_t REC_BUF_SIZE_IN_SAMPLES =
+ ENGINE_REC_BUF_SIZE_IN_SAMPLES * N_DEVICE_CHANNELS * N_BUFFERS_IN;
+const uint32_t PLAY_BUF_SIZE_IN_SAMPLES =
+ ENGINE_PLAY_BUF_SIZE_IN_SAMPLES * N_PLAY_CHANNELS * N_BUFFERS_OUT;
+
+const int kGetMicVolumeIntervalMs = 1000;
+
+class AudioDeviceMac : public AudioDeviceGeneric {
+ public:
+ AudioDeviceMac();
+ ~AudioDeviceMac();
+
+ // Retrieve the currently utilized audio layer
+ virtual int32_t ActiveAudioLayer(
+ AudioDeviceModule::AudioLayer& audioLayer) const;
+
+ // Main initializaton and termination
+ virtual InitStatus Init() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t Terminate() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual bool Initialized() const;
+
+ // Device enumeration
+ virtual int16_t PlayoutDevices();
+ virtual int16_t RecordingDevices();
+ virtual int32_t PlayoutDeviceName(uint16_t index,
+ char name[kAdmMaxDeviceNameSize],
+ char guid[kAdmMaxGuidSize]);
+ virtual int32_t RecordingDeviceName(uint16_t index,
+ char name[kAdmMaxDeviceNameSize],
+ char guid[kAdmMaxGuidSize]);
+
+ // Device selection
+ virtual int32_t SetPlayoutDevice(uint16_t index) RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device);
+ virtual int32_t SetRecordingDevice(uint16_t index);
+ virtual int32_t SetRecordingDevice(
+ AudioDeviceModule::WindowsDeviceType device);
+
+ // Audio transport initialization
+ virtual int32_t PlayoutIsAvailable(bool& available);
+ virtual int32_t InitPlayout() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual bool PlayoutIsInitialized() const;
+ virtual int32_t RecordingIsAvailable(bool& available);
+ virtual int32_t InitRecording() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual bool RecordingIsInitialized() const;
+
+ // Audio transport control
+ virtual int32_t StartPlayout() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t StopPlayout() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual bool Playing() const;
+ virtual int32_t StartRecording() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t StopRecording() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual bool Recording() const;
+
+ // Audio mixer initialization
+ virtual int32_t InitSpeaker() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual bool SpeakerIsInitialized() const;
+ virtual int32_t InitMicrophone() RTC_LOCKS_EXCLUDED(mutex_);
+ virtual bool MicrophoneIsInitialized() const;
+
+ // Speaker volume controls
+ virtual int32_t SpeakerVolumeIsAvailable(bool& available)
+ RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t SetSpeakerVolume(uint32_t volume);
+ virtual int32_t SpeakerVolume(uint32_t& volume) const;
+ virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const;
+ virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const;
+
+ // Microphone volume controls
+ virtual int32_t MicrophoneVolumeIsAvailable(bool& available)
+ RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t SetMicrophoneVolume(uint32_t volume);
+ virtual int32_t MicrophoneVolume(uint32_t& volume) const;
+ virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const;
+ virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const;
+
+ // Microphone mute control
+ virtual int32_t MicrophoneMuteIsAvailable(bool& available)
+ RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t SetMicrophoneMute(bool enable);
+ virtual int32_t MicrophoneMute(bool& enabled) const;
+
+ // Speaker mute control
+ virtual int32_t SpeakerMuteIsAvailable(bool& available)
+ RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t SetSpeakerMute(bool enable);
+ virtual int32_t SpeakerMute(bool& enabled) const;
+
+ // Stereo support
+ virtual int32_t StereoPlayoutIsAvailable(bool& available)
+ RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t SetStereoPlayout(bool enable);
+ virtual int32_t StereoPlayout(bool& enabled) const;
+ virtual int32_t StereoRecordingIsAvailable(bool& available);
+ virtual int32_t SetStereoRecording(bool enable);
+ virtual int32_t StereoRecording(bool& enabled) const;
+
+ // Delay information and control
+ virtual int32_t PlayoutDelay(uint16_t& delayMS) const;
+
+ virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer)
+ RTC_LOCKS_EXCLUDED(mutex_);
+
+ private:
+ int32_t InitSpeakerLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ int32_t InitMicrophoneLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ virtual int32_t MicrophoneIsAvailable(bool& available)
+ RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t MicrophoneIsAvailableLocked(bool& available)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ virtual int32_t SpeakerIsAvailable(bool& available)
+ RTC_LOCKS_EXCLUDED(mutex_);
+ virtual int32_t SpeakerIsAvailableLocked(bool& available)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ static void AtomicSet32(int32_t* theValue, int32_t newValue);
+ static int32_t AtomicGet32(int32_t* theValue);
+
+ static void logCAMsg(rtc::LoggingSeverity sev,
+ const char* msg,
+ const char* err);
+
+ int32_t GetNumberDevices(AudioObjectPropertyScope scope,
+ AudioDeviceID scopedDeviceIds[],
+ uint32_t deviceListLength);
+
+ int32_t GetDeviceName(AudioObjectPropertyScope scope,
+ uint16_t index,
+ rtc::ArrayView<char> name);
+
+ int32_t InitDevice(uint16_t userDeviceIndex,
+ AudioDeviceID& deviceId,
+ bool isInput);
+
+ // Always work with our preferred playout format inside VoE.
+ // Then convert the output to the OS setting using an AudioConverter.
+ OSStatus SetDesiredPlayoutFormat();
+
+ static OSStatus objectListenerProc(
+ AudioObjectID objectId,
+ UInt32 numberAddresses,
+ const AudioObjectPropertyAddress addresses[],
+ void* clientData);
+
+ OSStatus implObjectListenerProc(AudioObjectID objectId,
+ UInt32 numberAddresses,
+ const AudioObjectPropertyAddress addresses[]);
+
+ int32_t HandleDeviceChange();
+
+ int32_t HandleStreamFormatChange(AudioObjectID objectId,
+ AudioObjectPropertyAddress propertyAddress);
+
+ int32_t HandleDataSourceChange(AudioObjectID objectId,
+ AudioObjectPropertyAddress propertyAddress);
+
+ int32_t HandleProcessorOverload(AudioObjectPropertyAddress propertyAddress);
+
+ static OSStatus deviceIOProc(AudioDeviceID device,
+ const AudioTimeStamp* now,
+ const AudioBufferList* inputData,
+ const AudioTimeStamp* inputTime,
+ AudioBufferList* outputData,
+ const AudioTimeStamp* outputTime,
+ void* clientData);
+
+ static OSStatus outConverterProc(
+ AudioConverterRef audioConverter,
+ UInt32* numberDataPackets,
+ AudioBufferList* data,
+ AudioStreamPacketDescription** dataPacketDescription,
+ void* userData);
+
+ static OSStatus inDeviceIOProc(AudioDeviceID device,
+ const AudioTimeStamp* now,
+ const AudioBufferList* inputData,
+ const AudioTimeStamp* inputTime,
+ AudioBufferList* outputData,
+ const AudioTimeStamp* outputTime,
+ void* clientData);
+
+ static OSStatus inConverterProc(
+ AudioConverterRef audioConverter,
+ UInt32* numberDataPackets,
+ AudioBufferList* data,
+ AudioStreamPacketDescription** dataPacketDescription,
+ void* inUserData);
+
+ OSStatus implDeviceIOProc(const AudioBufferList* inputData,
+ const AudioTimeStamp* inputTime,
+ AudioBufferList* outputData,
+ const AudioTimeStamp* outputTime)
+ RTC_LOCKS_EXCLUDED(mutex_);
+
+ OSStatus implOutConverterProc(UInt32* numberDataPackets,
+ AudioBufferList* data);
+
+ OSStatus implInDeviceIOProc(const AudioBufferList* inputData,
+ const AudioTimeStamp* inputTime)
+ RTC_LOCKS_EXCLUDED(mutex_);
+
+ OSStatus implInConverterProc(UInt32* numberDataPackets,
+ AudioBufferList* data);
+
+ static void RunCapture(void*);
+ static void RunRender(void*);
+ bool CaptureWorkerThread();
+ bool RenderWorkerThread();
+
+ bool KeyPressed();
+
+ AudioDeviceBuffer* _ptrAudioBuffer;
+
+ Mutex mutex_;
+
+ rtc::Event _stopEventRec;
+ rtc::Event _stopEvent;
+
+ // Only valid/running between calls to StartRecording and StopRecording.
+ rtc::PlatformThread capture_worker_thread_;
+
+ // Only valid/running between calls to StartPlayout and StopPlayout.
+ rtc::PlatformThread render_worker_thread_;
+
+ AudioMixerManagerMac _mixerManager;
+
+ uint16_t _inputDeviceIndex;
+ uint16_t _outputDeviceIndex;
+ AudioDeviceID _inputDeviceID;
+ AudioDeviceID _outputDeviceID;
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+ AudioDeviceIOProcID _inDeviceIOProcID;
+ AudioDeviceIOProcID _deviceIOProcID;
+#endif
+ bool _inputDeviceIsSpecified;
+ bool _outputDeviceIsSpecified;
+
+ uint8_t _recChannels;
+ uint8_t _playChannels;
+
+ Float32* _captureBufData;
+ SInt16* _renderBufData;
+
+ SInt16 _renderConvertData[PLAY_BUF_SIZE_IN_SAMPLES];
+
+ bool _initialized;
+ bool _isShutDown;
+ bool _recording;
+ bool _playing;
+ bool _recIsInitialized;
+ bool _playIsInitialized;
+
+ // Atomically set varaibles
+ std::atomic<int32_t> _renderDeviceIsAlive;
+ std::atomic<int32_t> _captureDeviceIsAlive;
+
+ bool _twoDevices;
+ bool _doStop; // For play if not shared device or play+rec if shared device
+ bool _doStopRec; // For rec if not shared device
+ bool _macBookPro;
+ bool _macBookProPanRight;
+
+ AudioConverterRef _captureConverter;
+ AudioConverterRef _renderConverter;
+
+ AudioStreamBasicDescription _outStreamFormat;
+ AudioStreamBasicDescription _outDesiredFormat;
+ AudioStreamBasicDescription _inStreamFormat;
+ AudioStreamBasicDescription _inDesiredFormat;
+
+ uint32_t _captureLatencyUs;
+ uint32_t _renderLatencyUs;
+
+ // Atomically set variables
+ mutable std::atomic<int32_t> _captureDelayUs;
+ mutable std::atomic<int32_t> _renderDelayUs;
+
+ int32_t _renderDelayOffsetSamples;
+
+ PaUtilRingBuffer* _paCaptureBuffer;
+ PaUtilRingBuffer* _paRenderBuffer;
+
+ semaphore_t _renderSemaphore;
+ semaphore_t _captureSemaphore;
+
+ int _captureBufSizeSamples;
+ int _renderBufSizeSamples;
+
+ // Typing detection
+ // 0x5c is key "9", after that comes function keys.
+ bool prev_key_state_[0x5d];
+};
+
+} // namespace webrtc
+
+#endif // MODULES_AUDIO_DEVICE_MAIN_SOURCE_MAC_AUDIO_DEVICE_MAC_H_