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 "api/sequence_checker.h"
17 #include "modules/audio_device/audio_device_buffer.h"
18 #include "modules/audio_device/include/audio_device.h"
19 #include "rtc_base/checks.h"
20 #include "rtc_base/logging.h"
21 #include "rtc_base/ref_counted_object.h"
22 #include "rtc_base/string_utils.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_DLOG(INFO) << __FUNCTION__;
99     RTC_DCHECK_RUN_ON(&thread_checker_);
100   }
101 
~WindowsAudioDeviceModule()102   ~WindowsAudioDeviceModule() override {
103     RTC_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(INFO) << __FUNCTION__;
333     RETURN_IF_INPUT_RESTARTS(true);
334     return input_->Recording();
335   }
336 
InitSpeaker()337   int32_t InitSpeaker() override {
338     RTC_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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_DLOG(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   SequenceChecker 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_DLOG(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