Home | History | Annotate | Download | only in win
      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_CORE_WIN_H_
     12 #define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_
     13 
     14 #if (_MSC_VER >= 1400)  // only include for VS 2005 and higher
     15 
     16 #include "webrtc/modules/audio_device/audio_device_generic.h"
     17 
     18 #include <wmcodecdsp.h>      // CLSID_CWMAudioAEC
     19                              // (must be before audioclient.h)
     20 #include <Audioclient.h>     // WASAPI
     21 #include <Audiopolicy.h>
     22 #include <Mmdeviceapi.h>     // MMDevice
     23 #include <avrt.h>            // Avrt
     24 #include <endpointvolume.h>
     25 #include <mediaobj.h>        // IMediaObject
     26 
     27 #include "webrtc/base/scoped_ref_ptr.h"
     28 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
     29 
     30 // Use Multimedia Class Scheduler Service (MMCSS) to boost the thread priority
     31 #pragma comment( lib, "avrt.lib" )
     32 // AVRT function pointers
     33 typedef BOOL (WINAPI *PAvRevertMmThreadCharacteristics)(HANDLE);
     34 typedef HANDLE (WINAPI *PAvSetMmThreadCharacteristicsA)(LPCSTR, LPDWORD);
     35 typedef BOOL (WINAPI *PAvSetMmThreadPriority)(HANDLE, AVRT_PRIORITY);
     36 
     37 namespace webrtc {
     38 
     39 const float MAX_CORE_SPEAKER_VOLUME = 255.0f;
     40 const float MIN_CORE_SPEAKER_VOLUME = 0.0f;
     41 const float MAX_CORE_MICROPHONE_VOLUME = 255.0f;
     42 const float MIN_CORE_MICROPHONE_VOLUME = 0.0f;
     43 const uint16_t CORE_SPEAKER_VOLUME_STEP_SIZE = 1;
     44 const uint16_t CORE_MICROPHONE_VOLUME_STEP_SIZE = 1;
     45 
     46 // Utility class which initializes COM in the constructor (STA or MTA),
     47 // and uninitializes COM in the destructor.
     48 class ScopedCOMInitializer {
     49  public:
     50   // Enum value provided to initialize the thread as an MTA instead of STA.
     51   enum SelectMTA { kMTA };
     52 
     53   // Constructor for STA initialization.
     54   ScopedCOMInitializer() {
     55     Initialize(COINIT_APARTMENTTHREADED);
     56   }
     57 
     58   // Constructor for MTA initialization.
     59   explicit ScopedCOMInitializer(SelectMTA mta) {
     60     Initialize(COINIT_MULTITHREADED);
     61   }
     62 
     63   ScopedCOMInitializer::~ScopedCOMInitializer() {
     64     if (SUCCEEDED(hr_))
     65       CoUninitialize();
     66   }
     67 
     68   bool succeeded() const { return SUCCEEDED(hr_); }
     69 
     70  private:
     71   void Initialize(COINIT init) {
     72     hr_ = CoInitializeEx(NULL, init);
     73   }
     74 
     75   HRESULT hr_;
     76 
     77   ScopedCOMInitializer(const ScopedCOMInitializer&);
     78   void operator=(const ScopedCOMInitializer&);
     79 };
     80 
     81 
     82 class AudioDeviceWindowsCore : public AudioDeviceGeneric
     83 {
     84 public:
     85     AudioDeviceWindowsCore(const int32_t id);
     86     ~AudioDeviceWindowsCore();
     87 
     88     static bool CoreAudioIsSupported();
     89 
     90     // Retrieve the currently utilized audio layer
     91     virtual int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const;
     92 
     93     // Main initializaton and termination
     94     virtual int32_t Init();
     95     virtual int32_t Terminate();
     96     virtual bool Initialized() const;
     97 
     98     // Device enumeration
     99     virtual int16_t PlayoutDevices();
    100     virtual int16_t RecordingDevices();
    101     virtual int32_t PlayoutDeviceName(
    102         uint16_t index,
    103         char name[kAdmMaxDeviceNameSize],
    104         char guid[kAdmMaxGuidSize]);
    105     virtual int32_t RecordingDeviceName(
    106         uint16_t index,
    107         char name[kAdmMaxDeviceNameSize],
    108         char guid[kAdmMaxGuidSize]);
    109 
    110     // Device selection
    111     virtual int32_t SetPlayoutDevice(uint16_t index);
    112     virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device);
    113     virtual int32_t SetRecordingDevice(uint16_t index);
    114     virtual int32_t SetRecordingDevice(AudioDeviceModule::WindowsDeviceType device);
    115 
    116     // Audio transport initialization
    117     virtual int32_t PlayoutIsAvailable(bool& available);
    118     virtual int32_t InitPlayout();
    119     virtual bool PlayoutIsInitialized() const;
    120     virtual int32_t RecordingIsAvailable(bool& available);
    121     virtual int32_t InitRecording();
    122     virtual bool RecordingIsInitialized() const;
    123 
    124     // Audio transport control
    125     virtual int32_t StartPlayout();
    126     virtual int32_t StopPlayout();
    127     virtual bool Playing() const;
    128     virtual int32_t StartRecording();
    129     virtual int32_t StopRecording();
    130     virtual bool Recording() const;
    131 
    132     // Microphone Automatic Gain Control (AGC)
    133     virtual int32_t SetAGC(bool enable);
    134     virtual bool AGC() const;
    135 
    136     // Volume control based on the Windows Wave API (Windows only)
    137     virtual int32_t SetWaveOutVolume(uint16_t volumeLeft, uint16_t volumeRight);
    138     virtual int32_t WaveOutVolume(uint16_t& volumeLeft, uint16_t& volumeRight) const;
    139 
    140     // Audio mixer initialization
    141     virtual int32_t InitSpeaker();
    142     virtual bool SpeakerIsInitialized() const;
    143     virtual int32_t InitMicrophone();
    144     virtual bool MicrophoneIsInitialized() const;
    145 
    146     // Speaker volume controls
    147     virtual int32_t SpeakerVolumeIsAvailable(bool& available);
    148     virtual int32_t SetSpeakerVolume(uint32_t volume);
    149     virtual int32_t SpeakerVolume(uint32_t& volume) const;
    150     virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const;
    151     virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const;
    152     virtual int32_t SpeakerVolumeStepSize(uint16_t& stepSize) const;
    153 
    154     // Microphone volume controls
    155     virtual int32_t MicrophoneVolumeIsAvailable(bool& available);
    156     virtual int32_t SetMicrophoneVolume(uint32_t volume);
    157     virtual int32_t MicrophoneVolume(uint32_t& volume) const;
    158     virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const;
    159     virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const;
    160     virtual int32_t MicrophoneVolumeStepSize(uint16_t& stepSize) const;
    161 
    162     // Speaker mute control
    163     virtual int32_t SpeakerMuteIsAvailable(bool& available);
    164     virtual int32_t SetSpeakerMute(bool enable);
    165     virtual int32_t SpeakerMute(bool& enabled) const;
    166 
    167     // Microphone mute control
    168     virtual int32_t MicrophoneMuteIsAvailable(bool& available);
    169     virtual int32_t SetMicrophoneMute(bool enable);
    170     virtual int32_t MicrophoneMute(bool& enabled) const;
    171 
    172     // Microphone boost control
    173     virtual int32_t MicrophoneBoostIsAvailable(bool& available);
    174     virtual int32_t SetMicrophoneBoost(bool enable);
    175     virtual int32_t MicrophoneBoost(bool& enabled) const;
    176 
    177     // Stereo support
    178     virtual int32_t StereoPlayoutIsAvailable(bool& available);
    179     virtual int32_t SetStereoPlayout(bool enable);
    180     virtual int32_t StereoPlayout(bool& enabled) const;
    181     virtual int32_t StereoRecordingIsAvailable(bool& available);
    182     virtual int32_t SetStereoRecording(bool enable);
    183     virtual int32_t StereoRecording(bool& enabled) const;
    184 
    185     // Delay information and control
    186     virtual int32_t SetPlayoutBuffer(const AudioDeviceModule::BufferType type, uint16_t sizeMS);
    187     virtual int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type, uint16_t& sizeMS) const;
    188     virtual int32_t PlayoutDelay(uint16_t& delayMS) const;
    189     virtual int32_t RecordingDelay(uint16_t& delayMS) const;
    190 
    191     // CPU load
    192     virtual int32_t CPULoad(uint16_t& load) const;
    193 
    194     virtual int32_t EnableBuiltInAEC(bool enable);
    195     virtual bool BuiltInAECIsEnabled() const;
    196 
    197 public:
    198     virtual bool PlayoutWarning() const;
    199     virtual bool PlayoutError() const;
    200     virtual bool RecordingWarning() const;
    201     virtual bool RecordingError() const;
    202     virtual void ClearPlayoutWarning();
    203     virtual void ClearPlayoutError();
    204     virtual void ClearRecordingWarning();
    205     virtual void ClearRecordingError();
    206 
    207 public:
    208     virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);
    209 
    210 private:
    211     bool KeyPressed() const;
    212 
    213 private:    // avrt function pointers
    214     PAvRevertMmThreadCharacteristics    _PAvRevertMmThreadCharacteristics;
    215     PAvSetMmThreadCharacteristicsA      _PAvSetMmThreadCharacteristicsA;
    216     PAvSetMmThreadPriority              _PAvSetMmThreadPriority;
    217     HMODULE                             _avrtLibrary;
    218     bool                                _winSupportAvrt;
    219 
    220 private:    // thread functions
    221     DWORD InitCaptureThreadPriority();
    222     void RevertCaptureThreadPriority();
    223     static DWORD WINAPI WSAPICaptureThread(LPVOID context);
    224     DWORD DoCaptureThread();
    225 
    226     static DWORD WINAPI WSAPICaptureThreadPollDMO(LPVOID context);
    227     DWORD DoCaptureThreadPollDMO();
    228 
    229     static DWORD WINAPI WSAPIRenderThread(LPVOID context);
    230     DWORD DoRenderThread();
    231 
    232     static DWORD WINAPI GetCaptureVolumeThread(LPVOID context);
    233     DWORD DoGetCaptureVolumeThread();
    234 
    235     static DWORD WINAPI SetCaptureVolumeThread(LPVOID context);
    236     DWORD DoSetCaptureVolumeThread();
    237 
    238     void _Lock() { _critSect.Enter(); };
    239     void _UnLock() { _critSect.Leave(); };
    240 
    241 private:
    242     int32_t Id() {return _id;}
    243 
    244 private:
    245     int SetDMOProperties();
    246 
    247     int SetBoolProperty(IPropertyStore* ptrPS,
    248                         REFPROPERTYKEY key,
    249                         VARIANT_BOOL value);
    250 
    251     int SetVtI4Property(IPropertyStore* ptrPS,
    252                         REFPROPERTYKEY key,
    253                         LONG value);
    254 
    255     int32_t _EnumerateEndpointDevicesAll(EDataFlow dataFlow) const;
    256     void _TraceCOMError(HRESULT hr) const;
    257 
    258     int32_t _RefreshDeviceList(EDataFlow dir);
    259     int16_t _DeviceListCount(EDataFlow dir);
    260     int32_t _GetDefaultDeviceName(EDataFlow dir, ERole role, LPWSTR szBuffer, int bufferLen);
    261     int32_t _GetListDeviceName(EDataFlow dir, int index, LPWSTR szBuffer, int bufferLen);
    262     int32_t _GetDeviceName(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen);
    263     int32_t _GetListDeviceID(EDataFlow dir, int index, LPWSTR szBuffer, int bufferLen);
    264     int32_t _GetDefaultDeviceID(EDataFlow dir, ERole role, LPWSTR szBuffer, int bufferLen);
    265     int32_t _GetDefaultDeviceIndex(EDataFlow dir, ERole role, int* index);
    266     int32_t _GetDeviceID(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen);
    267     int32_t _GetDefaultDevice(EDataFlow dir, ERole role, IMMDevice** ppDevice);
    268     int32_t _GetListDevice(EDataFlow dir, int index, IMMDevice** ppDevice);
    269 
    270     // Converts from wide-char to UTF-8 if UNICODE is defined.
    271     // Does nothing if UNICODE is undefined.
    272     char* WideToUTF8(const TCHAR* src) const;
    273 
    274     int32_t InitRecordingDMO();
    275 
    276 private:
    277     ScopedCOMInitializer                    _comInit;
    278     AudioDeviceBuffer*                      _ptrAudioBuffer;
    279     CriticalSectionWrapper&                 _critSect;
    280     CriticalSectionWrapper&                 _volumeMutex;
    281     int32_t                           _id;
    282 
    283 private:  // MMDevice
    284     IMMDeviceEnumerator*                    _ptrEnumerator;
    285     IMMDeviceCollection*                    _ptrRenderCollection;
    286     IMMDeviceCollection*                    _ptrCaptureCollection;
    287     IMMDevice*                              _ptrDeviceOut;
    288     IMMDevice*                              _ptrDeviceIn;
    289 
    290 private:  // WASAPI
    291     IAudioClient*                           _ptrClientOut;
    292     IAudioClient*                           _ptrClientIn;
    293     IAudioRenderClient*                     _ptrRenderClient;
    294     IAudioCaptureClient*                    _ptrCaptureClient;
    295     IAudioEndpointVolume*                   _ptrCaptureVolume;
    296     ISimpleAudioVolume*                     _ptrRenderSimpleVolume;
    297 
    298     // DirectX Media Object (DMO) for the built-in AEC.
    299     rtc::scoped_refptr<IMediaObject> _dmo;
    300     rtc::scoped_refptr<IMediaBuffer> _mediaBuffer;
    301     bool                                    _builtInAecEnabled;
    302 
    303     HANDLE                                  _hRenderSamplesReadyEvent;
    304     HANDLE                                  _hPlayThread;
    305     HANDLE                                  _hRenderStartedEvent;
    306     HANDLE                                  _hShutdownRenderEvent;
    307 
    308     HANDLE                                  _hCaptureSamplesReadyEvent;
    309     HANDLE                                  _hRecThread;
    310     HANDLE                                  _hCaptureStartedEvent;
    311     HANDLE                                  _hShutdownCaptureEvent;
    312 
    313     HANDLE                                  _hGetCaptureVolumeThread;
    314     HANDLE                                  _hSetCaptureVolumeThread;
    315     HANDLE                                  _hSetCaptureVolumeEvent;
    316 
    317     HANDLE                                  _hMmTask;
    318 
    319     UINT                                    _playAudioFrameSize;
    320     uint32_t                          _playSampleRate;
    321     uint32_t                          _devicePlaySampleRate;
    322     uint32_t                          _playBlockSize;
    323     uint32_t                          _devicePlayBlockSize;
    324     uint32_t                          _playChannels;
    325     uint32_t                          _sndCardPlayDelay;
    326     UINT64                                  _writtenSamples;
    327     LONGLONG                                _playAcc;
    328 
    329     UINT                                    _recAudioFrameSize;
    330     uint32_t                          _recSampleRate;
    331     uint32_t                          _recBlockSize;
    332     uint32_t                          _recChannels;
    333     UINT64                                  _readSamples;
    334     uint32_t                          _sndCardRecDelay;
    335 
    336     uint16_t                          _recChannelsPrioList[2];
    337     uint16_t                          _playChannelsPrioList[2];
    338 
    339     LARGE_INTEGER                           _perfCounterFreq;
    340     double                                  _perfCounterFactor;
    341     float                                   _avgCPULoad;
    342 
    343 private:
    344     bool                                    _initialized;
    345     bool                                    _recording;
    346     bool                                    _playing;
    347     bool                                    _recIsInitialized;
    348     bool                                    _playIsInitialized;
    349     bool                                    _speakerIsInitialized;
    350     bool                                    _microphoneIsInitialized;
    351 
    352     bool                                    _usingInputDeviceIndex;
    353     bool                                    _usingOutputDeviceIndex;
    354     AudioDeviceModule::WindowsDeviceType    _inputDevice;
    355     AudioDeviceModule::WindowsDeviceType    _outputDevice;
    356     uint16_t                          _inputDeviceIndex;
    357     uint16_t                          _outputDeviceIndex;
    358 
    359     bool                                    _AGC;
    360 
    361     uint16_t                          _playWarning;
    362     uint16_t                          _playError;
    363     uint16_t                          _recWarning;
    364     uint16_t                          _recError;
    365 
    366     AudioDeviceModule::BufferType           _playBufType;
    367     uint16_t                          _playBufDelay;
    368     uint16_t                          _playBufDelayFixed;
    369 
    370     uint16_t                          _newMicLevel;
    371 
    372     mutable char                            _str[512];
    373 };
    374 
    375 #endif    // #if (_MSC_VER >= 1400)
    376 
    377 }  // namespace webrtc
    378 
    379 #endif  // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_
    380