OLD | NEW |
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2004 Google Inc. | 3 * Copyright 2004 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 61 |
62 namespace cricket { | 62 namespace cricket { |
63 namespace { | 63 namespace { |
64 | 64 |
65 const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo | | 65 const int kDefaultTraceFilter = webrtc::kTraceNone | webrtc::kTraceTerseInfo | |
66 webrtc::kTraceWarning | webrtc::kTraceError | | 66 webrtc::kTraceWarning | webrtc::kTraceError | |
67 webrtc::kTraceCritical; | 67 webrtc::kTraceCritical; |
68 const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo | | 68 const int kElevatedTraceFilter = kDefaultTraceFilter | webrtc::kTraceStateInfo | |
69 webrtc::kTraceInfo; | 69 webrtc::kTraceInfo; |
70 | 70 |
71 // For Linux/Mac, using the default device is done by specifying index 0 for | |
72 // VoE 4.0 and not -1 (which was the case for VoE 3.5). | |
73 // | |
74 // On Windows Vista and newer, Microsoft introduced the concept of "Default | 71 // On Windows Vista and newer, Microsoft introduced the concept of "Default |
75 // Communications Device". This means that there are two types of default | 72 // Communications Device". This means that there are two types of default |
76 // devices (old Wave Audio style default and Default Communications Device). | 73 // devices (old Wave Audio style default and Default Communications Device). |
77 // | 74 // |
78 // On Windows systems which only support Wave Audio style default, uses either | 75 // On Windows systems which only support Wave Audio style default, uses either |
79 // -1 or 0 to select the default device. | 76 // -1 or 0 to select the default device. |
80 // | |
81 // On Windows systems which support both "Default Communication Device" and | |
82 // old Wave Audio style default, use -1 for Default Communications Device and | |
83 // -2 for Wave Audio style default, which is what we want to use for clips. | |
84 // It's not clear yet whether the -2 index is handled properly on other OSes. | |
85 | |
86 #ifdef WIN32 | 77 #ifdef WIN32 |
87 const int kDefaultAudioDeviceId = -1; | 78 const int kDefaultAudioDeviceId = -1; |
88 #else | 79 #else |
89 const int kDefaultAudioDeviceId = 0; | 80 const int kDefaultAudioDeviceId = 0; |
90 #endif | 81 #endif |
91 | 82 |
92 // Parameter used for NACK. | 83 // Parameter used for NACK. |
93 // This value is equivalent to 5 seconds of audio data at 20 ms per packet. | 84 // This value is equivalent to 5 seconds of audio data at 20 ms per packet. |
94 const int kNackMaxPackets = 250; | 85 const int kNackMaxPackets = 250; |
95 | 86 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 // If OPUS, change what we send according to the "stereo" codec | 259 // If OPUS, change what we send according to the "stereo" codec |
269 // parameter, and not the "channels" parameter. We set | 260 // parameter, and not the "channels" parameter. We set |
270 // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If | 261 // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If |
271 // the bitrate is not specified, i.e. is <= zero, we set it to the | 262 // the bitrate is not specified, i.e. is <= zero, we set it to the |
272 // appropriate default value for mono or stereo Opus. | 263 // appropriate default value for mono or stereo Opus. |
273 | 264 |
274 voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1; | 265 voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1; |
275 voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate); | 266 voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate); |
276 } | 267 } |
277 | 268 |
278 // Gets the default set of options applied to the engine. Historically, these | |
279 // were supplied as a combination of flags from the channel manager (ec, agc, | |
280 // ns, and highpass) and the rest hardcoded in InitInternal. | |
281 AudioOptions GetDefaultEngineOptions() { | |
282 AudioOptions options; | |
283 options.echo_cancellation = rtc::Optional<bool>(true); | |
284 options.auto_gain_control = rtc::Optional<bool>(true); | |
285 options.noise_suppression = rtc::Optional<bool>(true); | |
286 options.highpass_filter = rtc::Optional<bool>(true); | |
287 options.stereo_swapping = rtc::Optional<bool>(false); | |
288 options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50); | |
289 options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false); | |
290 options.typing_detection = rtc::Optional<bool>(true); | |
291 options.adjust_agc_delta = rtc::Optional<int>(0); | |
292 options.experimental_agc = rtc::Optional<bool>(false); | |
293 options.extended_filter_aec = rtc::Optional<bool>(false); | |
294 options.delay_agnostic_aec = rtc::Optional<bool>(false); | |
295 options.experimental_ns = rtc::Optional<bool>(false); | |
296 options.aec_dump = rtc::Optional<bool>(false); | |
297 return options; | |
298 } | |
299 | |
300 webrtc::AudioState::Config MakeAudioStateConfig(VoEWrapper* voe_wrapper) { | 269 webrtc::AudioState::Config MakeAudioStateConfig(VoEWrapper* voe_wrapper) { |
301 webrtc::AudioState::Config config; | 270 webrtc::AudioState::Config config; |
302 config.voice_engine = voe_wrapper->engine(); | 271 config.voice_engine = voe_wrapper->engine(); |
303 return config; | 272 return config; |
304 } | 273 } |
305 | 274 |
306 class WebRtcVoiceCodecs final { | 275 class WebRtcVoiceCodecs final { |
307 public: | 276 public: |
308 // TODO(solenberg): Do this filtering once off-line, add a simple AudioCodec | 277 // TODO(solenberg): Do this filtering once off-line, add a simple AudioCodec |
309 // list and add a test which verifies VoE supports the listed codecs. | 278 // list and add a test which verifies VoE supports the listed codecs. |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 : voe_wrapper_(voe_wrapper) { | 472 : voe_wrapper_(voe_wrapper) { |
504 Construct(); | 473 Construct(); |
505 } | 474 } |
506 | 475 |
507 void WebRtcVoiceEngine::Construct() { | 476 void WebRtcVoiceEngine::Construct() { |
508 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 477 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
509 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; | 478 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::WebRtcVoiceEngine"; |
510 | 479 |
511 signal_thread_checker_.DetachFromThread(); | 480 signal_thread_checker_.DetachFromThread(); |
512 std::memset(&default_agc_config_, 0, sizeof(default_agc_config_)); | 481 std::memset(&default_agc_config_, 0, sizeof(default_agc_config_)); |
| 482 voe_config_.Set<webrtc::VoicePacing>(new webrtc::VoicePacing(true)); |
513 | 483 |
514 webrtc::Trace::set_level_filter(kDefaultTraceFilter); | 484 webrtc::Trace::set_level_filter(kDefaultTraceFilter); |
515 webrtc::Trace::SetTraceCallback(this); | 485 webrtc::Trace::SetTraceCallback(this); |
516 | 486 |
517 // Load our audio codec list. | 487 // Load our audio codec list. |
518 codecs_ = WebRtcVoiceCodecs::SupportedCodecs(); | 488 codecs_ = WebRtcVoiceCodecs::SupportedCodecs(); |
519 | |
520 options_ = GetDefaultEngineOptions(); | |
521 voe_config_.Set<webrtc::VoicePacing>(new webrtc::VoicePacing(true)); | |
522 } | 489 } |
523 | 490 |
524 WebRtcVoiceEngine::~WebRtcVoiceEngine() { | 491 WebRtcVoiceEngine::~WebRtcVoiceEngine() { |
525 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 492 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
526 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine"; | 493 LOG(LS_VERBOSE) << "WebRtcVoiceEngine::~WebRtcVoiceEngine"; |
527 if (adm_) { | 494 if (adm_) { |
528 voe_wrapper_.reset(); | 495 voe_wrapper_.reset(); |
529 adm_->Release(); | 496 adm_->Release(); |
530 adm_ = NULL; | 497 adm_ = NULL; |
531 } | 498 } |
(...skipping 19 matching lines...) Expand all Loading... |
551 // Temporarily turn logging level up for the Init call | 518 // Temporarily turn logging level up for the Init call |
552 webrtc::Trace::set_level_filter(kElevatedTraceFilter); | 519 webrtc::Trace::set_level_filter(kElevatedTraceFilter); |
553 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString(); | 520 LOG(LS_INFO) << webrtc::VoiceEngine::GetVersionString(); |
554 if (voe_wrapper_->base()->Init(adm_) == -1) { | 521 if (voe_wrapper_->base()->Init(adm_) == -1) { |
555 LOG_RTCERR0_EX(Init, voe_wrapper_->error()); | 522 LOG_RTCERR0_EX(Init, voe_wrapper_->error()); |
556 return false; | 523 return false; |
557 } | 524 } |
558 webrtc::Trace::set_level_filter(kDefaultTraceFilter); | 525 webrtc::Trace::set_level_filter(kDefaultTraceFilter); |
559 | 526 |
560 // Save the default AGC configuration settings. This must happen before | 527 // Save the default AGC configuration settings. This must happen before |
561 // calling SetOptions or the default will be overwritten. | 528 // calling ApplyOptions or the default will be overwritten. |
562 if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) { | 529 if (voe_wrapper_->processing()->GetAgcConfig(default_agc_config_) == -1) { |
563 LOG_RTCERR0(GetAgcConfig); | 530 LOG_RTCERR0(GetAgcConfig); |
564 return false; | 531 return false; |
565 } | 532 } |
566 | 533 |
567 // Set defaults for options, so that ApplyOptions applies them explicitly | |
568 // when we clear option (channel) overrides. External clients can still | |
569 // modify the defaults via SetOptions (on the media engine). | |
570 if (!SetOptions(GetDefaultEngineOptions())) { | |
571 return false; | |
572 } | |
573 | |
574 // Print our codec list again for the call diagnostic log | 534 // Print our codec list again for the call diagnostic log |
575 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; | 535 LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; |
576 for (const AudioCodec& codec : codecs_) { | 536 for (const AudioCodec& codec : codecs_) { |
577 LOG(LS_INFO) << ToString(codec); | 537 LOG(LS_INFO) << ToString(codec); |
578 } | 538 } |
579 | 539 |
| 540 SetDefaultDevices(); |
| 541 |
580 initialized_ = true; | 542 initialized_ = true; |
581 return true; | 543 return true; |
582 } | 544 } |
583 | 545 |
584 void WebRtcVoiceEngine::Terminate() { | 546 void WebRtcVoiceEngine::Terminate() { |
585 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 547 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
586 LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate"; | 548 LOG(LS_INFO) << "WebRtcVoiceEngine::Terminate"; |
587 initialized_ = false; | 549 initialized_ = false; |
588 | 550 |
589 StopAecDump(); | 551 StopAecDump(); |
590 | 552 |
591 voe_wrapper_->base()->Terminate(); | 553 voe_wrapper_->base()->Terminate(); |
592 } | 554 } |
593 | 555 |
594 rtc::scoped_refptr<webrtc::AudioState> | 556 rtc::scoped_refptr<webrtc::AudioState> |
595 WebRtcVoiceEngine::GetAudioState() const { | 557 WebRtcVoiceEngine::GetAudioState() const { |
596 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 558 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
597 return audio_state_; | 559 return audio_state_; |
598 } | 560 } |
599 | 561 |
600 VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(webrtc::Call* call, | 562 VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(webrtc::Call* call, |
601 const AudioOptions& options) { | 563 const AudioOptions& options) { |
602 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 564 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
603 return new WebRtcVoiceMediaChannel(this, options, call); | 565 return new WebRtcVoiceMediaChannel(this, options, call); |
604 } | 566 } |
605 | 567 |
606 bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) { | |
607 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
608 if (!ApplyOptions(options)) { | |
609 return false; | |
610 } | |
611 options_ = options; | |
612 return true; | |
613 } | |
614 | |
615 // AudioOptions defaults are set in InitInternal (for options with corresponding | |
616 // MediaEngineInterface flags) and in SetOptions(int) for flagless options. | |
617 bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { | 568 bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { |
618 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 569 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
619 LOG(LS_INFO) << "ApplyOptions: " << options_in.ToString(); | 570 LOG(LS_INFO) << "ApplyOptions: " << options_in.ToString(); |
620 AudioOptions options = options_in; // The options are modified below. | 571 |
| 572 // Default engine options. |
| 573 AudioOptions options; |
| 574 options.echo_cancellation = rtc::Optional<bool>(true); |
| 575 options.auto_gain_control = rtc::Optional<bool>(true); |
| 576 options.noise_suppression = rtc::Optional<bool>(true); |
| 577 options.highpass_filter = rtc::Optional<bool>(true); |
| 578 options.stereo_swapping = rtc::Optional<bool>(false); |
| 579 options.audio_jitter_buffer_max_packets = rtc::Optional<int>(50); |
| 580 options.audio_jitter_buffer_fast_accelerate = rtc::Optional<bool>(false); |
| 581 options.typing_detection = rtc::Optional<bool>(true); |
| 582 options.adjust_agc_delta = rtc::Optional<int>(0); |
| 583 options.experimental_agc = rtc::Optional<bool>(false); |
| 584 options.extended_filter_aec = rtc::Optional<bool>(false); |
| 585 options.delay_agnostic_aec = rtc::Optional<bool>(false); |
| 586 options.experimental_ns = rtc::Optional<bool>(false); |
| 587 options.aec_dump = rtc::Optional<bool>(false); |
| 588 |
| 589 // Apply any given options on top. |
| 590 options.SetAll(options_in); |
| 591 |
621 // kEcConference is AEC with high suppression. | 592 // kEcConference is AEC with high suppression. |
622 webrtc::EcModes ec_mode = webrtc::kEcConference; | 593 webrtc::EcModes ec_mode = webrtc::kEcConference; |
623 webrtc::AecmModes aecm_mode = webrtc::kAecmSpeakerphone; | 594 webrtc::AecmModes aecm_mode = webrtc::kAecmSpeakerphone; |
624 webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog; | 595 webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog; |
625 webrtc::NsModes ns_mode = webrtc::kNsHighSuppression; | 596 webrtc::NsModes ns_mode = webrtc::kNsHighSuppression; |
626 if (options.aecm_generate_comfort_noise) { | 597 if (options.aecm_generate_comfort_noise) { |
627 LOG(LS_VERBOSE) << "Comfort noise explicitly set to " | 598 LOG(LS_VERBOSE) << "Comfort noise explicitly set to " |
628 << *options.aecm_generate_comfort_noise | 599 << *options.aecm_generate_comfort_noise |
629 << " (default is false)."; | 600 << " (default is false)."; |
630 } | 601 } |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
880 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate; | 851 LOG(LS_INFO) << "Playout sample rate is " << *options.playout_sample_rate; |
881 if (voe_wrapper_->hw()->SetPlayoutSampleRate( | 852 if (voe_wrapper_->hw()->SetPlayoutSampleRate( |
882 *options.playout_sample_rate)) { | 853 *options.playout_sample_rate)) { |
883 LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate); | 854 LOG_RTCERR1(SetPlayoutSampleRate, *options.playout_sample_rate); |
884 } | 855 } |
885 } | 856 } |
886 | 857 |
887 return true; | 858 return true; |
888 } | 859 } |
889 | 860 |
890 // TODO(juberti): Refactor this so that the core logic can be used to set the | 861 void WebRtcVoiceEngine::SetDefaultDevices() { |
891 // soundclip device. At that time, reinstate the soundclip pause/resume code. | |
892 bool WebRtcVoiceEngine::SetDevices(const Device* in_device, | |
893 const Device* out_device) { | |
894 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 862 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
895 #if !defined(IOS) | 863 #if !defined(IOS) |
896 int in_id = in_device ? rtc::FromString<int>(in_device->id) : | 864 int in_id = kDefaultAudioDeviceId; |
897 kDefaultAudioDeviceId; | 865 int out_id = kDefaultAudioDeviceId; |
898 int out_id = out_device ? rtc::FromString<int>(out_device->id) : | 866 LOG(LS_INFO) << "Setting microphone to (id=" << in_id |
899 kDefaultAudioDeviceId; | 867 << ") and speaker to (id=" << out_id << ")"; |
900 // The device manager uses -1 as the default device, which was the case for | 868 |
901 // VoE 3.5. VoE 4.0, however, uses 0 as the default in Linux and Mac. | 869 bool ret = true; |
902 #ifndef WIN32 | 870 if (voe_wrapper_->hw()->SetRecordingDevice(in_id) == -1) { |
903 if (-1 == in_id) { | 871 LOG_RTCERR1(SetRecordingDevice, in_id); |
904 in_id = kDefaultAudioDeviceId; | 872 ret = false; |
905 } | 873 } |
906 if (-1 == out_id) { | 874 webrtc::AudioProcessing* ap = voe()->base()->audio_processing(); |
907 out_id = kDefaultAudioDeviceId; | 875 if (ap) { |
908 } | 876 ap->Initialize(); |
909 #endif | |
910 | |
911 std::string in_name = (in_id != kDefaultAudioDeviceId) ? | |
912 in_device->name : "Default device"; | |
913 std::string out_name = (out_id != kDefaultAudioDeviceId) ? | |
914 out_device->name : "Default device"; | |
915 LOG(LS_INFO) << "Setting microphone to (id=" << in_id << ", name=" << in_name | |
916 << ") and speaker to (id=" << out_id << ", name=" << out_name | |
917 << ")"; | |
918 | |
919 // Must also pause all audio playback and capture. | |
920 bool ret = true; | |
921 for (WebRtcVoiceMediaChannel* channel : channels_) { | |
922 if (!channel->PausePlayout()) { | |
923 LOG(LS_WARNING) << "Failed to pause playout"; | |
924 ret = false; | |
925 } | |
926 if (!channel->PauseSend()) { | |
927 LOG(LS_WARNING) << "Failed to pause send"; | |
928 ret = false; | |
929 } | |
930 } | 877 } |
931 | 878 |
932 // Find the recording device id in VoiceEngine and set recording device. | 879 if (voe_wrapper_->hw()->SetPlayoutDevice(out_id) == -1) { |
933 if (!FindWebRtcAudioDeviceId(true, in_name, in_id, &in_id)) { | 880 LOG_RTCERR1(SetPlayoutDevice, out_id); |
934 ret = false; | 881 ret = false; |
935 } | 882 } |
936 if (ret) { | |
937 if (voe_wrapper_->hw()->SetRecordingDevice(in_id) == -1) { | |
938 LOG_RTCERR2(SetRecordingDevice, in_name, in_id); | |
939 ret = false; | |
940 } | |
941 webrtc::AudioProcessing* ap = voe()->base()->audio_processing(); | |
942 if (ap) | |
943 ap->Initialize(); | |
944 } | |
945 | |
946 // Find the playout device id in VoiceEngine and set playout device. | |
947 if (!FindWebRtcAudioDeviceId(false, out_name, out_id, &out_id)) { | |
948 LOG(LS_WARNING) << "Failed to find VoiceEngine device id for " << out_name; | |
949 ret = false; | |
950 } | |
951 if (ret) { | |
952 if (voe_wrapper_->hw()->SetPlayoutDevice(out_id) == -1) { | |
953 LOG_RTCERR2(SetPlayoutDevice, out_name, out_id); | |
954 ret = false; | |
955 } | |
956 } | |
957 | |
958 // Resume all audio playback and capture. | |
959 for (WebRtcVoiceMediaChannel* channel : channels_) { | |
960 if (!channel->ResumePlayout()) { | |
961 LOG(LS_WARNING) << "Failed to resume playout"; | |
962 ret = false; | |
963 } | |
964 if (!channel->ResumeSend()) { | |
965 LOG(LS_WARNING) << "Failed to resume send"; | |
966 ret = false; | |
967 } | |
968 } | |
969 | 883 |
970 if (ret) { | 884 if (ret) { |
971 LOG(LS_INFO) << "Set microphone to (id=" << in_id <<" name=" << in_name | 885 LOG(LS_INFO) << "Set microphone to (id=" << in_id |
972 << ") and speaker to (id="<< out_id << " name=" << out_name | 886 << ") and speaker to (id=" << out_id << ")"; |
973 << ")"; | |
974 } | 887 } |
975 | |
976 return ret; | |
977 #else | |
978 return true; | |
979 #endif // !IOS | 888 #endif // !IOS |
980 } | 889 } |
981 | 890 |
982 bool WebRtcVoiceEngine::FindWebRtcAudioDeviceId( | |
983 bool is_input, const std::string& dev_name, int dev_id, int* rtc_id) { | |
984 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | |
985 // In Linux, VoiceEngine uses the same device dev_id as the device manager. | |
986 #if defined(LINUX) || defined(ANDROID) | |
987 *rtc_id = dev_id; | |
988 return true; | |
989 #else | |
990 // In Windows and Mac, we need to find the VoiceEngine device id by name | |
991 // unless the input dev_id is the default device id. | |
992 if (kDefaultAudioDeviceId == dev_id) { | |
993 *rtc_id = dev_id; | |
994 return true; | |
995 } | |
996 | |
997 // Get the number of VoiceEngine audio devices. | |
998 int count = 0; | |
999 if (is_input) { | |
1000 if (-1 == voe_wrapper_->hw()->GetNumOfRecordingDevices(count)) { | |
1001 LOG_RTCERR0(GetNumOfRecordingDevices); | |
1002 return false; | |
1003 } | |
1004 } else { | |
1005 if (-1 == voe_wrapper_->hw()->GetNumOfPlayoutDevices(count)) { | |
1006 LOG_RTCERR0(GetNumOfPlayoutDevices); | |
1007 return false; | |
1008 } | |
1009 } | |
1010 | |
1011 for (int i = 0; i < count; ++i) { | |
1012 char name[128]; | |
1013 char guid[128]; | |
1014 if (is_input) { | |
1015 voe_wrapper_->hw()->GetRecordingDeviceName(i, name, guid); | |
1016 LOG(LS_VERBOSE) << "VoiceEngine microphone " << i << ": " << name; | |
1017 } else { | |
1018 voe_wrapper_->hw()->GetPlayoutDeviceName(i, name, guid); | |
1019 LOG(LS_VERBOSE) << "VoiceEngine speaker " << i << ": " << name; | |
1020 } | |
1021 | |
1022 std::string webrtc_name(name); | |
1023 if (dev_name.compare(0, webrtc_name.size(), webrtc_name) == 0) { | |
1024 *rtc_id = i; | |
1025 return true; | |
1026 } | |
1027 } | |
1028 LOG(LS_WARNING) << "VoiceEngine cannot find device: " << dev_name; | |
1029 return false; | |
1030 #endif | |
1031 } | |
1032 | |
1033 bool WebRtcVoiceEngine::GetOutputVolume(int* level) { | 891 bool WebRtcVoiceEngine::GetOutputVolume(int* level) { |
1034 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); | 892 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); |
1035 unsigned int ulevel; | 893 unsigned int ulevel; |
1036 if (voe_wrapper_->volume()->GetSpeakerVolume(ulevel) == -1) { | 894 if (voe_wrapper_->volume()->GetSpeakerVolume(ulevel) == -1) { |
1037 LOG_RTCERR1(GetSpeakerVolume, level); | 895 LOG_RTCERR1(GetSpeakerVolume, level); |
1038 return false; | 896 return false; |
1039 } | 897 } |
1040 *level = ulevel; | 898 *level = ulevel; |
1041 return true; | 899 return true; |
1042 } | 900 } |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 LOG(LS_INFO) << "Setting voice channel options: " | 1362 LOG(LS_INFO) << "Setting voice channel options: " |
1505 << options.ToString(); | 1363 << options.ToString(); |
1506 | 1364 |
1507 // Check if DSCP value is changed from previous. | 1365 // Check if DSCP value is changed from previous. |
1508 bool dscp_option_changed = (options_.dscp != options.dscp); | 1366 bool dscp_option_changed = (options_.dscp != options.dscp); |
1509 | 1367 |
1510 // We retain all of the existing options, and apply the given ones | 1368 // We retain all of the existing options, and apply the given ones |
1511 // on top. This means there is no way to "clear" options such that | 1369 // on top. This means there is no way to "clear" options such that |
1512 // they go back to the engine default. | 1370 // they go back to the engine default. |
1513 options_.SetAll(options); | 1371 options_.SetAll(options); |
1514 | 1372 if (!engine()->ApplyOptions(options_)) { |
1515 if (send_ != SEND_NOTHING) { | 1373 LOG(LS_WARNING) << |
1516 if (!engine()->ApplyOptions(options_)) { | 1374 "Failed to apply engine options during channel SetOptions."; |
1517 LOG(LS_WARNING) << | 1375 return false; |
1518 "Failed to apply engine options during channel SetOptions."; | |
1519 return false; | |
1520 } | |
1521 } | 1376 } |
1522 | 1377 |
1523 if (dscp_option_changed) { | 1378 if (dscp_option_changed) { |
1524 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; | 1379 rtc::DiffServCodePoint dscp = rtc::DSCP_DEFAULT; |
1525 if (options_.dscp.value_or(false)) | 1380 if (options_.dscp.value_or(false)) { |
1526 dscp = kAudioDscpValue; | 1381 dscp = kAudioDscpValue; |
| 1382 } |
1527 if (MediaChannel::SetDscp(dscp) != 0) { | 1383 if (MediaChannel::SetDscp(dscp) != 0) { |
1528 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; | 1384 LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel"; |
1529 } | 1385 } |
1530 } | 1386 } |
1531 | 1387 |
1532 // TODO(solenberg): Don't recreate unless options changed. | 1388 // TODO(solenberg): Don't recreate unless options changed. |
1533 for (auto& it : recv_streams_) { | 1389 for (auto& it : recv_streams_) { |
1534 it.second->RecreateAudioReceiveStream( | 1390 it.second->RecreateAudioReceiveStream( |
1535 options_.combined_audio_video_bwe.value_or(false)); | 1391 options_.combined_audio_video_bwe.value_or(false)); |
1536 } | 1392 } |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1914 | 1770 |
1915 bool WebRtcVoiceMediaChannel::ResumeSend() { | 1771 bool WebRtcVoiceMediaChannel::ResumeSend() { |
1916 return ChangeSend(desired_send_); | 1772 return ChangeSend(desired_send_); |
1917 } | 1773 } |
1918 | 1774 |
1919 bool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) { | 1775 bool WebRtcVoiceMediaChannel::ChangeSend(SendFlags send) { |
1920 if (send_ == send) { | 1776 if (send_ == send) { |
1921 return true; | 1777 return true; |
1922 } | 1778 } |
1923 | 1779 |
1924 // Apply channel specific options. | 1780 // Apply channel specific options when channel is enabled for sending. |
1925 if (send == SEND_MICROPHONE) { | 1781 if (send == SEND_MICROPHONE) { |
1926 engine()->ApplyOptions(options_); | 1782 engine()->ApplyOptions(options_); |
1927 } | 1783 } |
1928 | 1784 |
1929 // Change the settings on each send channel. | 1785 // Change the settings on each send channel. |
1930 for (const auto& ch : send_streams_) { | 1786 for (const auto& ch : send_streams_) { |
1931 if (!ChangeSend(ch.second->channel(), send)) { | 1787 if (!ChangeSend(ch.second->channel(), send)) { |
1932 return false; | 1788 return false; |
1933 } | 1789 } |
1934 } | 1790 } |
1935 | 1791 |
1936 // Clear up the options after stopping sending. Since we may previously have | |
1937 // applied the channel specific options, now apply the original options stored | |
1938 // in WebRtcVoiceEngine. | |
1939 if (send == SEND_NOTHING) { | |
1940 engine()->ApplyOptions(engine()->GetOptions()); | |
1941 } | |
1942 | |
1943 send_ = send; | 1792 send_ = send; |
1944 return true; | 1793 return true; |
1945 } | 1794 } |
1946 | 1795 |
1947 bool WebRtcVoiceMediaChannel::ChangeSend(int channel, SendFlags send) { | 1796 bool WebRtcVoiceMediaChannel::ChangeSend(int channel, SendFlags send) { |
1948 if (send == SEND_MICROPHONE) { | 1797 if (send == SEND_MICROPHONE) { |
1949 if (engine()->voe()->base()->StartSend(channel) == -1) { | 1798 if (engine()->voe()->base()->StartSend(channel) == -1) { |
1950 LOG_RTCERR1(StartSend, channel); | 1799 LOG_RTCERR1(StartSend, channel); |
1951 return false; | 1800 return false; |
1952 } | 1801 } |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2636 } | 2485 } |
2637 } else { | 2486 } else { |
2638 LOG(LS_INFO) << "Stopping playout for channel #" << channel; | 2487 LOG(LS_INFO) << "Stopping playout for channel #" << channel; |
2639 engine()->voe()->base()->StopPlayout(channel); | 2488 engine()->voe()->base()->StopPlayout(channel); |
2640 } | 2489 } |
2641 return true; | 2490 return true; |
2642 } | 2491 } |
2643 } // namespace cricket | 2492 } // namespace cricket |
2644 | 2493 |
2645 #endif // HAVE_WEBRTC_VOICE | 2494 #endif // HAVE_WEBRTC_VOICE |
OLD | NEW |