summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/audio_device/win/audio_device_core_win.h
blob: 380effb44908a6c18d111f7ad17693a3e7a6c0d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef MODULES_AUDIO_DEVICE_WIN_AUDIO_DEVICE_CORE_WIN_H_
#define MODULES_AUDIO_DEVICE_WIN_AUDIO_DEVICE_CORE_WIN_H_

#if (_MSC_VER >= 1400)  // only include for VS 2005 and higher

#include <wmcodecdsp.h>  // CLSID_CWMAudioAEC
//(must be before audioclient.h)

#include <audioclient.h>  // WASAPI
#include <audiopolicy.h>
#include <avrt.h>  // Avrt
#include <endpointvolume.h>
#include <mediaobj.h>     // IMediaObject
#include <mmdeviceapi.h>  // MMDevice

#include "api/scoped_refptr.h"
#include "modules/audio_device/audio_device_generic.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/win/scoped_com_initializer.h"
#include "rtc_base/win32.h"

// Use Multimedia Class Scheduler Service (MMCSS) to boost the thread priority
#pragma comment(lib, "avrt.lib")
// AVRT function pointers
typedef BOOL(WINAPI* PAvRevertMmThreadCharacteristics)(HANDLE);
typedef HANDLE(WINAPI* PAvSetMmThreadCharacteristicsA)(LPCSTR, LPDWORD);
typedef BOOL(WINAPI* PAvSetMmThreadPriority)(HANDLE, AVRT_PRIORITY);

namespace webrtc {

const float MAX_CORE_SPEAKER_VOLUME = 255.0f;
const float MIN_CORE_SPEAKER_VOLUME = 0.0f;
const float MAX_CORE_MICROPHONE_VOLUME = 255.0f;
const float MIN_CORE_MICROPHONE_VOLUME = 0.0f;
const uint16_t CORE_SPEAKER_VOLUME_STEP_SIZE = 1;
const uint16_t CORE_MICROPHONE_VOLUME_STEP_SIZE = 1;

class AudioDeviceWindowsCore : public AudioDeviceGeneric {
 public:
  AudioDeviceWindowsCore();
  ~AudioDeviceWindowsCore();

  static bool CoreAudioIsSupported();

  // Retrieve the currently utilized audio layer
  virtual int32_t ActiveAudioLayer(
      AudioDeviceModule::AudioLayer& audioLayer) const;

  // Main initializaton and termination
  virtual InitStatus Init() RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t Terminate() RTC_LOCKS_EXCLUDED(mutex_);
  virtual bool Initialized() const;

  // Device enumeration
  virtual int16_t PlayoutDevices() RTC_LOCKS_EXCLUDED(mutex_);
  virtual int16_t RecordingDevices() RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t PlayoutDeviceName(uint16_t index,
                                    char name[kAdmMaxDeviceNameSize],
                                    char guid[kAdmMaxGuidSize])
      RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t RecordingDeviceName(uint16_t index,
                                      char name[kAdmMaxDeviceNameSize],
                                      char guid[kAdmMaxGuidSize])
      RTC_LOCKS_EXCLUDED(mutex_);

  // Device selection
  virtual int32_t SetPlayoutDevice(uint16_t index) RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device);
  virtual int32_t SetRecordingDevice(uint16_t index) RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t SetRecordingDevice(
      AudioDeviceModule::WindowsDeviceType device) RTC_LOCKS_EXCLUDED(mutex_);

  // Audio transport initialization
  virtual int32_t PlayoutIsAvailable(bool& available);
  virtual int32_t InitPlayout() RTC_LOCKS_EXCLUDED(mutex_);
  virtual bool PlayoutIsInitialized() const;
  virtual int32_t RecordingIsAvailable(bool& available);
  virtual int32_t InitRecording() RTC_LOCKS_EXCLUDED(mutex_);
  virtual bool RecordingIsInitialized() const;

  // Audio transport control
  virtual int32_t StartPlayout() RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t StopPlayout() RTC_LOCKS_EXCLUDED(mutex_);
  virtual bool Playing() const;
  virtual int32_t StartRecording() RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t StopRecording();
  virtual bool Recording() const;

  // Audio mixer initialization
  virtual int32_t InitSpeaker() RTC_LOCKS_EXCLUDED(mutex_);
  virtual bool SpeakerIsInitialized() const;
  virtual int32_t InitMicrophone() RTC_LOCKS_EXCLUDED(mutex_);
  virtual bool MicrophoneIsInitialized() const;

  // Speaker volume controls
  virtual int32_t SpeakerVolumeIsAvailable(bool& available)
      RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t SetSpeakerVolume(uint32_t volume) RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t SpeakerVolume(uint32_t& volume) const
      RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const;
  virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const;

  // Microphone volume controls
  virtual int32_t MicrophoneVolumeIsAvailable(bool& available)
      RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t SetMicrophoneVolume(uint32_t volume)
      RTC_LOCKS_EXCLUDED(mutex_, volume_mutex_);
  virtual int32_t MicrophoneVolume(uint32_t& volume) const
      RTC_LOCKS_EXCLUDED(mutex_, volume_mutex_);
  virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const;
  virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const;

  // Speaker mute control
  virtual int32_t SpeakerMuteIsAvailable(bool& available)
      RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t SetSpeakerMute(bool enable) RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t SpeakerMute(bool& enabled) const;

  // Microphone mute control
  virtual int32_t MicrophoneMuteIsAvailable(bool& available)
      RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t SetMicrophoneMute(bool enable);
  virtual int32_t MicrophoneMute(bool& enabled) const;

  // Stereo support
  virtual int32_t StereoPlayoutIsAvailable(bool& available);
  virtual int32_t SetStereoPlayout(bool enable) RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t StereoPlayout(bool& enabled) const;
  virtual int32_t StereoRecordingIsAvailable(bool& available);
  virtual int32_t SetStereoRecording(bool enable) RTC_LOCKS_EXCLUDED(mutex_);
  virtual int32_t StereoRecording(bool& enabled) const
      RTC_LOCKS_EXCLUDED(mutex_);

  // Delay information and control
  virtual int32_t PlayoutDelay(uint16_t& delayMS) const
      RTC_LOCKS_EXCLUDED(mutex_);

  virtual bool BuiltInAECIsAvailable() const;

  virtual int32_t EnableBuiltInAEC(bool enable);

 public:
  virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);

 private:
  bool KeyPressed() const;

 private:  // avrt function pointers
  PAvRevertMmThreadCharacteristics _PAvRevertMmThreadCharacteristics;
  PAvSetMmThreadCharacteristicsA _PAvSetMmThreadCharacteristicsA;
  PAvSetMmThreadPriority _PAvSetMmThreadPriority;
  HMODULE _avrtLibrary;
  bool _winSupportAvrt;

 private:  // thread functions
  int32_t InitSpeakerLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
  int32_t InitMicrophoneLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
  int16_t PlayoutDevicesLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
  int16_t RecordingDevicesLocked() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
  DWORD InitCaptureThreadPriority();
  void RevertCaptureThreadPriority();
  static DWORD WINAPI WSAPICaptureThread(LPVOID context);
  DWORD DoCaptureThread();

  static DWORD WINAPI WSAPICaptureThreadPollDMO(LPVOID context);
  DWORD DoCaptureThreadPollDMO() RTC_LOCKS_EXCLUDED(mutex_);

  static DWORD WINAPI WSAPIRenderThread(LPVOID context);
  DWORD DoRenderThread();

  void _Lock();
  void _UnLock();

  int SetDMOProperties();

  int SetBoolProperty(IPropertyStore* ptrPS,
                      REFPROPERTYKEY key,
                      VARIANT_BOOL value);

  int SetVtI4Property(IPropertyStore* ptrPS, REFPROPERTYKEY key, LONG value);

  int32_t _EnumerateEndpointDevicesAll(EDataFlow dataFlow) const;
  void _TraceCOMError(HRESULT hr) const;

  int32_t _RefreshDeviceList(EDataFlow dir);
  int16_t _DeviceListCount(EDataFlow dir);
  int32_t _GetDefaultDeviceName(EDataFlow dir,
                                ERole role,
                                LPWSTR szBuffer,
                                int bufferLen);
  int32_t _GetListDeviceName(EDataFlow dir,
                             int index,
                             LPWSTR szBuffer,
                             int bufferLen);
  int32_t _GetDeviceName(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen);
  int32_t _GetListDeviceID(EDataFlow dir,
                           int index,
                           LPWSTR szBuffer,
                           int bufferLen);
  int32_t _GetDefaultDeviceID(EDataFlow dir,
                              ERole role,
                              LPWSTR szBuffer,
                              int bufferLen);
  int32_t _GetDefaultDeviceIndex(EDataFlow dir, ERole role, int* index);
  int32_t _GetDeviceID(IMMDevice* pDevice, LPWSTR pszBuffer, int bufferLen);
  int32_t _GetDefaultDevice(EDataFlow dir, ERole role, IMMDevice** ppDevice);
  int32_t _GetListDevice(EDataFlow dir, int index, IMMDevice** ppDevice);

  int32_t InitRecordingDMO();

  ScopedCOMInitializer _comInit;
  AudioDeviceBuffer* _ptrAudioBuffer;
  mutable Mutex mutex_;
  mutable Mutex volume_mutex_ RTC_ACQUIRED_AFTER(mutex_);

  IMMDeviceEnumerator* _ptrEnumerator;
  IMMDeviceCollection* _ptrRenderCollection;
  IMMDeviceCollection* _ptrCaptureCollection;
  IMMDevice* _ptrDeviceOut;
  IMMDevice* _ptrDeviceIn;

  IAudioClient* _ptrClientOut;
  IAudioClient* _ptrClientIn;
  IAudioRenderClient* _ptrRenderClient;
  IAudioCaptureClient* _ptrCaptureClient;
  IAudioEndpointVolume* _ptrCaptureVolume;
  ISimpleAudioVolume* _ptrRenderSimpleVolume;

  // DirectX Media Object (DMO) for the built-in AEC.
  rtc::scoped_refptr<IMediaObject> _dmo;
  rtc::scoped_refptr<IMediaBuffer> _mediaBuffer;
  bool _builtInAecEnabled;

  HANDLE _hRenderSamplesReadyEvent;
  HANDLE _hPlayThread;
  HANDLE _hRenderStartedEvent;
  HANDLE _hShutdownRenderEvent;

  HANDLE _hCaptureSamplesReadyEvent;
  HANDLE _hRecThread;
  HANDLE _hCaptureStartedEvent;
  HANDLE _hShutdownCaptureEvent;

  HANDLE _hMmTask;

  UINT _playAudioFrameSize;
  uint32_t _playSampleRate;
  uint32_t _devicePlaySampleRate;
  uint32_t _playBlockSize;
  uint32_t _devicePlayBlockSize;
  uint32_t _playChannels;
  uint32_t _sndCardPlayDelay;
  UINT64 _writtenSamples;
  UINT64 _readSamples;

  UINT _recAudioFrameSize;
  uint32_t _recSampleRate;
  uint32_t _recBlockSize;
  uint32_t _recChannels;

  uint16_t _recChannelsPrioList[3];
  uint16_t _playChannelsPrioList[2];

  LARGE_INTEGER _perfCounterFreq;
  double _perfCounterFactor;

 private:
  bool _initialized;
  bool _recording;
  bool _playing;
  bool _recIsInitialized;
  bool _playIsInitialized;
  bool _speakerIsInitialized;
  bool _microphoneIsInitialized;

  bool _usingInputDeviceIndex;
  bool _usingOutputDeviceIndex;
  AudioDeviceModule::WindowsDeviceType _inputDevice;
  AudioDeviceModule::WindowsDeviceType _outputDevice;
  uint16_t _inputDeviceIndex;
  uint16_t _outputDeviceIndex;
};

#endif  // #if (_MSC_VER >= 1400)

}  // namespace webrtc

#endif  // MODULES_AUDIO_DEVICE_WIN_AUDIO_DEVICE_CORE_WIN_H_