audio_device_module_win.cc (16915B)
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/audio/audio_device.h" 17 #include "api/environment/environment.h" 18 #include "api/make_ref_counted.h" 19 #include "api/sequence_checker.h" 20 #include "modules/audio_device/audio_device_buffer.h" 21 #include "rtc_base/checks.h" 22 #include "rtc_base/logging.h" 23 #include "rtc_base/string_utils.h" 24 25 namespace webrtc { 26 namespace webrtc_win { 27 namespace { 28 29 #define RETURN_IF_OUTPUT_RESTARTS(...) \ 30 do { \ 31 if (output_->Restarting()) { \ 32 return __VA_ARGS__; \ 33 } \ 34 } while (0) 35 36 #define RETURN_IF_INPUT_RESTARTS(...) \ 37 do { \ 38 if (input_->Restarting()) { \ 39 return __VA_ARGS__; \ 40 } \ 41 } while (0) 42 43 #define RETURN_IF_OUTPUT_IS_INITIALIZED(...) \ 44 do { \ 45 if (output_->PlayoutIsInitialized()) { \ 46 return __VA_ARGS__; \ 47 } \ 48 } while (0) 49 50 #define RETURN_IF_INPUT_IS_INITIALIZED(...) \ 51 do { \ 52 if (input_->RecordingIsInitialized()) { \ 53 return __VA_ARGS__; \ 54 } \ 55 } while (0) 56 57 #define RETURN_IF_OUTPUT_IS_ACTIVE(...) \ 58 do { \ 59 if (output_->Playing()) { \ 60 return __VA_ARGS__; \ 61 } \ 62 } while (0) 63 64 #define RETURN_IF_INPUT_IS_ACTIVE(...) \ 65 do { \ 66 if (input_->Recording()) { \ 67 return __VA_ARGS__; \ 68 } \ 69 } while (0) 70 71 // This class combines a generic instance of an AudioInput and a generic 72 // instance of an AudioOutput to create an AudioDeviceModule. This is mostly 73 // done by delegating to the audio input/output with some glue code. This class 74 // also directly implements some of the AudioDeviceModule methods with dummy 75 // implementations. 76 // 77 // An instance must be created, destroyed and used on one and the same thread, 78 // i.e., all public methods must also be called on the same thread. A thread 79 // checker will RTC_DCHECK if any method is called on an invalid thread. 80 // TODO(henrika): is thread checking needed in AudioInput and AudioOutput? 81 class WindowsAudioDeviceModule : public AudioDeviceModuleForTest { 82 public: 83 enum class InitStatus { 84 OK = 0, 85 PLAYOUT_ERROR = 1, 86 RECORDING_ERROR = 2, 87 OTHER_ERROR = 3, 88 NUM_STATUSES = 4 89 }; 90 91 WindowsAudioDeviceModule(const Environment& env, 92 std::unique_ptr<AudioInput> audio_input, 93 std::unique_ptr<AudioOutput> audio_output) 94 : env_(env), 95 input_(std::move(audio_input)), 96 output_(std::move(audio_output)) { 97 RTC_CHECK(input_); 98 RTC_CHECK(output_); 99 RTC_DLOG(LS_INFO) << __FUNCTION__; 100 RTC_DCHECK_RUN_ON(&thread_checker_); 101 } 102 103 ~WindowsAudioDeviceModule() override { 104 RTC_DLOG(LS_INFO) << __FUNCTION__; 105 RTC_DCHECK_RUN_ON(&thread_checker_); 106 Terminate(); 107 } 108 109 WindowsAudioDeviceModule(const WindowsAudioDeviceModule&) = delete; 110 WindowsAudioDeviceModule& operator=(const WindowsAudioDeviceModule&) = delete; 111 112 int32_t ActiveAudioLayer( 113 AudioDeviceModule::AudioLayer* audioLayer) const override { 114 RTC_DLOG(LS_INFO) << __FUNCTION__; 115 RTC_DCHECK_RUN_ON(&thread_checker_); 116 // TODO(henrika): it might be possible to remove this unique signature. 117 *audioLayer = AudioDeviceModule::kWindowsCoreAudio2; 118 return 0; 119 } 120 121 int32_t RegisterAudioCallback(AudioTransport* audioCallback) override { 122 RTC_DLOG(LS_INFO) << __FUNCTION__; 123 RTC_DCHECK(audio_device_buffer_); 124 RTC_DCHECK_RUN_ON(&thread_checker_); 125 return audio_device_buffer_->RegisterAudioCallback(audioCallback); 126 } 127 128 int32_t Init() override { 129 RTC_DLOG(LS_INFO) << __FUNCTION__; 130 RTC_DCHECK_RUN_ON(&thread_checker_); 131 RETURN_IF_OUTPUT_RESTARTS(0); 132 RETURN_IF_INPUT_RESTARTS(0); 133 if (initialized_) { 134 return 0; 135 } 136 audio_device_buffer_ = std::make_unique<AudioDeviceBuffer>(env_); 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 155 int32_t Terminate() override { 156 RTC_DLOG(LS_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 169 bool Initialized() const override { 170 RTC_DCHECK_RUN_ON(&thread_checker_); 171 return initialized_; 172 } 173 174 int16_t PlayoutDevices() override { 175 RTC_DLOG(LS_INFO) << __FUNCTION__; 176 RTC_DCHECK_RUN_ON(&thread_checker_); 177 RETURN_IF_OUTPUT_RESTARTS(0); 178 return output_->NumDevices(); 179 } 180 181 int16_t RecordingDevices() override { 182 RTC_DLOG(LS_INFO) << __FUNCTION__; 183 RTC_DCHECK_RUN_ON(&thread_checker_); 184 RETURN_IF_INPUT_RESTARTS(0); 185 return input_->NumDevices(); 186 } 187 188 int32_t PlayoutDeviceName(uint16_t index, 189 char name[kAdmMaxDeviceNameSize], 190 char guid[kAdmMaxGuidSize]) override { 191 RTC_DLOG(LS_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 webrtc::strcpyn(guid, kAdmMaxGuidSize, guid_str.c_str()); 199 } else { 200 ret = output_->DeviceName(index, &name_str, nullptr); 201 } 202 webrtc::strcpyn(name, kAdmMaxDeviceNameSize, name_str.c_str()); 203 return ret; 204 } 205 int32_t RecordingDeviceName(uint16_t index, 206 char name[kAdmMaxDeviceNameSize], 207 char guid[kAdmMaxGuidSize]) override { 208 RTC_DLOG(LS_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 webrtc::strcpyn(guid, kAdmMaxGuidSize, guid_str.c_str()); 216 } else { 217 ret = input_->DeviceName(index, &name_str, nullptr); 218 } 219 webrtc::strcpyn(name, kAdmMaxDeviceNameSize, name_str.c_str()); 220 return ret; 221 } 222 223 int32_t SetPlayoutDevice(uint16_t index) override { 224 RTC_DLOG(LS_INFO) << __FUNCTION__; 225 RTC_DCHECK_RUN_ON(&thread_checker_); 226 RETURN_IF_OUTPUT_RESTARTS(0); 227 return output_->SetDevice(index); 228 } 229 230 int32_t SetPlayoutDevice( 231 AudioDeviceModule::WindowsDeviceType device) override { 232 RTC_DLOG(LS_INFO) << __FUNCTION__; 233 RTC_DCHECK_RUN_ON(&thread_checker_); 234 RETURN_IF_OUTPUT_RESTARTS(0); 235 return output_->SetDevice(device); 236 } 237 int32_t SetRecordingDevice(uint16_t index) override { 238 RTC_DLOG(LS_INFO) << __FUNCTION__; 239 RTC_DCHECK_RUN_ON(&thread_checker_); 240 return input_->SetDevice(index); 241 } 242 243 int32_t SetRecordingDevice( 244 AudioDeviceModule::WindowsDeviceType device) override { 245 RTC_DLOG(LS_INFO) << __FUNCTION__; 246 RTC_DCHECK_RUN_ON(&thread_checker_); 247 return input_->SetDevice(device); 248 } 249 250 int32_t PlayoutIsAvailable(bool* available) override { 251 RTC_DLOG(LS_INFO) << __FUNCTION__; 252 RTC_DCHECK_RUN_ON(&thread_checker_); 253 *available = true; 254 return 0; 255 } 256 257 int32_t InitPlayout() override { 258 RTC_DLOG(LS_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 265 bool PlayoutIsInitialized() const override { 266 RTC_DLOG(LS_INFO) << __FUNCTION__; 267 RTC_DCHECK_RUN_ON(&thread_checker_); 268 RETURN_IF_OUTPUT_RESTARTS(true); 269 return output_->PlayoutIsInitialized(); 270 } 271 272 int32_t RecordingIsAvailable(bool* available) override { 273 RTC_DLOG(LS_INFO) << __FUNCTION__; 274 RTC_DCHECK_RUN_ON(&thread_checker_); 275 *available = true; 276 return 0; 277 } 278 279 int32_t InitRecording() override { 280 RTC_DLOG(LS_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 287 bool RecordingIsInitialized() const override { 288 RTC_DLOG(LS_INFO) << __FUNCTION__; 289 RTC_DCHECK_RUN_ON(&thread_checker_); 290 RETURN_IF_INPUT_RESTARTS(true); 291 return input_->RecordingIsInitialized(); 292 } 293 294 int32_t StartPlayout() override { 295 RTC_DLOG(LS_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 302 int32_t StopPlayout() override { 303 RTC_DLOG(LS_INFO) << __FUNCTION__; 304 RTC_DCHECK_RUN_ON(&thread_checker_); 305 RETURN_IF_OUTPUT_RESTARTS(-1); 306 return output_->StopPlayout(); 307 } 308 309 bool Playing() const override { 310 RTC_DLOG(LS_INFO) << __FUNCTION__; 311 RTC_DCHECK_RUN_ON(&thread_checker_); 312 RETURN_IF_OUTPUT_RESTARTS(true); 313 return output_->Playing(); 314 } 315 316 int32_t StartRecording() override { 317 RTC_DLOG(LS_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 324 int32_t StopRecording() override { 325 RTC_DLOG(LS_INFO) << __FUNCTION__; 326 RTC_DCHECK_RUN_ON(&thread_checker_); 327 RETURN_IF_INPUT_RESTARTS(-1); 328 return input_->StopRecording(); 329 } 330 331 bool Recording() const override { 332 RTC_DLOG(LS_INFO) << __FUNCTION__; 333 RETURN_IF_INPUT_RESTARTS(true); 334 return input_->Recording(); 335 } 336 337 int32_t InitSpeaker() override { 338 RTC_DLOG(LS_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 344 bool SpeakerIsInitialized() const override { 345 RTC_DLOG(LS_INFO) << __FUNCTION__; 346 RTC_DCHECK_RUN_ON(&thread_checker_); 347 RTC_DLOG(LS_WARNING) << "This method has no effect"; 348 return initialized_; 349 } 350 351 int32_t InitMicrophone() override { 352 RTC_DLOG(LS_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 358 bool MicrophoneIsInitialized() const override { 359 RTC_DLOG(LS_INFO) << __FUNCTION__; 360 RTC_DCHECK_RUN_ON(&thread_checker_); 361 RTC_DLOG(LS_WARNING) << "This method has no effect"; 362 return initialized_; 363 } 364 365 int32_t SpeakerVolumeIsAvailable(bool* available) override { 366 // TODO(henrika): improve support. 367 RTC_DLOG(LS_INFO) << __FUNCTION__; 368 RTC_DCHECK_RUN_ON(&thread_checker_); 369 *available = false; 370 return 0; 371 } 372 373 int32_t SetSpeakerVolume(uint32_t volume) override { return 0; } 374 int32_t SpeakerVolume(uint32_t* volume) const override { return 0; } 375 int32_t MaxSpeakerVolume(uint32_t* maxVolume) const override { return 0; } 376 int32_t MinSpeakerVolume(uint32_t* minVolume) const override { return 0; } 377 378 int32_t MicrophoneVolumeIsAvailable(bool* available) override { 379 // TODO(henrika): improve support. 380 RTC_DLOG(LS_INFO) << __FUNCTION__; 381 RTC_DCHECK_RUN_ON(&thread_checker_); 382 *available = false; 383 return 0; 384 } 385 386 int32_t SetMicrophoneVolume(uint32_t volume) override { return 0; } 387 int32_t MicrophoneVolume(uint32_t* volume) const override { return 0; } 388 int32_t MaxMicrophoneVolume(uint32_t* maxVolume) const override { return 0; } 389 int32_t MinMicrophoneVolume(uint32_t* minVolume) const override { return 0; } 390 391 int32_t SpeakerMuteIsAvailable(bool* available) override { return 0; } 392 int32_t SetSpeakerMute(bool enable) override { return 0; } 393 int32_t SpeakerMute(bool* enabled) const override { return 0; } 394 395 int32_t MicrophoneMuteIsAvailable(bool* available) override { return 0; } 396 int32_t SetMicrophoneMute(bool enable) override { return 0; } 397 int32_t MicrophoneMute(bool* enabled) const override { return 0; } 398 399 int32_t StereoPlayoutIsAvailable(bool* available) const override { 400 // TODO(henrika): improve support. 401 RTC_DLOG(LS_INFO) << __FUNCTION__; 402 RTC_DCHECK_RUN_ON(&thread_checker_); 403 *available = true; 404 return 0; 405 } 406 407 int32_t SetStereoPlayout(bool enable) override { 408 // TODO(henrika): improve support. 409 RTC_DLOG(LS_INFO) << __FUNCTION__; 410 RTC_DCHECK_RUN_ON(&thread_checker_); 411 return 0; 412 } 413 414 int32_t StereoPlayout(bool* enabled) const override { 415 // TODO(henrika): improve support. 416 RTC_DLOG(LS_INFO) << __FUNCTION__; 417 RTC_DCHECK_RUN_ON(&thread_checker_); 418 *enabled = true; 419 return 0; 420 } 421 422 int32_t StereoRecordingIsAvailable(bool* available) const override { 423 // TODO(henrika): improve support. 424 RTC_DLOG(LS_INFO) << __FUNCTION__; 425 RTC_DCHECK_RUN_ON(&thread_checker_); 426 *available = true; 427 return 0; 428 } 429 430 int32_t SetStereoRecording(bool enable) override { 431 // TODO(henrika): improve support. 432 RTC_DLOG(LS_INFO) << __FUNCTION__; 433 RTC_DCHECK_RUN_ON(&thread_checker_); 434 return 0; 435 } 436 437 int32_t StereoRecording(bool* enabled) const override { 438 // TODO(henrika): improve support. 439 RTC_DLOG(LS_INFO) << __FUNCTION__; 440 RTC_DCHECK_RUN_ON(&thread_checker_); 441 *enabled = true; 442 return 0; 443 } 444 445 int32_t PlayoutDelay(uint16_t* delayMS) const override { return 0; } 446 447 bool BuiltInAECIsAvailable() const override { return false; } 448 bool BuiltInAGCIsAvailable() const override { return false; } 449 bool BuiltInNSIsAvailable() const override { return false; } 450 451 int32_t EnableBuiltInAEC(bool enable) override { return 0; } 452 int32_t EnableBuiltInAGC(bool enable) override { return 0; } 453 int32_t EnableBuiltInNS(bool enable) override { return 0; } 454 455 int32_t AttachAudioBuffer() { 456 RTC_DLOG(LS_INFO) << __FUNCTION__; 457 output_->AttachAudioBuffer(audio_device_buffer_.get()); 458 input_->AttachAudioBuffer(audio_device_buffer_.get()); 459 return 0; 460 } 461 462 int RestartPlayoutInternally() override { 463 RTC_DLOG(LS_INFO) << __FUNCTION__; 464 RTC_DCHECK_RUN_ON(&thread_checker_); 465 RETURN_IF_OUTPUT_RESTARTS(0); 466 return output_->RestartPlayout(); 467 } 468 469 int RestartRecordingInternally() override { 470 RTC_DLOG(LS_INFO) << __FUNCTION__; 471 RTC_DCHECK_RUN_ON(&thread_checker_); 472 return input_->RestartRecording(); 473 } 474 475 int SetPlayoutSampleRate(uint32_t sample_rate) override { 476 RTC_DLOG(LS_INFO) << __FUNCTION__; 477 RTC_DCHECK_RUN_ON(&thread_checker_); 478 return output_->SetSampleRate(sample_rate); 479 } 480 481 int SetRecordingSampleRate(uint32_t sample_rate) override { 482 RTC_DLOG(LS_INFO) << __FUNCTION__; 483 RTC_DCHECK_RUN_ON(&thread_checker_); 484 return input_->SetSampleRate(sample_rate); 485 } 486 487 private: 488 const Environment env_; 489 490 // Ensures that the class is used on the same thread as it is constructed 491 // and destroyed on. 492 SequenceChecker thread_checker_; 493 494 // Implements the AudioInput interface and deals with audio capturing parts. 495 const std::unique_ptr<AudioInput> input_; 496 497 // Implements the AudioOutput interface and deals with audio rendering parts. 498 const std::unique_ptr<AudioOutput> output_; 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 webrtc::scoped_refptr<AudioDeviceModuleForTest> 512 CreateWindowsCoreAudioAudioDeviceModuleFromInputAndOutput( 513 const Environment& env, 514 std::unique_ptr<AudioInput> audio_input, 515 std::unique_ptr<AudioOutput> audio_output) { 516 RTC_DLOG(LS_INFO) << __FUNCTION__; 517 return make_ref_counted<WindowsAudioDeviceModule>(env, std::move(audio_input), 518 std::move(audio_output)); 519 } 520 521 } // namespace webrtc_win 522 } // namespace webrtc