1 /*
2 * Copyright (c) 2018 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 #include "modules/audio_device/win/audio_device_module_win.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "modules/audio_device/audio_device_buffer.h"
17 #include "modules/audio_device/include/audio_device.h"
18 #include "rtc_base/checks.h"
19 #include "rtc_base/logging.h"
20 #include "rtc_base/ref_counted_object.h"
21 #include "rtc_base/string_utils.h"
22 #include "rtc_base/thread_checker.h"
23
24 namespace webrtc {
25 namespace webrtc_win {
26 namespace {
27
28 #define RETURN_IF_OUTPUT_RESTARTS(...) \
29 do { \
30 if (output_->Restarting()) { \
31 return __VA_ARGS__; \
32 } \
33 } while (0)
34
35 #define RETURN_IF_INPUT_RESTARTS(...) \
36 do { \
37 if (input_->Restarting()) { \
38 return __VA_ARGS__; \
39 } \
40 } while (0)
41
42 #define RETURN_IF_OUTPUT_IS_INITIALIZED(...) \
43 do { \
44 if (output_->PlayoutIsInitialized()) { \
45 return __VA_ARGS__; \
46 } \
47 } while (0)
48
49 #define RETURN_IF_INPUT_IS_INITIALIZED(...) \
50 do { \
51 if (input_->RecordingIsInitialized()) { \
52 return __VA_ARGS__; \
53 } \
54 } while (0)
55
56 #define RETURN_IF_OUTPUT_IS_ACTIVE(...) \
57 do { \
58 if (output_->Playing()) { \
59 return __VA_ARGS__; \
60 } \
61 } while (0)
62
63 #define RETURN_IF_INPUT_IS_ACTIVE(...) \
64 do { \
65 if (input_->Recording()) { \
66 return __VA_ARGS__; \
67 } \
68 } while (0)
69
70 // This class combines a generic instance of an AudioInput and a generic
71 // instance of an AudioOutput to create an AudioDeviceModule. This is mostly
72 // done by delegating to the audio input/output with some glue code. This class
73 // also directly implements some of the AudioDeviceModule methods with dummy
74 // implementations.
75 //
76 // An instance must be created, destroyed and used on one and the same thread,
77 // i.e., all public methods must also be called on the same thread. A thread
78 // checker will RTC_DCHECK if any method is called on an invalid thread.
79 // TODO(henrika): is thread checking needed in AudioInput and AudioOutput?
80 class WindowsAudioDeviceModule : public AudioDeviceModuleForTest {
81 public:
82 enum class InitStatus {
83 OK = 0,
84 PLAYOUT_ERROR = 1,
85 RECORDING_ERROR = 2,
86 OTHER_ERROR = 3,
87 NUM_STATUSES = 4
88 };
89
WindowsAudioDeviceModule(std::unique_ptr<AudioInput> audio_input,std::unique_ptr<AudioOutput> audio_output,TaskQueueFactory * task_queue_factory)90 WindowsAudioDeviceModule(std::unique_ptr<AudioInput> audio_input,
91 std::unique_ptr<AudioOutput> audio_output,
92 TaskQueueFactory* task_queue_factory)
93 : input_(std::move(audio_input)),
94 output_(std::move(audio_output)),
95 task_queue_factory_(task_queue_factory) {
96 RTC_CHECK(input_);
97 RTC_CHECK(output_);
98 RTC_LOG(INFO) << __FUNCTION__;
99 RTC_DCHECK_RUN_ON(&thread_checker_);
100 }
101
~WindowsAudioDeviceModule()102 ~WindowsAudioDeviceModule() override {
103 RTC_LOG(INFO) << __FUNCTION__;
104 RTC_DCHECK_RUN_ON(&thread_checker_);
105 Terminate();
106 }
107
108 WindowsAudioDeviceModule(const WindowsAudioDeviceModule&) = delete;
109 WindowsAudioDeviceModule& operator=(const WindowsAudioDeviceModule&) = delete;
110
ActiveAudioLayer(AudioDeviceModule::AudioLayer * audioLayer) const111 int32_t ActiveAudioLayer(
112 AudioDeviceModule::AudioLayer* audioLayer) const override {
113 RTC_LOG(INFO) << __FUNCTION__;
114 RTC_DCHECK_RUN_ON(&thread_checker_);
115 // TODO(henrika): it might be possible to remove this unique signature.
116 *audioLayer = AudioDeviceModule::kWindowsCoreAudio2;
117 return 0;
118 }
119
RegisterAudioCallback(AudioTransport * audioCallback)120 int32_t RegisterAudioCallback(AudioTransport* audioCallback) override {
121 RTC_LOG(INFO) << __FUNCTION__;
122 RTC_DCHECK(audio_device_buffer_);
123 RTC_DCHECK_RUN_ON(&thread_checker_);
124 return audio_device_buffer_->RegisterAudioCallback(audioCallback);
125 }
126
Init()127 int32_t Init() override {
128 RTC_LOG(INFO) << __FUNCTION__;
129 RTC_DCHECK_RUN_ON(&thread_checker_);
130 RETURN_IF_OUTPUT_RESTARTS(0);
131 RETURN_IF_INPUT_RESTARTS(0);
132 if (initialized_) {
133 return 0;
134 }
135 audio_device_buffer_ =
136 std::make_unique<AudioDeviceBuffer>(task_queue_factory_);
137 AttachAudioBuffer();
138 InitStatus status;
139 if (output_->Init() != 0) {
140 status = InitStatus::PLAYOUT_ERROR;
141 } else if (input_->Init() != 0) {
142 output_->Terminate();
143 status = InitStatus::RECORDING_ERROR;
144 } else {
145 initialized_ = true;
146 status = InitStatus::OK;
147 }
148 if (status != InitStatus::OK) {
149 RTC_LOG(LS_ERROR) << "Audio device initialization failed";
150 return -1;
151 }
152 return 0;
153 }
154
Terminate()155 int32_t Terminate() override {
156 RTC_LOG(INFO) << __FUNCTION__;
157 RTC_DCHECK_RUN_ON(&thread_checker_);
158 RETURN_IF_OUTPUT_RESTARTS(0);
159 RETURN_IF_INPUT_RESTARTS(0);
160 if (!initialized_)
161 return 0;
162 int32_t err = input_->Terminate();
163 err |= output_->Terminate();
164 initialized_ = false;
165 RTC_DCHECK_EQ(err, 0);
166 return err;
167 }
168
Initialized() const169 bool Initialized() const override {
170 RTC_DCHECK_RUN_ON(&thread_checker_);
171 return initialized_;
172 }
173
PlayoutDevices()174 int16_t PlayoutDevices() override {
175 RTC_LOG(INFO) << __FUNCTION__;
176 RTC_DCHECK_RUN_ON(&thread_checker_);
177 RETURN_IF_OUTPUT_RESTARTS(0);
178 return output_->NumDevices();
179 }
180
RecordingDevices()181 int16_t RecordingDevices() override {
182 RTC_LOG(INFO) << __FUNCTION__;
183 RTC_DCHECK_RUN_ON(&thread_checker_);
184 RETURN_IF_INPUT_RESTARTS(0);
185 return input_->NumDevices();
186 }
187
PlayoutDeviceName(uint16_t index,char name[kAdmMaxDeviceNameSize],char guid[kAdmMaxGuidSize])188 int32_t PlayoutDeviceName(uint16_t index,
189 char name[kAdmMaxDeviceNameSize],
190 char guid[kAdmMaxGuidSize]) override {
191 RTC_LOG(INFO) << __FUNCTION__;
192 RTC_DCHECK_RUN_ON(&thread_checker_);
193 RETURN_IF_OUTPUT_RESTARTS(0);
194 std::string name_str, guid_str;
195 int ret = -1;
196 if (guid != nullptr) {
197 ret = output_->DeviceName(index, &name_str, &guid_str);
198 rtc::strcpyn(guid, kAdmMaxGuidSize, guid_str.c_str());
199 } else {
200 ret = output_->DeviceName(index, &name_str, nullptr);
201 }
202 rtc::strcpyn(name, kAdmMaxDeviceNameSize, name_str.c_str());
203 return ret;
204 }
RecordingDeviceName(uint16_t index,char name[kAdmMaxDeviceNameSize],char guid[kAdmMaxGuidSize])205 int32_t RecordingDeviceName(uint16_t index,
206 char name[kAdmMaxDeviceNameSize],
207 char guid[kAdmMaxGuidSize]) override {
208 RTC_LOG(INFO) << __FUNCTION__;
209 RTC_DCHECK_RUN_ON(&thread_checker_);
210 RETURN_IF_INPUT_RESTARTS(0);
211 std::string name_str, guid_str;
212 int ret = -1;
213 if (guid != nullptr) {
214 ret = input_->DeviceName(index, &name_str, &guid_str);
215 rtc::strcpyn(guid, kAdmMaxGuidSize, guid_str.c_str());
216 } else {
217 ret = input_->DeviceName(index, &name_str, nullptr);
218 }
219 rtc::strcpyn(name, kAdmMaxDeviceNameSize, name_str.c_str());
220 return ret;
221 }
222
SetPlayoutDevice(uint16_t index)223 int32_t SetPlayoutDevice(uint16_t index) override {
224 RTC_LOG(INFO) << __FUNCTION__;
225 RTC_DCHECK_RUN_ON(&thread_checker_);
226 RETURN_IF_OUTPUT_RESTARTS(0);
227 return output_->SetDevice(index);
228 }
229
SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device)230 int32_t SetPlayoutDevice(
231 AudioDeviceModule::WindowsDeviceType device) override {
232 RTC_LOG(INFO) << __FUNCTION__;
233 RTC_DCHECK_RUN_ON(&thread_checker_);
234 RETURN_IF_OUTPUT_RESTARTS(0);
235 return output_->SetDevice(device);
236 }
SetRecordingDevice(uint16_t index)237 int32_t SetRecordingDevice(uint16_t index) override {
238 RTC_LOG(INFO) << __FUNCTION__;
239 RTC_DCHECK_RUN_ON(&thread_checker_);
240 return input_->SetDevice(index);
241 }
242
SetRecordingDevice(AudioDeviceModule::WindowsDeviceType device)243 int32_t SetRecordingDevice(
244 AudioDeviceModule::WindowsDeviceType device) override {
245 RTC_LOG(INFO) << __FUNCTION__;
246 RTC_DCHECK_RUN_ON(&thread_checker_);
247 return input_->SetDevice(device);
248 }
249
PlayoutIsAvailable(bool * available)250 int32_t PlayoutIsAvailable(bool* available) override {
251 RTC_LOG(INFO) << __FUNCTION__;
252 RTC_DCHECK_RUN_ON(&thread_checker_);
253 *available = true;
254 return 0;
255 }
256
InitPlayout()257 int32_t InitPlayout() override {
258 RTC_LOG(INFO) << __FUNCTION__;
259 RTC_DCHECK_RUN_ON(&thread_checker_);
260 RETURN_IF_OUTPUT_RESTARTS(0);
261 RETURN_IF_OUTPUT_IS_INITIALIZED(0);
262 return output_->InitPlayout();
263 }
264
PlayoutIsInitialized() const265 bool PlayoutIsInitialized() const override {
266 RTC_LOG(INFO) << __FUNCTION__;
267 RTC_DCHECK_RUN_ON(&thread_checker_);
268 RETURN_IF_OUTPUT_RESTARTS(true);
269 return output_->PlayoutIsInitialized();
270 }
271
RecordingIsAvailable(bool * available)272 int32_t RecordingIsAvailable(bool* available) override {
273 RTC_LOG(INFO) << __FUNCTION__;
274 RTC_DCHECK_RUN_ON(&thread_checker_);
275 *available = true;
276 return 0;
277 }
278
InitRecording()279 int32_t InitRecording() override {
280 RTC_LOG(INFO) << __FUNCTION__;
281 RTC_DCHECK_RUN_ON(&thread_checker_);
282 RETURN_IF_INPUT_RESTARTS(0);
283 RETURN_IF_INPUT_IS_INITIALIZED(0);
284 return input_->InitRecording();
285 }
286
RecordingIsInitialized() const287 bool RecordingIsInitialized() const override {
288 RTC_LOG(INFO) << __FUNCTION__;
289 RTC_DCHECK_RUN_ON(&thread_checker_);
290 RETURN_IF_INPUT_RESTARTS(true);
291 return input_->RecordingIsInitialized();
292 }
293
StartPlayout()294 int32_t StartPlayout() override {
295 RTC_LOG(INFO) << __FUNCTION__;
296 RTC_DCHECK_RUN_ON(&thread_checker_);
297 RETURN_IF_OUTPUT_RESTARTS(0);
298 RETURN_IF_OUTPUT_IS_ACTIVE(0);
299 return output_->StartPlayout();
300 }
301
StopPlayout()302 int32_t StopPlayout() override {
303 RTC_LOG(INFO) << __FUNCTION__;
304 RTC_DCHECK_RUN_ON(&thread_checker_);
305 RETURN_IF_OUTPUT_RESTARTS(-1);
306 return output_->StopPlayout();
307 }
308
Playing() const309 bool Playing() const override {
310 RTC_LOG(INFO) << __FUNCTION__;
311 RTC_DCHECK_RUN_ON(&thread_checker_);
312 RETURN_IF_OUTPUT_RESTARTS(true);
313 return output_->Playing();
314 }
315
StartRecording()316 int32_t StartRecording() override {
317 RTC_LOG(INFO) << __FUNCTION__;
318 RTC_DCHECK_RUN_ON(&thread_checker_);
319 RETURN_IF_INPUT_RESTARTS(0);
320 RETURN_IF_INPUT_IS_ACTIVE(0);
321 return input_->StartRecording();
322 }
323
StopRecording()324 int32_t StopRecording() override {
325 RTC_LOG(INFO) << __FUNCTION__;
326 RTC_DCHECK_RUN_ON(&thread_checker_);
327 RETURN_IF_INPUT_RESTARTS(-1);
328 return input_->StopRecording();
329 }
330
Recording() const331 bool Recording() const override {
332 RTC_LOG(INFO) << __FUNCTION__;
333 RETURN_IF_INPUT_RESTARTS(true);
334 return input_->Recording();
335 }
336
InitSpeaker()337 int32_t InitSpeaker() override {
338 RTC_LOG(INFO) << __FUNCTION__;
339 RTC_DCHECK_RUN_ON(&thread_checker_);
340 RTC_DLOG(LS_WARNING) << "This method has no effect";
341 return initialized_ ? 0 : -1;
342 }
343
SpeakerIsInitialized() const344 bool SpeakerIsInitialized() const override {
345 RTC_LOG(INFO) << __FUNCTION__;
346 RTC_DCHECK_RUN_ON(&thread_checker_);
347 RTC_DLOG(LS_WARNING) << "This method has no effect";
348 return initialized_;
349 }
350
InitMicrophone()351 int32_t InitMicrophone() override {
352 RTC_LOG(INFO) << __FUNCTION__;
353 RTC_DCHECK_RUN_ON(&thread_checker_);
354 RTC_DLOG(LS_WARNING) << "This method has no effect";
355 return initialized_ ? 0 : -1;
356 }
357
MicrophoneIsInitialized() const358 bool MicrophoneIsInitialized() const override {
359 RTC_LOG(INFO) << __FUNCTION__;
360 RTC_DCHECK_RUN_ON(&thread_checker_);
361 RTC_DLOG(LS_WARNING) << "This method has no effect";
362 return initialized_;
363 }
364
SpeakerVolumeIsAvailable(bool * available)365 int32_t SpeakerVolumeIsAvailable(bool* available) override {
366 // TODO(henrika): improve support.
367 RTC_LOG(INFO) << __FUNCTION__;
368 RTC_DCHECK_RUN_ON(&thread_checker_);
369 *available = false;
370 return 0;
371 }
372
SetSpeakerVolume(uint32_t volume)373 int32_t SetSpeakerVolume(uint32_t volume) override { return 0; }
SpeakerVolume(uint32_t * volume) const374 int32_t SpeakerVolume(uint32_t* volume) const override { return 0; }
MaxSpeakerVolume(uint32_t * maxVolume) const375 int32_t MaxSpeakerVolume(uint32_t* maxVolume) const override { return 0; }
MinSpeakerVolume(uint32_t * minVolume) const376 int32_t MinSpeakerVolume(uint32_t* minVolume) const override { return 0; }
377
MicrophoneVolumeIsAvailable(bool * available)378 int32_t MicrophoneVolumeIsAvailable(bool* available) override {
379 // TODO(henrika): improve support.
380 RTC_LOG(INFO) << __FUNCTION__;
381 RTC_DCHECK_RUN_ON(&thread_checker_);
382 *available = false;
383 return 0;
384 }
385
SetMicrophoneVolume(uint32_t volume)386 int32_t SetMicrophoneVolume(uint32_t volume) override { return 0; }
MicrophoneVolume(uint32_t * volume) const387 int32_t MicrophoneVolume(uint32_t* volume) const override { return 0; }
MaxMicrophoneVolume(uint32_t * maxVolume) const388 int32_t MaxMicrophoneVolume(uint32_t* maxVolume) const override { return 0; }
MinMicrophoneVolume(uint32_t * minVolume) const389 int32_t MinMicrophoneVolume(uint32_t* minVolume) const override { return 0; }
390
SpeakerMuteIsAvailable(bool * available)391 int32_t SpeakerMuteIsAvailable(bool* available) override { return 0; }
SetSpeakerMute(bool enable)392 int32_t SetSpeakerMute(bool enable) override { return 0; }
SpeakerMute(bool * enabled) const393 int32_t SpeakerMute(bool* enabled) const override { return 0; }
394
MicrophoneMuteIsAvailable(bool * available)395 int32_t MicrophoneMuteIsAvailable(bool* available) override { return 0; }
SetMicrophoneMute(bool enable)396 int32_t SetMicrophoneMute(bool enable) override { return 0; }
MicrophoneMute(bool * enabled) const397 int32_t MicrophoneMute(bool* enabled) const override { return 0; }
398
StereoPlayoutIsAvailable(bool * available) const399 int32_t StereoPlayoutIsAvailable(bool* available) const override {
400 // TODO(henrika): improve support.
401 RTC_LOG(INFO) << __FUNCTION__;
402 RTC_DCHECK_RUN_ON(&thread_checker_);
403 *available = true;
404 return 0;
405 }
406
SetStereoPlayout(bool enable)407 int32_t SetStereoPlayout(bool enable) override {
408 // TODO(henrika): improve support.
409 RTC_LOG(INFO) << __FUNCTION__;
410 RTC_DCHECK_RUN_ON(&thread_checker_);
411 return 0;
412 }
413
StereoPlayout(bool * enabled) const414 int32_t StereoPlayout(bool* enabled) const override {
415 // TODO(henrika): improve support.
416 RTC_LOG(INFO) << __FUNCTION__;
417 RTC_DCHECK_RUN_ON(&thread_checker_);
418 *enabled = true;
419 return 0;
420 }
421
StereoRecordingIsAvailable(bool * available) const422 int32_t StereoRecordingIsAvailable(bool* available) const override {
423 // TODO(henrika): improve support.
424 RTC_LOG(INFO) << __FUNCTION__;
425 RTC_DCHECK_RUN_ON(&thread_checker_);
426 *available = true;
427 return 0;
428 }
429
SetStereoRecording(bool enable)430 int32_t SetStereoRecording(bool enable) override {
431 // TODO(henrika): improve support.
432 RTC_LOG(INFO) << __FUNCTION__;
433 RTC_DCHECK_RUN_ON(&thread_checker_);
434 return 0;
435 }
436
StereoRecording(bool * enabled) const437 int32_t StereoRecording(bool* enabled) const override {
438 // TODO(henrika): improve support.
439 RTC_LOG(INFO) << __FUNCTION__;
440 RTC_DCHECK_RUN_ON(&thread_checker_);
441 *enabled = true;
442 return 0;
443 }
444
PlayoutDelay(uint16_t * delayMS) const445 int32_t PlayoutDelay(uint16_t* delayMS) const override { return 0; }
446
BuiltInAECIsAvailable() const447 bool BuiltInAECIsAvailable() const override { return false; }
BuiltInAGCIsAvailable() const448 bool BuiltInAGCIsAvailable() const override { return false; }
BuiltInNSIsAvailable() const449 bool BuiltInNSIsAvailable() const override { return false; }
450
EnableBuiltInAEC(bool enable)451 int32_t EnableBuiltInAEC(bool enable) override { return 0; }
EnableBuiltInAGC(bool enable)452 int32_t EnableBuiltInAGC(bool enable) override { return 0; }
EnableBuiltInNS(bool enable)453 int32_t EnableBuiltInNS(bool enable) override { return 0; }
454
AttachAudioBuffer()455 int32_t AttachAudioBuffer() {
456 RTC_DLOG(INFO) << __FUNCTION__;
457 output_->AttachAudioBuffer(audio_device_buffer_.get());
458 input_->AttachAudioBuffer(audio_device_buffer_.get());
459 return 0;
460 }
461
RestartPlayoutInternally()462 int RestartPlayoutInternally() override {
463 RTC_DLOG(INFO) << __FUNCTION__;
464 RTC_DCHECK_RUN_ON(&thread_checker_);
465 RETURN_IF_OUTPUT_RESTARTS(0);
466 return output_->RestartPlayout();
467 }
468
RestartRecordingInternally()469 int RestartRecordingInternally() override {
470 RTC_DLOG(INFO) << __FUNCTION__;
471 RTC_DCHECK_RUN_ON(&thread_checker_);
472 return input_->RestartRecording();
473 }
474
SetPlayoutSampleRate(uint32_t sample_rate)475 int SetPlayoutSampleRate(uint32_t sample_rate) override {
476 RTC_DLOG(INFO) << __FUNCTION__;
477 RTC_DCHECK_RUN_ON(&thread_checker_);
478 return output_->SetSampleRate(sample_rate);
479 }
480
SetRecordingSampleRate(uint32_t sample_rate)481 int SetRecordingSampleRate(uint32_t sample_rate) override {
482 RTC_DLOG(INFO) << __FUNCTION__;
483 RTC_DCHECK_RUN_ON(&thread_checker_);
484 return input_->SetSampleRate(sample_rate);
485 }
486
487 private:
488 // Ensures that the class is used on the same thread as it is constructed
489 // and destroyed on.
490 rtc::ThreadChecker thread_checker_;
491
492 // Implements the AudioInput interface and deals with audio capturing parts.
493 const std::unique_ptr<AudioInput> input_;
494
495 // Implements the AudioOutput interface and deals with audio rendering parts.
496 const std::unique_ptr<AudioOutput> output_;
497
498 TaskQueueFactory* const task_queue_factory_;
499
500 // The AudioDeviceBuffer (ADB) instance is needed for sending/receiving audio
501 // to/from the WebRTC layer. Created and owned by this object. Used by
502 // both |input_| and |output_| but they use orthogonal parts of the ADB.
503 std::unique_ptr<AudioDeviceBuffer> audio_device_buffer_;
504
505 // Set to true after a successful call to Init(). Cleared by Terminate().
506 bool initialized_ = false;
507 };
508
509 } // namespace
510
511 rtc::scoped_refptr<AudioDeviceModuleForTest>
CreateWindowsCoreAudioAudioDeviceModuleFromInputAndOutput(std::unique_ptr<AudioInput> audio_input,std::unique_ptr<AudioOutput> audio_output,TaskQueueFactory * task_queue_factory)512 CreateWindowsCoreAudioAudioDeviceModuleFromInputAndOutput(
513 std::unique_ptr<AudioInput> audio_input,
514 std::unique_ptr<AudioOutput> audio_output,
515 TaskQueueFactory* task_queue_factory) {
516 RTC_LOG(INFO) << __FUNCTION__;
517 return new rtc::RefCountedObject<WindowsAudioDeviceModule>(
518 std::move(audio_input), std::move(audio_output), task_queue_factory);
519 }
520
521 } // namespace webrtc_win
522 } // namespace webrtc
523