diff --git a/webrtc/api/localaudiosource.cc b/webrtc/api/localaudiosource.cc index 9da9fd2612..53c426e011 100644 --- a/webrtc/api/localaudiosource.cc +++ b/webrtc/api/localaudiosource.cc @@ -49,6 +49,7 @@ void FromConstraints(const MediaConstraintsInterface::Constraints& constraints, options->experimental_ns}, {MediaConstraintsInterface::kIntelligibilityEnhancer, options->intelligibility_enhancer}, + {MediaConstraintsInterface::kLevelControl, options->level_control}, {MediaConstraintsInterface::kHighpassFilter, options->highpass_filter}, {MediaConstraintsInterface::kTypingNoiseDetection, options->typing_detection}, diff --git a/webrtc/api/mediaconstraintsinterface.cc b/webrtc/api/mediaconstraintsinterface.cc index 6a014a2b03..7ac7417669 100644 --- a/webrtc/api/mediaconstraintsinterface.cc +++ b/webrtc/api/mediaconstraintsinterface.cc @@ -48,6 +48,7 @@ const char MediaConstraintsInterface::kExperimentalNoiseSuppression[] = "googNoiseSuppression2"; const char MediaConstraintsInterface::kIntelligibilityEnhancer[] = "intelligibilityEnhancer"; +const char MediaConstraintsInterface::kLevelControl[] = "levelControl"; const char MediaConstraintsInterface::kHighpassFilter[] = "googHighpassFilter"; const char MediaConstraintsInterface::kTypingNoiseDetection[] = diff --git a/webrtc/api/mediaconstraintsinterface.h b/webrtc/api/mediaconstraintsinterface.h index 13560dd35b..d6fd6beb95 100644 --- a/webrtc/api/mediaconstraintsinterface.h +++ b/webrtc/api/mediaconstraintsinterface.h @@ -74,6 +74,7 @@ class MediaConstraintsInterface { static const char kNoiseSuppression[]; // googNoiseSuppression static const char kExperimentalNoiseSuppression[]; // googNoiseSuppression2 static const char kIntelligibilityEnhancer[]; // intelligibilityEnhancer + static const char kLevelControl[]; // levelControl static const char kHighpassFilter[]; // googHighpassFilter static const char kTypingNoiseDetection[]; // googTypingNoiseDetection static const char kAudioMirroring[]; // googAudioMirroring diff --git a/webrtc/media/base/mediachannel.h b/webrtc/media/base/mediachannel.h index bb30798249..5a4124ac11 100644 --- a/webrtc/media/base/mediachannel.h +++ b/webrtc/media/base/mediachannel.h @@ -158,6 +158,7 @@ struct AudioOptions { SetFrom(&delay_agnostic_aec, change.delay_agnostic_aec); SetFrom(&experimental_ns, change.experimental_ns); SetFrom(&intelligibility_enhancer, change.intelligibility_enhancer); + SetFrom(&level_control, change.level_control); SetFrom(&tx_agc_target_dbov, change.tx_agc_target_dbov); SetFrom(&tx_agc_digital_compression_gain, change.tx_agc_digital_compression_gain); @@ -169,27 +170,30 @@ struct AudioOptions { bool operator==(const AudioOptions& o) const { return echo_cancellation == o.echo_cancellation && - auto_gain_control == o.auto_gain_control && - noise_suppression == o.noise_suppression && - highpass_filter == o.highpass_filter && - stereo_swapping == o.stereo_swapping && - audio_jitter_buffer_max_packets == o.audio_jitter_buffer_max_packets && - audio_jitter_buffer_fast_accelerate == - o.audio_jitter_buffer_fast_accelerate && - typing_detection == o.typing_detection && - aecm_generate_comfort_noise == o.aecm_generate_comfort_noise && - experimental_agc == o.experimental_agc && - extended_filter_aec == o.extended_filter_aec && - delay_agnostic_aec == o.delay_agnostic_aec && - experimental_ns == o.experimental_ns && - intelligibility_enhancer == o.intelligibility_enhancer && - adjust_agc_delta == o.adjust_agc_delta && - tx_agc_target_dbov == o.tx_agc_target_dbov && - tx_agc_digital_compression_gain == o.tx_agc_digital_compression_gain && - tx_agc_limiter == o.tx_agc_limiter && - recording_sample_rate == o.recording_sample_rate && - playout_sample_rate == o.playout_sample_rate && - combined_audio_video_bwe == o.combined_audio_video_bwe; + auto_gain_control == o.auto_gain_control && + noise_suppression == o.noise_suppression && + highpass_filter == o.highpass_filter && + stereo_swapping == o.stereo_swapping && + audio_jitter_buffer_max_packets == + o.audio_jitter_buffer_max_packets && + audio_jitter_buffer_fast_accelerate == + o.audio_jitter_buffer_fast_accelerate && + typing_detection == o.typing_detection && + aecm_generate_comfort_noise == o.aecm_generate_comfort_noise && + experimental_agc == o.experimental_agc && + extended_filter_aec == o.extended_filter_aec && + delay_agnostic_aec == o.delay_agnostic_aec && + experimental_ns == o.experimental_ns && + intelligibility_enhancer == o.intelligibility_enhancer && + level_control == o.level_control && + adjust_agc_delta == o.adjust_agc_delta && + tx_agc_target_dbov == o.tx_agc_target_dbov && + tx_agc_digital_compression_gain == + o.tx_agc_digital_compression_gain && + tx_agc_limiter == o.tx_agc_limiter && + recording_sample_rate == o.recording_sample_rate && + playout_sample_rate == o.playout_sample_rate && + combined_audio_video_bwe == o.combined_audio_video_bwe; } bool operator!=(const AudioOptions& o) const { return !(*this == o); } @@ -213,6 +217,7 @@ struct AudioOptions { ost << ToStringIfSet("delay_agnostic_aec", delay_agnostic_aec); ost << ToStringIfSet("experimental_ns", experimental_ns); ost << ToStringIfSet("intelligibility_enhancer", intelligibility_enhancer); + ost << ToStringIfSet("level_control", level_control); ost << ToStringIfSet("tx_agc_target_dbov", tx_agc_target_dbov); ost << ToStringIfSet("tx_agc_digital_compression_gain", tx_agc_digital_compression_gain); @@ -248,6 +253,7 @@ struct AudioOptions { rtc::Optional delay_agnostic_aec; rtc::Optional experimental_ns; rtc::Optional intelligibility_enhancer; + rtc::Optional level_control; // Note that tx_agc_* only applies to non-experimental AGC. rtc::Optional tx_agc_target_dbov; rtc::Optional tx_agc_digital_compression_gain; diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc index d329270ce5..469098a322 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -559,6 +559,7 @@ WebRtcVoiceEngine::WebRtcVoiceEngine( options.delay_agnostic_aec = rtc::Optional(false); options.experimental_ns = rtc::Optional(false); options.intelligibility_enhancer = rtc::Optional(false); + options.level_control = rtc::Optional(false); bool error = ApplyOptions(options); RTC_DCHECK(error); } @@ -682,9 +683,29 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { } } + // Use optional to avoid uneccessary calls to BuiltInAGCIsAvailable while + // complying with the unittest requirements of only 1 call per test. + rtc::Optional built_in_agc_avaliable; + if (options.level_control) { + if (!built_in_agc_avaliable) { + built_in_agc_avaliable = + rtc::Optional(adm()->BuiltInAGCIsAvailable()); + } + RTC_DCHECK(built_in_agc_avaliable); + if (*built_in_agc_avaliable) { + // Disable internal software level control if built-in AGC is enabled, + // i.e., replace the software AGC with the built-in AGC. + options.level_control = rtc::Optional(false); + } + } + if (options.auto_gain_control) { - const bool built_in_agc = adm()->BuiltInAGCIsAvailable(); - if (built_in_agc) { + if (!built_in_agc_avaliable) { + built_in_agc_avaliable = + rtc::Optional(adm()->BuiltInAGCIsAvailable()); + } + RTC_DCHECK(built_in_agc_avaliable); + if (*built_in_agc_avaliable) { if (adm()->EnableBuiltInAGC(*options.auto_gain_control) == 0 && *options.auto_gain_control) { // Disable internal software AGC if built-in AGC is enabled, @@ -841,6 +862,16 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { new webrtc::Intelligibility(*intelligibility_enhancer_)); } + if (options.level_control) { + level_control_ = options.level_control; + } + + LOG(LS_INFO) << "Level control: " + << (!!level_control_ ? *level_control_ : -1); + if (level_control_) { + config.Set(new webrtc::LevelControl(*level_control_)); + } + // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine // returns NULL on audio_processing(). webrtc::AudioProcessing* audioproc = voe_wrapper_->base()->audio_processing(); diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h index 16da9ef29e..64e0f5b185 100644 --- a/webrtc/media/engine/webrtcvoiceengine.h +++ b/webrtc/media/engine/webrtcvoiceengine.h @@ -138,14 +138,16 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback { bool is_dumping_aec_ = false; webrtc::AgcConfig default_agc_config_; - // Cache received extended_filter_aec, delay_agnostic_aec, experimental_ns and - // intelligibility_enhancer values, and apply them in case they are missing - // in the audio options. We need to do this because SetExtraOptions() will - // revert to defaults for options which are not provided. + // Cache received extended_filter_aec, delay_agnostic_aec, experimental_ns + // level controller, and intelligibility_enhancer values, and apply them + // in case they are missing in the audio options. We need to do this because + // SetExtraOptions() will revert to defaults for options which are not + // provided. rtc::Optional extended_filter_aec_; rtc::Optional delay_agnostic_aec_; rtc::Optional experimental_ns_; rtc::Optional intelligibility_enhancer_; + rtc::Optional level_control_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceEngine); };