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