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/system_wrappers/interface/critical_section_wrapper.h" 28 #include "webrtc/system_wrappers/interface/scoped_refptr.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. ScopedCOMInitializer()54 ScopedCOMInitializer() { 55 Initialize(COINIT_APARTMENTTHREADED); 56 } 57 58 // Constructor for MTA initialization. ScopedCOMInitializer(SelectMTA mta)59 explicit ScopedCOMInitializer(SelectMTA mta) { 60 Initialize(COINIT_MULTITHREADED); 61 } 62 ~ScopedCOMInitializer()63 ScopedCOMInitializer::~ScopedCOMInitializer() { 64 if (SUCCEEDED(hr_)) 65 CoUninitialize(); 66 } 67 succeeded()68 bool succeeded() const { return SUCCEEDED(hr_); } 69 70 private: Initialize(COINIT init)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 _SetThreadName(DWORD dwThreadID, LPCSTR szThreadName); _Lock()239 void _Lock() { _critSect.Enter(); }; _UnLock()240 void _UnLock() { _critSect.Leave(); }; 241 242 private: Id()243 int32_t Id() {return _id;} 244 245 private: 246 int SetDMOProperties(); 247 248 int SetBoolProperty(IPropertyStore* ptrPS, 249 REFPROPERTYKEY key, 250 VARIANT_BOOL value); 251 252 int SetVtI4Property(IPropertyStore* ptrPS, 253 REFPROPERTYKEY key, 254 LONG value); 255 256 int32_t _EnumerateEndpointDevicesAll(EDataFlow dataFlow) const; 257 void _TraceCOMError(HRESULT hr) const; 258 259 int32_t _RefreshDeviceList(EDataFlow dir); 260 int16_t _DeviceListCount(EDataFlow dir); 261 int32_t _GetDefaultDeviceName(EDataFlow dir, ERole role, LPWSTR szBuffer, int bufferLen); 262 int32_t _GetListDeviceName(EDataFlow dir, int index, LPWSTR szBuffer, int bufferLen); 263 int32_t _GetDeviceName(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen); 264 int32_t _GetListDeviceID(EDataFlow dir, int index, LPWSTR szBuffer, int bufferLen); 265 int32_t _GetDefaultDeviceID(EDataFlow dir, ERole role, LPWSTR szBuffer, int bufferLen); 266 int32_t _GetDefaultDeviceIndex(EDataFlow dir, ERole role, int* index); 267 int32_t _GetDeviceID(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen); 268 int32_t _GetDefaultDevice(EDataFlow dir, ERole role, IMMDevice** ppDevice); 269 int32_t _GetListDevice(EDataFlow dir, int index, IMMDevice** ppDevice); 270 271 // Converts from wide-char to UTF-8 if UNICODE is defined. 272 // Does nothing if UNICODE is undefined. 273 char* WideToUTF8(const TCHAR* src) const; 274 275 int32_t InitRecordingDMO(); 276 277 private: 278 ScopedCOMInitializer _comInit; 279 AudioDeviceBuffer* _ptrAudioBuffer; 280 CriticalSectionWrapper& _critSect; 281 CriticalSectionWrapper& _volumeMutex; 282 int32_t _id; 283 284 private: // MMDevice 285 IMMDeviceEnumerator* _ptrEnumerator; 286 IMMDeviceCollection* _ptrRenderCollection; 287 IMMDeviceCollection* _ptrCaptureCollection; 288 IMMDevice* _ptrDeviceOut; 289 IMMDevice* _ptrDeviceIn; 290 291 private: // WASAPI 292 IAudioClient* _ptrClientOut; 293 IAudioClient* _ptrClientIn; 294 IAudioRenderClient* _ptrRenderClient; 295 IAudioCaptureClient* _ptrCaptureClient; 296 IAudioEndpointVolume* _ptrCaptureVolume; 297 ISimpleAudioVolume* _ptrRenderSimpleVolume; 298 299 // DirectX Media Object (DMO) for the built-in AEC. 300 scoped_refptr<IMediaObject> _dmo; 301 scoped_refptr<IMediaBuffer> _mediaBuffer; 302 bool _builtInAecEnabled; 303 304 HANDLE _hRenderSamplesReadyEvent; 305 HANDLE _hPlayThread; 306 HANDLE _hRenderStartedEvent; 307 HANDLE _hShutdownRenderEvent; 308 309 HANDLE _hCaptureSamplesReadyEvent; 310 HANDLE _hRecThread; 311 HANDLE _hCaptureStartedEvent; 312 HANDLE _hShutdownCaptureEvent; 313 314 HANDLE _hGetCaptureVolumeThread; 315 HANDLE _hSetCaptureVolumeThread; 316 HANDLE _hSetCaptureVolumeEvent; 317 318 HANDLE _hMmTask; 319 320 UINT _playAudioFrameSize; 321 uint32_t _playSampleRate; 322 uint32_t _devicePlaySampleRate; 323 uint32_t _playBlockSize; 324 uint32_t _devicePlayBlockSize; 325 uint32_t _playChannels; 326 uint32_t _sndCardPlayDelay; 327 UINT64 _writtenSamples; 328 LONGLONG _playAcc; 329 330 UINT _recAudioFrameSize; 331 uint32_t _recSampleRate; 332 uint32_t _recBlockSize; 333 uint32_t _recChannels; 334 UINT64 _readSamples; 335 uint32_t _sndCardRecDelay; 336 337 uint16_t _recChannelsPrioList[2]; 338 uint16_t _playChannelsPrioList[2]; 339 340 LARGE_INTEGER _perfCounterFreq; 341 double _perfCounterFactor; 342 float _avgCPULoad; 343 344 private: 345 bool _initialized; 346 bool _recording; 347 bool _playing; 348 bool _recIsInitialized; 349 bool _playIsInitialized; 350 bool _speakerIsInitialized; 351 bool _microphoneIsInitialized; 352 353 bool _usingInputDeviceIndex; 354 bool _usingOutputDeviceIndex; 355 AudioDeviceModule::WindowsDeviceType _inputDevice; 356 AudioDeviceModule::WindowsDeviceType _outputDevice; 357 uint16_t _inputDeviceIndex; 358 uint16_t _outputDeviceIndex; 359 360 bool _AGC; 361 362 uint16_t _playWarning; 363 uint16_t _playError; 364 uint16_t _recWarning; 365 uint16_t _recError; 366 367 AudioDeviceModule::BufferType _playBufType; 368 uint16_t _playBufDelay; 369 uint16_t _playBufDelayFixed; 370 371 uint16_t _newMicLevel; 372 373 mutable char _str[512]; 374 }; 375 376 #endif // #if (_MSC_VER >= 1400) 377 378 } // namespace webrtc 379 380 #endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_ 381