Home | History | Annotate | Download | only in mac
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      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 
     11 #ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_MAC_H
     12 #define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_MAC_H
     13 
     14 #include "webrtc/base/scoped_ptr.h"
     15 #include "webrtc/base/thread_annotations.h"
     16 #include "webrtc/modules/audio_device/audio_device_generic.h"
     17 #include "webrtc/modules/audio_device/mac/audio_mixer_manager_mac.h"
     18 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
     19 
     20 #include <AudioToolbox/AudioConverter.h>
     21 #include <CoreAudio/CoreAudio.h>
     22 #include <mach/semaphore.h>
     23 
     24 struct PaUtilRingBuffer;
     25 
     26 namespace rtc {
     27 class PlatformThread;
     28 }  // namespace rtc
     29 
     30 namespace webrtc {
     31 class EventWrapper;
     32 
     33 const uint32_t N_REC_SAMPLES_PER_SEC = 48000;
     34 const uint32_t N_PLAY_SAMPLES_PER_SEC = 48000;
     35 
     36 const uint32_t N_REC_CHANNELS = 1;   // default is mono recording
     37 const uint32_t N_PLAY_CHANNELS = 2;  // default is stereo playout
     38 const uint32_t N_DEVICE_CHANNELS = 64;
     39 
     40 const int kBufferSizeMs = 10;
     41 
     42 const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES =
     43     N_REC_SAMPLES_PER_SEC * kBufferSizeMs / 1000;
     44 const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES =
     45     N_PLAY_SAMPLES_PER_SEC * kBufferSizeMs / 1000;
     46 
     47 const int N_BLOCKS_IO = 2;
     48 const int N_BUFFERS_IN = 2;   // Must be at least N_BLOCKS_IO.
     49 const int N_BUFFERS_OUT = 3;  // Must be at least N_BLOCKS_IO.
     50 
     51 const uint32_t TIMER_PERIOD_MS = 2 * 10 * N_BLOCKS_IO * 1000000;
     52 
     53 const uint32_t REC_BUF_SIZE_IN_SAMPLES =
     54     ENGINE_REC_BUF_SIZE_IN_SAMPLES * N_DEVICE_CHANNELS * N_BUFFERS_IN;
     55 const uint32_t PLAY_BUF_SIZE_IN_SAMPLES =
     56     ENGINE_PLAY_BUF_SIZE_IN_SAMPLES * N_PLAY_CHANNELS * N_BUFFERS_OUT;
     57 
     58 const int kGetMicVolumeIntervalMs = 1000;
     59 
     60 class AudioDeviceMac : public AudioDeviceGeneric {
     61  public:
     62   AudioDeviceMac(const int32_t id);
     63   ~AudioDeviceMac();
     64 
     65   // Retrieve the currently utilized audio layer
     66   virtual int32_t ActiveAudioLayer(
     67       AudioDeviceModule::AudioLayer& audioLayer) const;
     68 
     69   // Main initializaton and termination
     70   virtual int32_t Init();
     71   virtual int32_t Terminate();
     72   virtual bool Initialized() const;
     73 
     74   // Device enumeration
     75   virtual int16_t PlayoutDevices();
     76   virtual int16_t RecordingDevices();
     77   virtual int32_t PlayoutDeviceName(uint16_t index,
     78                                     char name[kAdmMaxDeviceNameSize],
     79                                     char guid[kAdmMaxGuidSize]);
     80   virtual int32_t RecordingDeviceName(uint16_t index,
     81                                       char name[kAdmMaxDeviceNameSize],
     82                                       char guid[kAdmMaxGuidSize]);
     83 
     84   // Device selection
     85   virtual int32_t SetPlayoutDevice(uint16_t index);
     86   virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device);
     87   virtual int32_t SetRecordingDevice(uint16_t index);
     88   virtual int32_t SetRecordingDevice(
     89       AudioDeviceModule::WindowsDeviceType device);
     90 
     91   // Audio transport initialization
     92   virtual int32_t PlayoutIsAvailable(bool& available);
     93   virtual int32_t InitPlayout();
     94   virtual bool PlayoutIsInitialized() const;
     95   virtual int32_t RecordingIsAvailable(bool& available);
     96   virtual int32_t InitRecording();
     97   virtual bool RecordingIsInitialized() const;
     98 
     99   // Audio transport control
    100   virtual int32_t StartPlayout();
    101   virtual int32_t StopPlayout();
    102   virtual bool Playing() const;
    103   virtual int32_t StartRecording();
    104   virtual int32_t StopRecording();
    105   virtual bool Recording() const;
    106 
    107   // Microphone Automatic Gain Control (AGC)
    108   virtual int32_t SetAGC(bool enable);
    109   virtual bool AGC() const;
    110 
    111   // Volume control based on the Windows Wave API (Windows only)
    112   virtual int32_t SetWaveOutVolume(uint16_t volumeLeft, uint16_t volumeRight);
    113   virtual int32_t WaveOutVolume(uint16_t& volumeLeft,
    114                                 uint16_t& volumeRight) const;
    115 
    116   // Audio mixer initialization
    117   virtual int32_t InitSpeaker();
    118   virtual bool SpeakerIsInitialized() const;
    119   virtual int32_t InitMicrophone();
    120   virtual bool MicrophoneIsInitialized() const;
    121 
    122   // Speaker volume controls
    123   virtual int32_t SpeakerVolumeIsAvailable(bool& available);
    124   virtual int32_t SetSpeakerVolume(uint32_t volume);
    125   virtual int32_t SpeakerVolume(uint32_t& volume) const;
    126   virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const;
    127   virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const;
    128   virtual int32_t SpeakerVolumeStepSize(uint16_t& stepSize) const;
    129 
    130   // Microphone volume controls
    131   virtual int32_t MicrophoneVolumeIsAvailable(bool& available);
    132   virtual int32_t SetMicrophoneVolume(uint32_t volume);
    133   virtual int32_t MicrophoneVolume(uint32_t& volume) const;
    134   virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const;
    135   virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const;
    136   virtual int32_t MicrophoneVolumeStepSize(uint16_t& stepSize) const;
    137 
    138   // Microphone mute control
    139   virtual int32_t MicrophoneMuteIsAvailable(bool& available);
    140   virtual int32_t SetMicrophoneMute(bool enable);
    141   virtual int32_t MicrophoneMute(bool& enabled) const;
    142 
    143   // Speaker mute control
    144   virtual int32_t SpeakerMuteIsAvailable(bool& available);
    145   virtual int32_t SetSpeakerMute(bool enable);
    146   virtual int32_t SpeakerMute(bool& enabled) const;
    147 
    148   // Microphone boost control
    149   virtual int32_t MicrophoneBoostIsAvailable(bool& available);
    150   virtual int32_t SetMicrophoneBoost(bool enable);
    151   virtual int32_t MicrophoneBoost(bool& enabled) const;
    152 
    153   // Stereo support
    154   virtual int32_t StereoPlayoutIsAvailable(bool& available);
    155   virtual int32_t SetStereoPlayout(bool enable);
    156   virtual int32_t StereoPlayout(bool& enabled) const;
    157   virtual int32_t StereoRecordingIsAvailable(bool& available);
    158   virtual int32_t SetStereoRecording(bool enable);
    159   virtual int32_t StereoRecording(bool& enabled) const;
    160 
    161   // Delay information and control
    162   virtual int32_t SetPlayoutBuffer(const AudioDeviceModule::BufferType type,
    163                                    uint16_t sizeMS);
    164   virtual int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type,
    165                                 uint16_t& sizeMS) const;
    166   virtual int32_t PlayoutDelay(uint16_t& delayMS) const;
    167   virtual int32_t RecordingDelay(uint16_t& delayMS) const;
    168 
    169   // CPU load
    170   virtual int32_t CPULoad(uint16_t& load) const;
    171 
    172   virtual bool PlayoutWarning() const;
    173   virtual bool PlayoutError() const;
    174   virtual bool RecordingWarning() const;
    175   virtual bool RecordingError() const;
    176   virtual void ClearPlayoutWarning();
    177   virtual void ClearPlayoutError();
    178   virtual void ClearRecordingWarning();
    179   virtual void ClearRecordingError();
    180 
    181   virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);
    182 
    183  private:
    184   virtual int32_t MicrophoneIsAvailable(bool& available);
    185   virtual int32_t SpeakerIsAvailable(bool& available);
    186 
    187   static void AtomicSet32(int32_t* theValue, int32_t newValue);
    188   static int32_t AtomicGet32(int32_t* theValue);
    189 
    190   static void logCAMsg(const TraceLevel level,
    191                        const TraceModule module,
    192                        const int32_t id,
    193                        const char* msg,
    194                        const char* err);
    195 
    196   int32_t GetNumberDevices(const AudioObjectPropertyScope scope,
    197                            AudioDeviceID scopedDeviceIds[],
    198                            const uint32_t deviceListLength);
    199 
    200   int32_t GetDeviceName(const AudioObjectPropertyScope scope,
    201                         const uint16_t index,
    202                         char* name);
    203 
    204   int32_t InitDevice(uint16_t userDeviceIndex,
    205                      AudioDeviceID& deviceId,
    206                      bool isInput);
    207 
    208   // Always work with our preferred playout format inside VoE.
    209   // Then convert the output to the OS setting using an AudioConverter.
    210   OSStatus SetDesiredPlayoutFormat();
    211 
    212   static OSStatus objectListenerProc(
    213       AudioObjectID objectId,
    214       UInt32 numberAddresses,
    215       const AudioObjectPropertyAddress addresses[],
    216       void* clientData);
    217 
    218   OSStatus implObjectListenerProc(AudioObjectID objectId,
    219                                   UInt32 numberAddresses,
    220                                   const AudioObjectPropertyAddress addresses[]);
    221 
    222   int32_t HandleDeviceChange();
    223 
    224   int32_t HandleStreamFormatChange(AudioObjectID objectId,
    225                                    AudioObjectPropertyAddress propertyAddress);
    226 
    227   int32_t HandleDataSourceChange(AudioObjectID objectId,
    228                                  AudioObjectPropertyAddress propertyAddress);
    229 
    230   int32_t HandleProcessorOverload(AudioObjectPropertyAddress propertyAddress);
    231 
    232   static OSStatus deviceIOProc(AudioDeviceID device,
    233                                const AudioTimeStamp* now,
    234                                const AudioBufferList* inputData,
    235                                const AudioTimeStamp* inputTime,
    236                                AudioBufferList* outputData,
    237                                const AudioTimeStamp* outputTime,
    238                                void* clientData);
    239 
    240   static OSStatus outConverterProc(
    241       AudioConverterRef audioConverter,
    242       UInt32* numberDataPackets,
    243       AudioBufferList* data,
    244       AudioStreamPacketDescription** dataPacketDescription,
    245       void* userData);
    246 
    247   static OSStatus inDeviceIOProc(AudioDeviceID device,
    248                                  const AudioTimeStamp* now,
    249                                  const AudioBufferList* inputData,
    250                                  const AudioTimeStamp* inputTime,
    251                                  AudioBufferList* outputData,
    252                                  const AudioTimeStamp* outputTime,
    253                                  void* clientData);
    254 
    255   static OSStatus inConverterProc(
    256       AudioConverterRef audioConverter,
    257       UInt32* numberDataPackets,
    258       AudioBufferList* data,
    259       AudioStreamPacketDescription** dataPacketDescription,
    260       void* inUserData);
    261 
    262   OSStatus implDeviceIOProc(const AudioBufferList* inputData,
    263                             const AudioTimeStamp* inputTime,
    264                             AudioBufferList* outputData,
    265                             const AudioTimeStamp* outputTime);
    266 
    267   OSStatus implOutConverterProc(UInt32* numberDataPackets,
    268                                 AudioBufferList* data);
    269 
    270   OSStatus implInDeviceIOProc(const AudioBufferList* inputData,
    271                               const AudioTimeStamp* inputTime);
    272 
    273   OSStatus implInConverterProc(UInt32* numberDataPackets,
    274                                AudioBufferList* data);
    275 
    276   static bool RunCapture(void*);
    277   static bool RunRender(void*);
    278   bool CaptureWorkerThread();
    279   bool RenderWorkerThread();
    280 
    281   bool KeyPressed();
    282 
    283   AudioDeviceBuffer* _ptrAudioBuffer;
    284 
    285   CriticalSectionWrapper& _critSect;
    286 
    287   EventWrapper& _stopEventRec;
    288   EventWrapper& _stopEvent;
    289 
    290   // TODO(pbos): Replace with direct members, just start/stop, no need to
    291   // recreate the thread.
    292   // Only valid/running between calls to StartRecording and StopRecording.
    293   rtc::scoped_ptr<rtc::PlatformThread> capture_worker_thread_;
    294 
    295   // Only valid/running between calls to StartPlayout and StopPlayout.
    296   rtc::scoped_ptr<rtc::PlatformThread> render_worker_thread_;
    297 
    298   int32_t _id;
    299 
    300   AudioMixerManagerMac _mixerManager;
    301 
    302   uint16_t _inputDeviceIndex;
    303   uint16_t _outputDeviceIndex;
    304   AudioDeviceID _inputDeviceID;
    305   AudioDeviceID _outputDeviceID;
    306 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
    307   AudioDeviceIOProcID _inDeviceIOProcID;
    308   AudioDeviceIOProcID _deviceIOProcID;
    309 #endif
    310   bool _inputDeviceIsSpecified;
    311   bool _outputDeviceIsSpecified;
    312 
    313   uint8_t _recChannels;
    314   uint8_t _playChannels;
    315 
    316   Float32* _captureBufData;
    317   SInt16* _renderBufData;
    318 
    319   SInt16 _renderConvertData[PLAY_BUF_SIZE_IN_SAMPLES];
    320 
    321   AudioDeviceModule::BufferType _playBufType;
    322 
    323   bool _initialized;
    324   bool _isShutDown;
    325   bool _recording;
    326   bool _playing;
    327   bool _recIsInitialized;
    328   bool _playIsInitialized;
    329   bool _AGC;
    330 
    331   // Atomically set varaibles
    332   int32_t _renderDeviceIsAlive;
    333   int32_t _captureDeviceIsAlive;
    334 
    335   bool _twoDevices;
    336   bool _doStop;  // For play if not shared device or play+rec if shared device
    337   bool _doStopRec;  // For rec if not shared device
    338   bool _macBookPro;
    339   bool _macBookProPanRight;
    340 
    341   AudioConverterRef _captureConverter;
    342   AudioConverterRef _renderConverter;
    343 
    344   AudioStreamBasicDescription _outStreamFormat;
    345   AudioStreamBasicDescription _outDesiredFormat;
    346   AudioStreamBasicDescription _inStreamFormat;
    347   AudioStreamBasicDescription _inDesiredFormat;
    348 
    349   uint32_t _captureLatencyUs;
    350   uint32_t _renderLatencyUs;
    351 
    352   // Atomically set variables
    353   mutable int32_t _captureDelayUs;
    354   mutable int32_t _renderDelayUs;
    355 
    356   int32_t _renderDelayOffsetSamples;
    357 
    358   uint16_t _playBufDelayFixed;  // fixed playback delay
    359 
    360   uint16_t _playWarning;
    361   uint16_t _playError;
    362   uint16_t _recWarning;
    363   uint16_t _recError;
    364 
    365   PaUtilRingBuffer* _paCaptureBuffer;
    366   PaUtilRingBuffer* _paRenderBuffer;
    367 
    368   semaphore_t _renderSemaphore;
    369   semaphore_t _captureSemaphore;
    370 
    371   int _captureBufSizeSamples;
    372   int _renderBufSizeSamples;
    373 
    374   // Typing detection
    375   // 0x5c is key "9", after that comes function keys.
    376   bool prev_key_state_[0x5d];
    377 
    378   int get_mic_volume_counter_ms_;
    379 };
    380 
    381 }  // namespace webrtc
    382 
    383 #endif  // MODULES_AUDIO_DEVICE_MAIN_SOURCE_MAC_AUDIO_DEVICE_MAC_H_
    384