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