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 AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_ 12 #define AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_ 13 14 #if (_MSC_VER >= 1400) // only include for VS 2005 and higher 15 16 #include "rtc_base/win32.h" 17 18 #include "modules/audio_device/audio_device_generic.h" 19 20 #include <wmcodecdsp.h> // CLSID_CWMAudioAEC 21 // (must be before audioclient.h) 22 #include <audioclient.h> // WASAPI 23 #include <audiopolicy.h> 24 #include <avrt.h> // Avrt 25 #include <endpointvolume.h> 26 #include <mediaobj.h> // IMediaObject 27 #include <mmdeviceapi.h> // MMDevice 28 29 #include "api/scoped_refptr.h" 30 #include "rtc_base/synchronization/mutex.h" 31 32 // Use Multimedia Class Scheduler Service (MMCSS) to boost the thread priority 33 #pragma comment(lib, "avrt.lib") 34 // AVRT function pointers 35 typedef BOOL(WINAPI* PAvRevertMmThreadCharacteristics)(HANDLE); 36 typedef HANDLE(WINAPI* PAvSetMmThreadCharacteristicsA)(LPCSTR, LPDWORD); 37 typedef BOOL(WINAPI* PAvSetMmThreadPriority)(HANDLE, AVRT_PRIORITY); 38 39 namespace webrtc { 40 41 const float MAX_CORE_SPEAKER_VOLUME = 255.0f; 42 const float MIN_CORE_SPEAKER_VOLUME = 0.0f; 43 const float MAX_CORE_MICROPHONE_VOLUME = 255.0f; 44 const float MIN_CORE_MICROPHONE_VOLUME = 0.0f; 45 const uint16_t CORE_SPEAKER_VOLUME_STEP_SIZE = 1; 46 const uint16_t CORE_MICROPHONE_VOLUME_STEP_SIZE = 1; 47 48 // Utility class which initializes COM in the constructor (STA or MTA), 49 // and uninitializes COM in the destructor. 50 class ScopedCOMInitializer { 51 public: 52 // Enum value provided to initialize the thread as an MTA instead of STA. 53 enum SelectMTA { kMTA }; 54 55 // Constructor for STA initialization. ScopedCOMInitializer()56 ScopedCOMInitializer() { Initialize(COINIT_APARTMENTTHREADED); } 57 58 // Constructor for MTA initialization. ScopedCOMInitializer(SelectMTA mta)59 explicit ScopedCOMInitializer(SelectMTA mta) { 60 Initialize(COINIT_MULTITHREADED); 61 } 62 ~ScopedCOMInitializer()63 ~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) { hr_ = CoInitializeEx(NULL, init); } 72 73 HRESULT hr_; 74 75 ScopedCOMInitializer(const ScopedCOMInitializer&); 76 void operator=(const ScopedCOMInitializer&); 77 }; 78 79 class AudioDeviceWindowsCore : public AudioDeviceGeneric { 80 public: 81 AudioDeviceWindowsCore(); 82 ~AudioDeviceWindowsCore(); 83 84 static bool CoreAudioIsSupported(); 85 86 // Retrieve the currently utilized audio layer 87 virtual int32_t ActiveAudioLayer( 88 AudioDeviceModule::AudioLayer& audioLayer) const; 89 90 // Main initializaton and termination 91 virtual InitStatus Init(); 92 virtual int32_t Terminate(); 93 virtual bool Initialized() const; 94 95 // Device enumeration 96 virtual int16_t PlayoutDevices(); 97 virtual int16_t RecordingDevices(); 98 virtual int32_t PlayoutDeviceName(uint16_t index, 99 char name[kAdmMaxDeviceNameSize], 100 char guid[kAdmMaxGuidSize]); 101 virtual int32_t RecordingDeviceName(uint16_t index, 102 char name[kAdmMaxDeviceNameSize], 103 char guid[kAdmMaxGuidSize]); 104 105 // Device selection 106 virtual int32_t SetPlayoutDevice(uint16_t index); 107 virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device); 108 virtual int32_t SetRecordingDevice(uint16_t index); 109 virtual int32_t SetRecordingDevice( 110 AudioDeviceModule::WindowsDeviceType device); 111 112 // Audio transport initialization 113 virtual int32_t PlayoutIsAvailable(bool& available); 114 virtual int32_t InitPlayout(); 115 virtual bool PlayoutIsInitialized() const; 116 virtual int32_t RecordingIsAvailable(bool& available); 117 virtual int32_t InitRecording(); 118 virtual bool RecordingIsInitialized() const; 119 120 // Audio transport control 121 virtual int32_t StartPlayout(); 122 virtual int32_t StopPlayout(); 123 virtual bool Playing() const; 124 virtual int32_t StartRecording(); 125 virtual int32_t StopRecording(); 126 virtual bool Recording() const; 127 128 // Audio mixer initialization 129 virtual int32_t InitSpeaker(); 130 virtual bool SpeakerIsInitialized() const; 131 virtual int32_t InitMicrophone(); 132 virtual bool MicrophoneIsInitialized() const; 133 134 // Speaker volume controls 135 virtual int32_t SpeakerVolumeIsAvailable(bool& available); 136 virtual int32_t SetSpeakerVolume(uint32_t volume); 137 virtual int32_t SpeakerVolume(uint32_t& volume) const; 138 virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const; 139 virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const; 140 141 // Microphone volume controls 142 virtual int32_t MicrophoneVolumeIsAvailable(bool& available); 143 virtual int32_t SetMicrophoneVolume(uint32_t volume); 144 virtual int32_t MicrophoneVolume(uint32_t& volume) const; 145 virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const; 146 virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const; 147 148 // Speaker mute control 149 virtual int32_t SpeakerMuteIsAvailable(bool& available); 150 virtual int32_t SetSpeakerMute(bool enable); 151 virtual int32_t SpeakerMute(bool& enabled) const; 152 153 // Microphone mute control 154 virtual int32_t MicrophoneMuteIsAvailable(bool& available); 155 virtual int32_t SetMicrophoneMute(bool enable); 156 virtual int32_t MicrophoneMute(bool& enabled) const; 157 158 // Stereo support 159 virtual int32_t StereoPlayoutIsAvailable(bool& available); 160 virtual int32_t SetStereoPlayout(bool enable); 161 virtual int32_t StereoPlayout(bool& enabled) const; 162 virtual int32_t StereoRecordingIsAvailable(bool& available); 163 virtual int32_t SetStereoRecording(bool enable); 164 virtual int32_t StereoRecording(bool& enabled) const; 165 166 // Delay information and control 167 virtual int32_t PlayoutDelay(uint16_t& delayMS) const; 168 169 virtual bool BuiltInAECIsAvailable() const; 170 171 virtual int32_t EnableBuiltInAEC(bool enable); 172 173 public: 174 virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer); 175 176 private: 177 bool KeyPressed() const; 178 179 private: // avrt function pointers 180 PAvRevertMmThreadCharacteristics _PAvRevertMmThreadCharacteristics; 181 PAvSetMmThreadCharacteristicsA _PAvSetMmThreadCharacteristicsA; 182 PAvSetMmThreadPriority _PAvSetMmThreadPriority; 183 HMODULE _avrtLibrary; 184 bool _winSupportAvrt; 185 186 private: // thread functions 187 DWORD InitCaptureThreadPriority(); 188 void RevertCaptureThreadPriority(); 189 static DWORD WINAPI WSAPICaptureThread(LPVOID context); 190 DWORD DoCaptureThread(); 191 192 static DWORD WINAPI WSAPICaptureThreadPollDMO(LPVOID context); 193 DWORD DoCaptureThreadPollDMO(); 194 195 static DWORD WINAPI WSAPIRenderThread(LPVOID context); 196 DWORD DoRenderThread(); 197 198 void _Lock(); 199 void _UnLock(); 200 201 int SetDMOProperties(); 202 203 int SetBoolProperty(IPropertyStore* ptrPS, 204 REFPROPERTYKEY key, 205 VARIANT_BOOL value); 206 207 int SetVtI4Property(IPropertyStore* ptrPS, REFPROPERTYKEY key, LONG value); 208 209 int32_t _EnumerateEndpointDevicesAll(EDataFlow dataFlow) const; 210 void _TraceCOMError(HRESULT hr) const; 211 212 int32_t _RefreshDeviceList(EDataFlow dir); 213 int16_t _DeviceListCount(EDataFlow dir); 214 int32_t _GetDefaultDeviceName(EDataFlow dir, 215 ERole role, 216 LPWSTR szBuffer, 217 int bufferLen); 218 int32_t _GetListDeviceName(EDataFlow dir, 219 int index, 220 LPWSTR szBuffer, 221 int bufferLen); 222 int32_t _GetDeviceName(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen); 223 int32_t _GetListDeviceID(EDataFlow dir, 224 int index, 225 LPWSTR szBuffer, 226 int bufferLen); 227 int32_t _GetDefaultDeviceID(EDataFlow dir, 228 ERole role, 229 LPWSTR szBuffer, 230 int bufferLen); 231 int32_t _GetDefaultDeviceIndex(EDataFlow dir, ERole role, int* index); 232 int32_t _GetDeviceID(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen); 233 int32_t _GetDefaultDevice(EDataFlow dir, ERole role, IMMDevice** ppDevice); 234 int32_t _GetListDevice(EDataFlow dir, int index, IMMDevice** ppDevice); 235 236 int32_t InitRecordingDMO(); 237 238 ScopedCOMInitializer _comInit; 239 AudioDeviceBuffer* _ptrAudioBuffer; 240 mutable Mutex mutex_; 241 mutable Mutex volume_mutex_; 242 243 IMMDeviceEnumerator* _ptrEnumerator; 244 IMMDeviceCollection* _ptrRenderCollection; 245 IMMDeviceCollection* _ptrCaptureCollection; 246 IMMDevice* _ptrDeviceOut; 247 IMMDevice* _ptrDeviceIn; 248 249 IAudioClient* _ptrClientOut; 250 IAudioClient* _ptrClientIn; 251 IAudioRenderClient* _ptrRenderClient; 252 IAudioCaptureClient* _ptrCaptureClient; 253 IAudioEndpointVolume* _ptrCaptureVolume; 254 ISimpleAudioVolume* _ptrRenderSimpleVolume; 255 256 // DirectX Media Object (DMO) for the built-in AEC. 257 rtc::scoped_refptr<IMediaObject> _dmo; 258 rtc::scoped_refptr<IMediaBuffer> _mediaBuffer; 259 bool _builtInAecEnabled; 260 261 HANDLE _hRenderSamplesReadyEvent; 262 HANDLE _hPlayThread; 263 HANDLE _hRenderStartedEvent; 264 HANDLE _hShutdownRenderEvent; 265 266 HANDLE _hCaptureSamplesReadyEvent; 267 HANDLE _hRecThread; 268 HANDLE _hCaptureStartedEvent; 269 HANDLE _hShutdownCaptureEvent; 270 271 HANDLE _hMmTask; 272 273 UINT _playAudioFrameSize; 274 uint32_t _playSampleRate; 275 uint32_t _devicePlaySampleRate; 276 uint32_t _playBlockSize; 277 uint32_t _devicePlayBlockSize; 278 uint32_t _playChannels; 279 uint32_t _sndCardPlayDelay; 280 UINT64 _writtenSamples; 281 UINT64 _readSamples; 282 283 UINT _recAudioFrameSize; 284 uint32_t _recSampleRate; 285 uint32_t _recBlockSize; 286 uint32_t _recChannels; 287 288 uint16_t _recChannelsPrioList[3]; 289 uint16_t _playChannelsPrioList[2]; 290 291 LARGE_INTEGER _perfCounterFreq; 292 double _perfCounterFactor; 293 294 private: 295 bool _initialized; 296 bool _recording; 297 bool _playing; 298 bool _recIsInitialized; 299 bool _playIsInitialized; 300 bool _speakerIsInitialized; 301 bool _microphoneIsInitialized; 302 303 bool _usingInputDeviceIndex; 304 bool _usingOutputDeviceIndex; 305 AudioDeviceModule::WindowsDeviceType _inputDevice; 306 AudioDeviceModule::WindowsDeviceType _outputDevice; 307 uint16_t _inputDeviceIndex; 308 uint16_t _outputDeviceIndex; 309 }; 310 311 #endif // #if (_MSC_VER >= 1400) 312 313 } // namespace webrtc 314 315 #endif // AUDIO_DEVICE_AUDIO_DEVICE_CORE_WIN_H_ 316