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