blob: 8dece727399637d56528df9ddc876abfbf06dbc3 [file] [log] [blame]
xians@google.com68efa212011-08-11 12:41:56 +00001/*
leozwang@webrtc.org28f39132012-03-01 18:01:48 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
xians@google.com68efa212011-08-11 12:41:56 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef AUDIO_DEVICE_AUDIO_DEVICE_MAC_H_
12#define AUDIO_DEVICE_AUDIO_DEVICE_MAC_H_
xians@google.com68efa212011-08-11 12:41:56 +000013
kwibergf01633e2016-02-24 05:00:36 -080014#include <memory>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_device/audio_device_generic.h"
17#include "modules/audio_device/mac/audio_mixer_manager_mac.h"
18#include "rtc_base/criticalsection.h"
19#include "rtc_base/logging.h"
20#include "rtc_base/thread_annotations.h"
21#include "system_wrappers/include/event_wrapper.h"
xians@google.com68efa212011-08-11 12:41:56 +000022
xians@google.com68efa212011-08-11 12:41:56 +000023#include <AudioToolbox/AudioConverter.h>
pbos@webrtc.org811269d2013-07-11 13:24:38 +000024#include <CoreAudio/CoreAudio.h>
xians@google.com68efa212011-08-11 12:41:56 +000025#include <mach/semaphore.h>
26
27struct PaUtilRingBuffer;
28
Peter Boström8c38e8b2015-11-26 17:45:47 +010029namespace rtc {
30class PlatformThread;
31} // namespace rtc
32
andrew2bc63a12016-01-11 15:59:17 -080033namespace webrtc {
xians@google.com68efa212011-08-11 12:41:56 +000034class EventWrapper;
xians@google.com68efa212011-08-11 12:41:56 +000035
andrew@webrtc.org569fdef2013-06-08 00:43:25 +000036const uint32_t N_REC_SAMPLES_PER_SEC = 48000;
37const uint32_t N_PLAY_SAMPLES_PER_SEC = 48000;
xians@google.com68efa212011-08-11 12:41:56 +000038
andrew2bc63a12016-01-11 15:59:17 -080039const uint32_t N_REC_CHANNELS = 1; // default is mono recording
40const uint32_t N_PLAY_CHANNELS = 2; // default is stereo playout
andrew@webrtc.org569fdef2013-06-08 00:43:25 +000041const uint32_t N_DEVICE_CHANNELS = 64;
xians@google.com68efa212011-08-11 12:41:56 +000042
andrewec80f032016-01-08 01:16:17 -080043const int kBufferSizeMs = 10;
44
45const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES =
46 N_REC_SAMPLES_PER_SEC * kBufferSizeMs / 1000;
47const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES =
48 N_PLAY_SAMPLES_PER_SEC * kBufferSizeMs / 1000;
xians@google.com68efa212011-08-11 12:41:56 +000049
andrew@webrtc.org6f69eb72013-06-07 17:56:50 +000050const int N_BLOCKS_IO = 2;
andrew2bc63a12016-01-11 15:59:17 -080051const int N_BUFFERS_IN = 2; // Must be at least N_BLOCKS_IO.
andrew@webrtc.org6f69eb72013-06-07 17:56:50 +000052const int N_BUFFERS_OUT = 3; // Must be at least N_BLOCKS_IO.
xians@google.com68efa212011-08-11 12:41:56 +000053
andrewec80f032016-01-08 01:16:17 -080054const uint32_t TIMER_PERIOD_MS = 2 * 10 * N_BLOCKS_IO * 1000000;
xians@google.com68efa212011-08-11 12:41:56 +000055
andrew@webrtc.org569fdef2013-06-08 00:43:25 +000056const uint32_t REC_BUF_SIZE_IN_SAMPLES =
andrew@webrtc.org6f69eb72013-06-07 17:56:50 +000057 ENGINE_REC_BUF_SIZE_IN_SAMPLES * N_DEVICE_CHANNELS * N_BUFFERS_IN;
andrew@webrtc.org569fdef2013-06-08 00:43:25 +000058const uint32_t PLAY_BUF_SIZE_IN_SAMPLES =
andrew@webrtc.org6f69eb72013-06-07 17:56:50 +000059 ENGINE_PLAY_BUF_SIZE_IN_SAMPLES * N_PLAY_CHANNELS * N_BUFFERS_OUT;
xians@google.com68efa212011-08-11 12:41:56 +000060
andrewec80f032016-01-08 01:16:17 -080061const int kGetMicVolumeIntervalMs = 1000;
62
andrew2bc63a12016-01-11 15:59:17 -080063class AudioDeviceMac : public AudioDeviceGeneric {
64 public:
sazab4aa4eb2017-07-19 01:12:36 -070065 AudioDeviceMac();
andrew2bc63a12016-01-11 15:59:17 -080066 ~AudioDeviceMac();
xians@google.com68efa212011-08-11 12:41:56 +000067
andrew2bc63a12016-01-11 15:59:17 -080068 // Retrieve the currently utilized audio layer
69 virtual int32_t ActiveAudioLayer(
70 AudioDeviceModule::AudioLayer& audioLayer) const;
xians@google.com68efa212011-08-11 12:41:56 +000071
andrew2bc63a12016-01-11 15:59:17 -080072 // Main initializaton and termination
Max Morin84cab202016-07-01 13:35:19 +020073 virtual InitStatus Init();
andrew2bc63a12016-01-11 15:59:17 -080074 virtual int32_t Terminate();
75 virtual bool Initialized() const;
xians@google.com68efa212011-08-11 12:41:56 +000076
andrew2bc63a12016-01-11 15:59:17 -080077 // Device enumeration
78 virtual int16_t PlayoutDevices();
79 virtual int16_t RecordingDevices();
80 virtual int32_t PlayoutDeviceName(uint16_t index,
81 char name[kAdmMaxDeviceNameSize],
82 char guid[kAdmMaxGuidSize]);
83 virtual int32_t RecordingDeviceName(uint16_t index,
84 char name[kAdmMaxDeviceNameSize],
85 char guid[kAdmMaxGuidSize]);
xians@google.com68efa212011-08-11 12:41:56 +000086
andrew2bc63a12016-01-11 15:59:17 -080087 // Device selection
88 virtual int32_t SetPlayoutDevice(uint16_t index);
89 virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device);
90 virtual int32_t SetRecordingDevice(uint16_t index);
91 virtual int32_t SetRecordingDevice(
92 AudioDeviceModule::WindowsDeviceType device);
xians@google.com68efa212011-08-11 12:41:56 +000093
andrew2bc63a12016-01-11 15:59:17 -080094 // Audio transport initialization
95 virtual int32_t PlayoutIsAvailable(bool& available);
96 virtual int32_t InitPlayout();
97 virtual bool PlayoutIsInitialized() const;
98 virtual int32_t RecordingIsAvailable(bool& available);
99 virtual int32_t InitRecording();
100 virtual bool RecordingIsInitialized() const;
xians@google.com68efa212011-08-11 12:41:56 +0000101
andrew2bc63a12016-01-11 15:59:17 -0800102 // Audio transport control
103 virtual int32_t StartPlayout();
104 virtual int32_t StopPlayout();
105 virtual bool Playing() const;
106 virtual int32_t StartRecording();
107 virtual int32_t StopRecording();
108 virtual bool Recording() const;
xians@google.com68efa212011-08-11 12:41:56 +0000109
andrew2bc63a12016-01-11 15:59:17 -0800110 // Microphone Automatic Gain Control (AGC)
111 virtual int32_t SetAGC(bool enable);
112 virtual bool AGC() const;
xians@google.com68efa212011-08-11 12:41:56 +0000113
andrew2bc63a12016-01-11 15:59:17 -0800114 // Audio mixer initialization
115 virtual int32_t InitSpeaker();
116 virtual bool SpeakerIsInitialized() const;
117 virtual int32_t InitMicrophone();
118 virtual bool MicrophoneIsInitialized() const;
xians@google.com68efa212011-08-11 12:41:56 +0000119
andrew2bc63a12016-01-11 15:59:17 -0800120 // Speaker volume controls
121 virtual int32_t SpeakerVolumeIsAvailable(bool& available);
122 virtual int32_t SetSpeakerVolume(uint32_t volume);
123 virtual int32_t SpeakerVolume(uint32_t& volume) const;
124 virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const;
125 virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const;
xians@google.com68efa212011-08-11 12:41:56 +0000126
andrew2bc63a12016-01-11 15:59:17 -0800127 // Microphone volume controls
128 virtual int32_t MicrophoneVolumeIsAvailable(bool& available);
129 virtual int32_t SetMicrophoneVolume(uint32_t volume);
130 virtual int32_t MicrophoneVolume(uint32_t& volume) const;
131 virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const;
132 virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const;
xians@google.com68efa212011-08-11 12:41:56 +0000133
andrew2bc63a12016-01-11 15:59:17 -0800134 // Microphone mute control
135 virtual int32_t MicrophoneMuteIsAvailable(bool& available);
136 virtual int32_t SetMicrophoneMute(bool enable);
137 virtual int32_t MicrophoneMute(bool& enabled) const;
xians@google.com68efa212011-08-11 12:41:56 +0000138
andrew2bc63a12016-01-11 15:59:17 -0800139 // Speaker mute control
140 virtual int32_t SpeakerMuteIsAvailable(bool& available);
141 virtual int32_t SetSpeakerMute(bool enable);
142 virtual int32_t SpeakerMute(bool& enabled) const;
xians@google.com68efa212011-08-11 12:41:56 +0000143
andrew2bc63a12016-01-11 15:59:17 -0800144 // Stereo support
145 virtual int32_t StereoPlayoutIsAvailable(bool& available);
146 virtual int32_t SetStereoPlayout(bool enable);
147 virtual int32_t StereoPlayout(bool& enabled) const;
148 virtual int32_t StereoRecordingIsAvailable(bool& available);
149 virtual int32_t SetStereoRecording(bool enable);
150 virtual int32_t StereoRecording(bool& enabled) const;
xians@google.com68efa212011-08-11 12:41:56 +0000151
andrew2bc63a12016-01-11 15:59:17 -0800152 // Delay information and control
andrew2bc63a12016-01-11 15:59:17 -0800153 virtual int32_t PlayoutDelay(uint16_t& delayMS) const;
xians@google.com68efa212011-08-11 12:41:56 +0000154
andrew2bc63a12016-01-11 15:59:17 -0800155 virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);
xians@google.com68efa212011-08-11 12:41:56 +0000156
andrew2bc63a12016-01-11 15:59:17 -0800157 private:
158 virtual int32_t MicrophoneIsAvailable(bool& available);
159 virtual int32_t SpeakerIsAvailable(bool& available);
andrew@webrtc.orgc7c432a2014-04-02 16:49:26 +0000160
andrew2bc63a12016-01-11 15:59:17 -0800161 static void AtomicSet32(int32_t* theValue, int32_t newValue);
162 static int32_t AtomicGet32(int32_t* theValue);
xians@google.com68efa212011-08-11 12:41:56 +0000163
sazab4aa4eb2017-07-19 01:12:36 -0700164 static void logCAMsg(const rtc::LoggingSeverity sev,
andrew2bc63a12016-01-11 15:59:17 -0800165 const char* msg,
166 const char* err);
xians@google.com68efa212011-08-11 12:41:56 +0000167
andrew2bc63a12016-01-11 15:59:17 -0800168 int32_t GetNumberDevices(const AudioObjectPropertyScope scope,
169 AudioDeviceID scopedDeviceIds[],
170 const uint32_t deviceListLength);
xians@google.com68efa212011-08-11 12:41:56 +0000171
andrew2bc63a12016-01-11 15:59:17 -0800172 int32_t GetDeviceName(const AudioObjectPropertyScope scope,
173 const uint16_t index,
174 char* name);
xians@google.com68efa212011-08-11 12:41:56 +0000175
andrew2bc63a12016-01-11 15:59:17 -0800176 int32_t InitDevice(uint16_t userDeviceIndex,
177 AudioDeviceID& deviceId,
178 bool isInput);
xians@google.com68efa212011-08-11 12:41:56 +0000179
andrew2bc63a12016-01-11 15:59:17 -0800180 // Always work with our preferred playout format inside VoE.
181 // Then convert the output to the OS setting using an AudioConverter.
182 OSStatus SetDesiredPlayoutFormat();
braveyao@webrtc.org346a64b2015-03-21 01:05:56 +0000183
andrew2bc63a12016-01-11 15:59:17 -0800184 static OSStatus objectListenerProc(
185 AudioObjectID objectId,
186 UInt32 numberAddresses,
187 const AudioObjectPropertyAddress addresses[],
188 void* clientData);
xians@google.com68efa212011-08-11 12:41:56 +0000189
andrew2bc63a12016-01-11 15:59:17 -0800190 OSStatus implObjectListenerProc(AudioObjectID objectId,
191 UInt32 numberAddresses,
192 const AudioObjectPropertyAddress addresses[]);
xians@google.com68efa212011-08-11 12:41:56 +0000193
andrew2bc63a12016-01-11 15:59:17 -0800194 int32_t HandleDeviceChange();
xians@google.com68efa212011-08-11 12:41:56 +0000195
andrew2bc63a12016-01-11 15:59:17 -0800196 int32_t HandleStreamFormatChange(AudioObjectID objectId,
197 AudioObjectPropertyAddress propertyAddress);
198
199 int32_t HandleDataSourceChange(AudioObjectID objectId,
xians@google.com68efa212011-08-11 12:41:56 +0000200 AudioObjectPropertyAddress propertyAddress);
201
andrew2bc63a12016-01-11 15:59:17 -0800202 int32_t HandleProcessorOverload(AudioObjectPropertyAddress propertyAddress);
xians@google.com68efa212011-08-11 12:41:56 +0000203
andrew2bc63a12016-01-11 15:59:17 -0800204 static OSStatus deviceIOProc(AudioDeviceID device,
205 const AudioTimeStamp* now,
206 const AudioBufferList* inputData,
207 const AudioTimeStamp* inputTime,
208 AudioBufferList* outputData,
209 const AudioTimeStamp* outputTime,
210 void* clientData);
xians@google.com68efa212011-08-11 12:41:56 +0000211
andrew2bc63a12016-01-11 15:59:17 -0800212 static OSStatus outConverterProc(
213 AudioConverterRef audioConverter,
214 UInt32* numberDataPackets,
215 AudioBufferList* data,
216 AudioStreamPacketDescription** dataPacketDescription,
217 void* userData);
218
219 static OSStatus inDeviceIOProc(AudioDeviceID device,
220 const AudioTimeStamp* now,
221 const AudioBufferList* inputData,
222 const AudioTimeStamp* inputTime,
223 AudioBufferList* outputData,
xians@google.com68efa212011-08-11 12:41:56 +0000224 const AudioTimeStamp* outputTime,
andrew2bc63a12016-01-11 15:59:17 -0800225 void* clientData);
xians@google.com68efa212011-08-11 12:41:56 +0000226
andrew2bc63a12016-01-11 15:59:17 -0800227 static OSStatus inConverterProc(
228 AudioConverterRef audioConverter,
229 UInt32* numberDataPackets,
230 AudioBufferList* data,
231 AudioStreamPacketDescription** dataPacketDescription,
232 void* inUserData);
xians@google.com68efa212011-08-11 12:41:56 +0000233
andrew2bc63a12016-01-11 15:59:17 -0800234 OSStatus implDeviceIOProc(const AudioBufferList* inputData,
235 const AudioTimeStamp* inputTime,
236 AudioBufferList* outputData,
237 const AudioTimeStamp* outputTime);
xians@google.com68efa212011-08-11 12:41:56 +0000238
andrew2bc63a12016-01-11 15:59:17 -0800239 OSStatus implOutConverterProc(UInt32* numberDataPackets,
240 AudioBufferList* data);
xians@google.com68efa212011-08-11 12:41:56 +0000241
andrew2bc63a12016-01-11 15:59:17 -0800242 OSStatus implInDeviceIOProc(const AudioBufferList* inputData,
243 const AudioTimeStamp* inputTime);
xians@google.com68efa212011-08-11 12:41:56 +0000244
andrew2bc63a12016-01-11 15:59:17 -0800245 OSStatus implInConverterProc(UInt32* numberDataPackets,
246 AudioBufferList* data);
xians@google.com68efa212011-08-11 12:41:56 +0000247
andrew2bc63a12016-01-11 15:59:17 -0800248 static bool RunCapture(void*);
249 static bool RunRender(void*);
250 bool CaptureWorkerThread();
251 bool RenderWorkerThread();
xians@google.com68efa212011-08-11 12:41:56 +0000252
andrew2bc63a12016-01-11 15:59:17 -0800253 bool KeyPressed();
xians@google.com68efa212011-08-11 12:41:56 +0000254
andrew2bc63a12016-01-11 15:59:17 -0800255 AudioDeviceBuffer* _ptrAudioBuffer;
xians@google.com68efa212011-08-11 12:41:56 +0000256
kthelgasonff046c72017-03-31 02:03:55 -0700257 rtc::CriticalSection _critSect;
niklas.enbom@webrtc.org3be565b2013-05-07 21:04:24 +0000258
andrew2bc63a12016-01-11 15:59:17 -0800259 EventWrapper& _stopEventRec;
260 EventWrapper& _stopEvent;
xians@google.com68efa212011-08-11 12:41:56 +0000261
andrew2bc63a12016-01-11 15:59:17 -0800262 // TODO(pbos): Replace with direct members, just start/stop, no need to
263 // recreate the thread.
264 // Only valid/running between calls to StartRecording and StopRecording.
kwibergf01633e2016-02-24 05:00:36 -0800265 std::unique_ptr<rtc::PlatformThread> capture_worker_thread_;
xians@google.com68efa212011-08-11 12:41:56 +0000266
andrew2bc63a12016-01-11 15:59:17 -0800267 // Only valid/running between calls to StartPlayout and StopPlayout.
kwibergf01633e2016-02-24 05:00:36 -0800268 std::unique_ptr<rtc::PlatformThread> render_worker_thread_;
xians@google.com68efa212011-08-11 12:41:56 +0000269
andrew2bc63a12016-01-11 15:59:17 -0800270 AudioMixerManagerMac _mixerManager;
xians@google.com68efa212011-08-11 12:41:56 +0000271
andrew2bc63a12016-01-11 15:59:17 -0800272 uint16_t _inputDeviceIndex;
273 uint16_t _outputDeviceIndex;
274 AudioDeviceID _inputDeviceID;
275 AudioDeviceID _outputDeviceID;
xians@google.com68efa212011-08-11 12:41:56 +0000276#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
andrew2bc63a12016-01-11 15:59:17 -0800277 AudioDeviceIOProcID _inDeviceIOProcID;
278 AudioDeviceIOProcID _deviceIOProcID;
xians@google.com68efa212011-08-11 12:41:56 +0000279#endif
andrew2bc63a12016-01-11 15:59:17 -0800280 bool _inputDeviceIsSpecified;
281 bool _outputDeviceIsSpecified;
xians@google.com68efa212011-08-11 12:41:56 +0000282
andrew2bc63a12016-01-11 15:59:17 -0800283 uint8_t _recChannels;
284 uint8_t _playChannels;
xians@google.com68efa212011-08-11 12:41:56 +0000285
andrew2bc63a12016-01-11 15:59:17 -0800286 Float32* _captureBufData;
287 SInt16* _renderBufData;
xians@google.com68efa212011-08-11 12:41:56 +0000288
andrew2bc63a12016-01-11 15:59:17 -0800289 SInt16 _renderConvertData[PLAY_BUF_SIZE_IN_SAMPLES];
xians@google.com68efa212011-08-11 12:41:56 +0000290
andrew2bc63a12016-01-11 15:59:17 -0800291 bool _initialized;
292 bool _isShutDown;
293 bool _recording;
294 bool _playing;
295 bool _recIsInitialized;
296 bool _playIsInitialized;
297 bool _AGC;
xians@google.com68efa212011-08-11 12:41:56 +0000298
andrew2bc63a12016-01-11 15:59:17 -0800299 // Atomically set varaibles
300 int32_t _renderDeviceIsAlive;
301 int32_t _captureDeviceIsAlive;
xians@google.com68efa212011-08-11 12:41:56 +0000302
andrew2bc63a12016-01-11 15:59:17 -0800303 bool _twoDevices;
304 bool _doStop; // For play if not shared device or play+rec if shared device
305 bool _doStopRec; // For rec if not shared device
306 bool _macBookPro;
307 bool _macBookProPanRight;
xians@google.com68efa212011-08-11 12:41:56 +0000308
andrew2bc63a12016-01-11 15:59:17 -0800309 AudioConverterRef _captureConverter;
310 AudioConverterRef _renderConverter;
xians@google.com68efa212011-08-11 12:41:56 +0000311
andrew2bc63a12016-01-11 15:59:17 -0800312 AudioStreamBasicDescription _outStreamFormat;
313 AudioStreamBasicDescription _outDesiredFormat;
314 AudioStreamBasicDescription _inStreamFormat;
315 AudioStreamBasicDescription _inDesiredFormat;
xians@google.com68efa212011-08-11 12:41:56 +0000316
andrew2bc63a12016-01-11 15:59:17 -0800317 uint32_t _captureLatencyUs;
318 uint32_t _renderLatencyUs;
xians@google.com68efa212011-08-11 12:41:56 +0000319
andrew2bc63a12016-01-11 15:59:17 -0800320 // Atomically set variables
321 mutable int32_t _captureDelayUs;
322 mutable int32_t _renderDelayUs;
xians@google.com68efa212011-08-11 12:41:56 +0000323
andrew2bc63a12016-01-11 15:59:17 -0800324 int32_t _renderDelayOffsetSamples;
xians@google.com68efa212011-08-11 12:41:56 +0000325
andrew2bc63a12016-01-11 15:59:17 -0800326 PaUtilRingBuffer* _paCaptureBuffer;
327 PaUtilRingBuffer* _paRenderBuffer;
xians@google.com68efa212011-08-11 12:41:56 +0000328
andrew2bc63a12016-01-11 15:59:17 -0800329 semaphore_t _renderSemaphore;
330 semaphore_t _captureSemaphore;
xians@google.com68efa212011-08-11 12:41:56 +0000331
andrew2bc63a12016-01-11 15:59:17 -0800332 int _captureBufSizeSamples;
333 int _renderBufSizeSamples;
niklas.enbom@webrtc.orgcc9238e2013-08-15 14:19:12 +0000334
andrew2bc63a12016-01-11 15:59:17 -0800335 // Typing detection
336 // 0x5c is key "9", after that comes function keys.
337 bool prev_key_state_[0x5d];
andrewec80f032016-01-08 01:16:17 -0800338
andrew2bc63a12016-01-11 15:59:17 -0800339 int get_mic_volume_counter_ms_;
xians@google.com68efa212011-08-11 12:41:56 +0000340};
341
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000342} // namespace webrtc
xians@google.com68efa212011-08-11 12:41:56 +0000343
344#endif // MODULES_AUDIO_DEVICE_MAIN_SOURCE_MAC_AUDIO_DEVICE_MAC_H_