• 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/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