• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
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 
_Lock()238     void _Lock() { _critSect.Enter(); };
_UnLock()239     void _UnLock() { _critSect.Leave(); };
240 
241 private:
Id()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